Services
Role of Services
A Service is a specific business logic using data as input and generating data as output.
A Service can manipulate multiple models or collections of models.
A Service can call external services and reuse internal librairies.
Location
app/services/
- Should be suffix with
_service.rb
Usage
A service can be called anywhere: from a Controller, a Background Job, an other service.
Naming
A service should be called with a verb as first word. Example:
CreateCompanyWithMultipleEmployees
SendWeeklyReportToAdmins
CheckInvalidUsers
ConsolidateJobOffers
SendNotificationsForNewJobOffers
Don't hesitate to be very explicit in the name of the service.
Structure
- Expose a static
#execute
method - May be destructive
- May not be idempotent
Tips
- Wrap all database transactions in a
ActiveRecord::Base.transaction
block so any failure will rollback the database state.
Code
module Accounts
class CreateOrUpdateCompanyAccount < Service::Base
include LogNotifiers::HasNotifier
self.log_notifier_name = 'accounts'
def initialize(company_profile:, role:)
@company_profile = company_profile
@role = role
@predicate = user_is_valid?.and(company_profile_is_valid?)
@is_new_company_profile = @company_profile.new_record?
end
private
def user
@company_profile.user
end
def execute
skip_confirmation!
ActiveRecord::Base.transaction do
create_or_update_user!
handle_former_permissions!
set_role!
save_company!
::Credits::CreateAllocations.new(company_profile: @company_profile).execute
send_invitation if @is_new_company_profile
end
end
def user_is_valid?
Accounts::UserIsValid.new(user)
end
def company_profile_is_valid?
Accounts::CompanyProfileIsValid.new(@company_profile)
end
def skip_confirmation!
#
end
def create_or_update_user!
#
end
def handle_former_permissions!
#
end
def set_role!
#
end
def save_company!
#
end
def send_invitation
#
end
end
end