Created
November 25, 2019 10:30
-
-
Save smostovoy/72fdee4955a89cf494e52aae8370667f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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