Created
December 13, 2012 16:41
-
-
Save jacortinas/4277777 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class InvitationRequest | |
extend ActiveModel::Naming | |
include ActiveModel::Conversion | |
include ActiveModel::Validations | |
include ActiveModel::Serializers::JSON | |
attr_reader :email, :url | |
attr_writer :clock, :invitation_class, :mailer | |
validates :email, presence: true | |
def self.for attributes | |
req = new attributes | |
req.fulfill if req.valid? && !req.fulfilled? | |
req | |
end | |
def initialize attributes = {} | |
@email = attributes[:email] | |
@url = attributes[:url] | |
@clock = Time | |
@invitation_class = Invitation | |
@mailer = InvitationMailer | |
end | |
def fulfill | |
@mailer.deliver_request_confirmation invitation | |
end | |
def fulfilled? | |
invitation.persisted? | |
end | |
def invitation | |
@invitation ||= find_invitation || create_invitation | |
end | |
def attributes | |
{ email: email, url: url, fulfilled?: fulfilled? } | |
end | |
def persisted? | |
false | |
end | |
private | |
def find_invitation | |
@invitation_class.find_by_email email | |
end | |
def create_invitation | |
@invitation_class.create email: email, url: url, requested_at: @clock.now.utc | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class InvitationRequestSerializer < ActiveModel::Serializer | |
attributes :email, :url, :fulfilled? | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
describe InvitationRequest do | |
context 'when fulfilling for some attributes' do | |
it 'does not fulfill the request if not valid' do | |
req = double(:invitation_request, valid?: false) | |
InvitationRequest.stub(:new).and_return req | |
req.should_not_receive :fulfill | |
InvitationRequest.for email: '[email protected]', url: 'test.com' | |
end | |
it 'does not fulfill the request if already fulfilled' do | |
req = double(:invitation_request, valid?: true, fulfilled?: true) | |
InvitationRequest.stub(:new).and_return req | |
req.should_not_receive :fulfill | |
InvitationRequest.for email: '[email protected]', url: 'test.com' | |
end | |
end | |
it 'requires an email' do | |
expect(InvitationRequest.new).to have(1).error_on :email | |
end | |
it 'sets the email from initializing attributes' do | |
req = InvitationRequest.new email: '[email protected]' | |
expect(req.email).to eq '[email protected]' | |
end | |
it 'sets the url from initializing attributes' do | |
req = InvitationRequest.new url: 'test.com' | |
expect(req.url).to eq 'test.com' | |
end | |
it 'deliver a confirmation when fulfilled' do | |
req = InvitationRequest.new | |
mailer = double(:mailer).as_null_object | |
req.mailer = mailer | |
req.stub(:invitation).and_return 'fake invite' | |
mailer.should_receive(:deliver_request_confirmation).with 'fake invite' | |
req.fulfill | |
end | |
it 'is fulfilled if an invitation has already been created' do | |
req = InvitationRequest.new | |
invitation = double :invitation, persisted?: true | |
req.stub(:invitation).and_return invitation | |
expect(req).to be_fulfilled | |
end | |
context 'when fulfilled' do | |
it 'finds an invitation' do | |
req = InvitationRequest.new email: '[email protected]' | |
cls = double :invitation_class | |
req.invitation_class = cls | |
cls.should_receive(:find_by_email).with('[email protected]').and_return 'an invitation' | |
expect(req.invitation).to eq 'an invitation' | |
end | |
end | |
context 'when not fulfilled' do | |
it 'creates an invitation' do | |
req = InvitationRequest.new email: '[email protected]', url: 'test.com' | |
cls = double :invitation_class | |
clock = double :time | |
clock.stub_chain('now.utc').and_return Time.new(1970, 1, 1) | |
cls.stub(:find_by_email).and_return nil | |
cls.should_receive(:create).with( | |
hash_including({ | |
email: '[email protected]', | |
url: 'test.com', | |
requested_at: Time.new(1970, 1, 1) | |
}) | |
).and_return 'an invitation' | |
req.invitation_class = cls | |
req.clock = clock | |
expect(req.invitation).to eq 'an invitation' | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class InvitationRequestsController < ApplicationController | |
respond_to :json, only: :create | |
def new | |
@invitation_request = InvitationRequest.new | |
end | |
def create | |
respond_with InvitationRequest.for(valid_params), location: root_url | |
end | |
private | |
def valid_params | |
params.fetch(:invitation_request).slice(:email, :url) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
describe InvitationRequestsController do | |
describe 'GET new' do | |
it 'assigns a new invitation request' do | |
get:new | |
expect(assigns(:invitation_request)).to be_instance_of InvitationRequest | |
end | |
it 'renders the new template' do | |
get :new | |
expect(response).to render_template 'new' | |
end | |
end | |
describe 'POST create' do | |
context 'when the invitation request has errors' do | |
it 'renders the errors as json' do | |
post :create, invitation_request: {}, format: :json | |
expect(response.body).to match /^{\"errors\":/ | |
end | |
end | |
context 'when the invitation request is valid' do | |
it 'renders the invitation request' do | |
req = InvitationRequest.new email: '[email protected]' | |
InvitationRequest.stub(:for).and_return req | |
post :create, invitation_request: { email: '[email protected]' }, format: :json | |
expect(response.body).to eq req.to_json | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment