Skip to content

Instantly share code, notes, and snippets.

@fuksito
Created August 10, 2021 07:34
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fuksito/c4469a163f9ebe2868094aa6262fa306 to your computer and use it in GitHub Desktop.
Save fuksito/c4469a163f9ebe2868094aa6262fa306 to your computer and use it in GitHub Desktop.
CallableService Concern for Rails
# Usually service classes have only one purpose and thus should have only one public method that triggers action
# This module simplifies the common approach:
#
# SomeService.new(a, b, c).call
#
# To:
#
# SomeService.call(a, b, c)
#
# Requirements for class:
#
# 1. Have instance method #call
# 2. include CallableService
#
# Use cases:
#
# 1. Can be used instead of Sidekiq worker when worker just delegates to service
# SomeService.delay.call(a, b, c)
#
# 2. Less code in specs when checking expectation that service was called
#
# expect(SomeService).to receive(:call).with(a, b, c)
#
# instead of:
#
# service = double(SomeService)
# expect(service).to receive(:call)
# expect(SomeService).to receive(:new).with(a,b,c).and_return(service)
#
# 3. Can be used in maps
#
# ['Check Up', 'Covid-19 Testing'].map(&StringFormatService)
#
# instead of
#
# ['Check Up', 'Covid-19 Testing'].map do |string|
# StringFormatService.new(string).call
# end
#
# 4. Can still be initiated with #new to debug inner state, like
#
# service = SomeService.new(a,b,c)
# service.send(:some_private_method)
#
module CallableService
extend ActiveSupport::Concern
module ClassMethods
def call(*args, &block)
new(*args, &block).call
end
def to_proc
public_method(:call).to_proc
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment