module Olivander module Resources class CrudChain attr_accessor :controller def initialize(controller) @controller = controller end def links @links ||= { authorize_action: nil, before_load: nil, load_resource: nil, after_load: nil, authorize_resource: nil, before_assign: nil, assign: nil, after_assign: nil, update_if: nil, before_update: nil, update: nil, after_update: nil, update_success: nil, update_failure: nil, render_success: nil, render_failure: nil } end def on(chain_link, &block) raise "Invalid Link: #{chain_link}" unless links.keys.include?(chain_link) links[chain_link] = block self end def skip_load clear_keys(%i[before_load load_resource after_load]) self end def skip_assign clear_keys(%i[before_assign assign after_assign]) self end def skip_update update_if { false } self end def skip_render clear_keys(%i[render_success render_failure]) self end def execute execute_link_keys(%i[authorize_action before_load load_resource after_load authorize_resource before_assign assign after_assign]) success = perform_update # we may not do any update - in which case we assume success success = true if success.nil? execute_link_key(success ? :render_success : :render_failure) success end # def self.test # CrudChain.new('string') # .before_load { puts "we did a before load from within this action: #{self}" } # .before_update { puts "we are doing a before_update on a controller named: #{self.class.name}" } # .execute # end def clear_keys(keys) keys.each { |k| clear_key(k) } end def clear_keys_except(keys) (links.keys - keys).each { |k| clear_key(k) } end def clear_key(key) links[key] = nil end private def perform_update perform_update = execute_link_key(:update_if) perform_update = true if perform_update.nil? return false unless perform_update execute_link_key(:before_update) success = execute_link_key(:update) execute_link_key(:after_update) execute_link_key(success ? :update_success : :update_failure) success end def execute_link_keys(keys) keys.each do |k| execute_link_key(k) end end def execute_link_key(key) block = links[key] return if block.nil? @controller.instance_exec(&block) end def respond_to_missing?(method_name, _include_private = false) links.keys.include?(method_name.to_sym) end # syntax sugar to allow direct assignment of a chain link def method_missing(m, *args, &block) if respond_to_missing?(m) send(:on, m, &block) else super end end end end end