Service Objects
important
We’re currently making rapid changes to the product so our docs may be out of date. If you need help, please email yo@forem.com.
What are Service Objects
Service objects are Plain Old Ruby Objects (POROs) which encapsulate a whole business process/user interaction.
Our services are located in app/services
with the corresponding specs in
spec/services
. Their main interface is a class level method named call
, as
in the following example:
class ImportUsers
def self.call(arg1)
new(arg1).call
end
def initialize(arg1)
@arg1 = arg1
end
def call
# import code goes here
end
end
To distinguish services from models we often give them verb names vs noun names,
e.g. ImportUsers
instead of UserImporter
.
Generating Service Objects
To make our services more consistent we use a custom Rails generator. Some usage examples:
Generate a non-namespaced service without arguments
$ rails generate service DoTheThing
# app/services/do_the_thing.rb
class DoTheThing
def self.call
new.call
end
def call
end
end
# spec/services/do_the_thing_spec.rb
require "rails_helper"
RSpec.describe DoTheThing, type: :service do
pending "add some examples to (or delete) #{__FILE__}"
end
Generate a non-namespaced service with arguments:
$ rails generate service DoTheThing arg1 arg2
# app/services/do_the_thing.rb
class DoTheThing
def self.call(arg1, arg2)
new(arg1, arg2).call
end
def initialize(arg1, arg2)
@arg1 = arg1
@arg2 = arg2
end
def call
end
end
The generated spec is the same as above.
Generate a namespaced service with arguments
$ rails generate service things/dothem arg1 arg2
# app/services/things/do_them.rb
class Things::DoThem
def self.call(arg1, arg2)
new(arg1, arg2).call
end
def initialize(arg1, arg2)
@arg1 = arg1
@arg2 = arg2
end
def call
end
end
# spec/services/things/do_them_spec.rb
require "rails_helper"
RSpec.describe Things::DoThem, type: :service do
pending "add some examples to (or delete) #{__FILE__}"
end