Skip to content

Instantly share code, notes, and snippets.

@smostovoy
Created November 25, 2019 10:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smostovoy/72fdee4955a89cf494e52aae8370667f to your computer and use it in GitHub Desktop.
Save smostovoy/72fdee4955a89cf494e52aae8370667f to your computer and use it in GitHub Desktop.
# frozen_string_literal: true
class BaseOperation
# DSL method to create wrapped operations with a transaction
# Creates both #some_action and #some_action! method versions
# A 'bang' version of a method does not process validation exceptions (to bubble up)
#
# All block arguments are converted to a method params
#
# Examples:
#
# class SomeOperation < BaseOperation
# action(:create) do |some_attr|
# # User.create
# # generate password
# # send email
# end
#
# action(:destroy) do
# #some stuff
# end
# end
#
# Usage:
# SomeOperation.new.create(some_attr)
# SomeOperation.new.create!(some_attr)
def self.action(name, options = {}, &block)
define_method("#{name}_unwrapped", &block)
define_method(name) do |*arg|
perform(name, options, *arg)
end
define_method("#{name}!") do |*arg|
perform!(name, options, *arg)
end
end
protected
def error(message)
{ success: false, error: message }
end
def success(result)
{ success: true, result: result }
end
private
def self.caught_exceptions
[ActiveRecord::RecordInvalid]
end
def perform(action, options, *args)
result = perform!(action, options, *args)
# If operation created a custom result, return it
return result if result.is_a?(Hash) && !result[:success].nil?
success(result)
rescue *self.class.caught_exceptions => exception
on_error(action, exception)
end
def perform!(action, options, *args)
return public_send("#{action}_unwrapped", *args) if options[:transaction] == false
ActiveRecord::Base.transaction do
public_send("#{action}_unwrapped", *args)
end
end
def on_error(action, exception)
Rails.logger.debug("#{self.class.name}##{action} error: #{exception.message}")
error(exception.message)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment