module SnFoil::Context

ActiveSupport::Concern for adding SnFoil Context functionality

@author Matthew Howes

@since 0.1.0

Constants

VERSION

Public Instance Methods

action(name, with: nil, &block) click to toggle source
# File lib/snfoil/context.rb, line 37
def action(name, with: nil, &block)
  raise SnFoil::Context::Error, "action #{name} already defined for #{self.name}" if (@snfoil_actions ||= []).include?(name)

  @snfoil_actions << name
  define_workflow(name)
  define_action_primary(name, with, block)
end
interval(name) click to toggle source
# File lib/snfoil/context.rb, line 45
def interval(name)
  define_singleton_methods(name)
  define_instance_methods(name)
end
intervals(*names) click to toggle source
# File lib/snfoil/context.rb, line 50
def intervals(*names)
  names.each { |name| interval(name) }
end
run_interval(interval, **options) click to toggle source
# File lib/snfoil/context.rb, line 55
def run_interval(interval, **options)
  hooks = self.class.instance_variable_get("@snfoil_#{interval}_hooks") || []
  options = hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
  send(interval, **options)
end

Private Instance Methods

define_action_primary(name, method, block) click to toggle source
# File lib/snfoil/context.rb, line 74
def define_action_primary(name, method, block) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
  define_method(name) do |*_args, **options| # rubocop:disable Metrics/MethodLength
    options[:action] ||= name.to_sym

    options = run_interval(format('setup_%s', name), **options)
    authorize(name, **options) if respond_to?(:authorize)

    options = run_interval(format('before_%s', name), **options)
    authorize(name, **options) if respond_to?(:authorize)

    options = if run_action_primary(method, block, **options)
                run_interval(format('after_%s_success', name), **options)
              else
                run_interval(format('after_%s_failure', name), **options)
              end
    run_interval(format('after_%s', name), **options)
  end
end
define_instance_methods(method_name) click to toggle source
# File lib/snfoil/context.rb, line 107
def define_instance_methods(method_name)
  define_method(method_name) do |**options|
    options
  end
end
define_singleton_methods(method_name) click to toggle source
# File lib/snfoil/context.rb, line 93
def define_singleton_methods(method_name)
  singleton_var = "snfoil_#{method_name}_hooks"
  instance_variable_set("@#{singleton_var}", [])
  define_singleton_method(singleton_var) { instance_variable_get("@#{singleton_var}") }
  define_singleton_method(method_name) do |method = nil, **options, &block|
    raise SnFoil::Context::ArgumentError, "\##{method_name} requires either a method name or a block" if method.nil? && block.nil?

    instance_variable_get("@#{singleton_var}") << { method: method,
                                                    block: block,
                                                    if: options[:if],
                                                    unless: options[:unless] }
  end
end
define_workflow(name) click to toggle source
# File lib/snfoil/context.rb, line 66
def define_workflow(name)
  interval format('setup_%s', name)
  interval format('before_%s', name)
  interval format('after_%s_success', name)
  interval format('after_%s_failure', name)
  interval format('after_%s', name)
end
run_action_primary(method, block, **options) click to toggle source
# File lib/snfoil/context.rb, line 114
def run_action_primary(method, block, **options)
  return send(method, **options) if method

  instance_exec(**options, &block)
end