Skip to content

Instantly share code, notes, and snippets.

@cainlevy
Last active November 8, 2019 19:02
Show Gist options
  • Save cainlevy/0600c91c638acbf3573688ad5d3141d6 to your computer and use it in GitHub Desktop.
Save cainlevy/0600c91c638acbf3573688ad5d3141d6 to your computer and use it in GitHub Desktop.
Simple base class for service objects that implement 1) an initializer and 2) a perform method that returns a Promise
# Service objects are classes that inherit from this base and implement two instance methods:
# * initialize(*args, **params) => void
# * perform() => Promise
class ServiceBase
include ActiveModel::Validations
# invokes the service and returns a Promise
def self.perform(*args, **params)
klass = params.any? ? new(*args, **params) : new(*args)
klass.perform_in_transaction
end
# invokes the service. returns a value on success, and raises an exception on failure.
def self.perform!(*args, **params)
perform(*args, **params).unbox
end
# must be implemented by inheriting class to return a Promise
def perform
raise MethodNotImplemented
end
def perform_in_transaction
instrument do
transaction do
perform
end
end
end
private def instrument
# ... New Relic or Datadog or STATSD or what have you
end
private def transaction
result = nil
ActiveRecord::Base.transaction do
result = yield
result.rescue { raise ActiveRecord::Rollback }
end
result
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment