Skip to content

Instantly share code, notes, and snippets.

@mattbeedle
Created September 5, 2014 21:24
Show Gist options
  • Save mattbeedle/436f619e78047ba5e9ea to your computer and use it in GitHub Desktop.
Save mattbeedle/436f619e78047ba5e9ea to your computer and use it in GitHub Desktop.
Alternative Rails architecture with mediators and runners
class API:V1::Companies
helpers do
def create_company_runner
CreateCompanyRunner.new(create_response, current_user, params[:company])
end
def create_response
CreateResponse.new(self)
end
end
resource :companies do
post { create_company_runner.run }
end
end
class CreateResponse < SimpleDelegator
def creation_successful(company)
present :company, company
end
def creation_failed(form)
error!({ errors: form.errors }, 422)
end
end
class CreateCompanyRunner
include ActiveSupport::Rescuable
rescue_from RecordInvalidException, with: :invalid
pattr_initialize :listener, :user, :attributes
def run
validate!
create!
rescue Exception => e
rescue_with_handler(e)
end
private
def form
@form ||= CompanyForm.new(attributes)
end
def validate!
raise RecordInvalidException.new(form) unless form.valid?
end
def create!
mediator.call
listener.created_successfully mediator.company
end
def mediator
@mediator ||= CreateCompanyMediator.new
end
def invalid(exception)
listener.creation_failed(exception.record)
end
end
class CreateCompanyMediator
def initialize(user, attributes)
@user = user
@attributes = attributes.merge(default_attributes)
end
def call
create!
lookup_details
end
def company
@company ||= Company.new(attributes)
end
private
attr_reader :user, :attributes
def create!
repository.save! company
end
def default_attributes
{ user_id: user.id }
end
def lookup_details
company_lookup_job.async.perform(company)
end
def company_lookup_job
@company_lookup_job ||= CompanyLookupJob.new
end
def repository
@repository ||= CompanyRepository.new
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment