Skip to content

Instantly share code, notes, and snippets.

@jsuchal
Forked from franckverrot/example.rb
Last active August 29, 2015 14:00
Show Gist options
  • Save jsuchal/2eb5eefe7b122066e966 to your computer and use it in GitHub Desktop.
Save jsuchal/2eb5eefe7b122066e966 to your computer and use it in GitHub Desktop.
class InviteController < ApplicationController
# The controller's responsibility is to build an object graph
# that will do the hard work.
def accept
scenario = InvitationScenario.new
scenario.accept_invite_token_for_user(current_user, params[:token], bus.when(
inviting_succeeded: ->(user) { redirect_to invite.item, notice: "Welcome!" },
inviting_failed: ->(error) { redirect_to '/', alert: "Oopsy!" }
))
end
def bus
Bus.new # https://github.com/minio-sk/bus - hardcode or inject (constructor/setter)
end
end
# This class supplements "AcceptInvite". It will tell the data repository
# to find some data, and based on the outcome of the retrieval, will do some
# work and then tell its collaborator to act.
# This is where the business logic would go
class InvitationScenario
def initialize(repository = InviteRepository.new)
@repository = repository
end
def accept_invite_token_for_user(current_user, token_str, collaborator, bus = nil)
@repository.find_user_by_token(current_user, token_str, bus || Bus.new.when(
user_found: ->(user_record) { collaborator.inviting_succeeded(user_record) }
user_not_found: ->(exception) { collaborator.inviting_failed(exception) }
find_user_failed: ->(exception) { collaborator.inviting_failed(exception) }
))
end
end
# This class tells its collaborator about the outcome of
# the data retrieval (it encapsulates ActiveRecord, which shouldn't
# leak in the controller)
class InviteRepository
def find_user_by_token(current_user, token_str, collaborator)
begin
user = current_user.invites.find_by_token!(token_str)
collaborator.user_found(user)
rescue ActiveRecord::RecordNotFound => exception
collaborator.user_not_found(exception)
rescue => e
collaborator.find_user_failed(exception)
end
end
end
# The models looks like
class Invite < ActiveRecord::Base; end
class User < ActiveRecord::Base
has_many :invites
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment