Skip to content

Instantly share code, notes, and snippets.

@alebian
Last active September 26, 2017 18:09
Show Gist options
  • Save alebian/553c0d904aee6633f76b07f0672b15ce to your computer and use it in GitHub Desktop.
Save alebian/553c0d904aee6633f76b07f0672b15ce to your computer and use it in GitHub Desktop.
Mixin for Interactor objects. Dependencies: interactor, dry-types
require 'interactor'
require 'dry-types'
# Author:: Alejandro Bezdjian
# Copyright:: Copyright (c) 2017 Alejandro Bezdjian
# License:: Apache 2.0
class InteractorMixin
include Interactor
module Types
# Check out http://dry-rb.org/gems/dry-types
include Dry::Types.module
end
# Used to access attributes with bare words
def method_missing(method, *args, &block)
return context.send(method) if context.respond_to?(method)
super
end
def respond_to_missing?(method_name, include_private = false)
context.respond_to?(method) || super
end
def param(name, options = {})
set_default!(name, options[:default])
check_type!(name, options[:type])
check_presence!(name, options[:required])
end
def set_default!(name, value)
context[name] = value if attribute(name).nil? && present?(value)
end
def check_type!(name, type)
fail!("Expected #{name} to be #{type.name}") if present?(type) && invalid_type?(type, name)
end
def check_presence!(name, required)
fail!("Expected #{name} to be present") if attribute(name).nil? && required
end
def present?(object)
return false if object.nil?
true
end
# Method to get value from Interactor's context
def attribute(name)
context.send(name)
end
# Params:
# * +type+ - A class or a Dry::Type is expected
def valid_type?(type, attribute_name)
return type.valid?(attribute(attribute_name)) if type.respond_to?(:valid?)
attribute(attribute_name).is_a?(type)
end
# Params:
# * +type+ - A Dry::Type is expected
def invalid_type?(type, attribute_name)
!valid_type?(type, attribute_name)
end
# Method to stop Interactor's execution in one step
def fail!(message)
context.error = message
context.fail!
end
# Method used to add the final result to the Interactor object
def result(something)
context.result = something
end
end
class TestInteractor < InteractorMixin
before do
param :param1, type: Types::String, required: true
param :param2, type: Types::Coercible::Float
param :param3, type: Pepe
end
def call
puts param1
puts param2
puts param3
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment