lib/lotus/interactor.rb in lotus-utils-0.4.3 vs lib/lotus/interactor.rb in lotus-utils-0.5.0
- old
+ new
@@ -1,6 +1,7 @@
require 'lotus/utils/basic_object'
+require 'lotus/utils/class_attribute'
require 'lotus/utils/hash'
module Lotus
# Lotus Interactor
#
@@ -26,10 +27,11 @@
#
# @since 0.3.5
# @api private
def initialize(payload = {})
@payload = _payload(payload)
+ @errors = []
@success = true
end
# Check if the current status is successful
#
@@ -56,13 +58,21 @@
# @see Lotus::Interactor::Result#error
# @see Lotus::Interactor#call
# @see Lotus::Interactor#error
# @see Lotus::Interactor#error!
def errors
- @payload.fetch(:_errors) { [] }
+ @errors.dup
end
+ # @since 0.5.0
+ # @api private
+ def add_error(*errors)
+ @errors << errors
+ @errors.flatten!
+ nil
+ end
+
# Returns the first errors collected during an operation
#
# @return [nil,String] the error, if present
#
# @since 0.3.5
@@ -120,10 +130,11 @@
def self.included(base)
super
base.class_eval do
prepend Interface
+ extend ClassMethods
end
end
# Interactor interface
#
@@ -144,12 +155,12 @@
# require 'lotus/interactor'
#
# class UpdateProfile
# include Lotus::Interactor
#
- # def initialize(person, params)
- # @person = person
+ # def initialize(user, params)
+ # @user = user
# @params = params
# end
#
# def call
# # ...
@@ -157,11 +168,10 @@
# end
def initialize(*args)
super
ensure
@__result = ::Lotus::Interactor::Result.new
- @_errors = []
end
# Triggers the operation and return a result.
#
# All the instance variables will be available in the result.
@@ -170,15 +180,16 @@
#
# @return [Lotus::Interactor::Result] the result of the operation
#
# @raise [NoMethodError] if this isn't implemented by the including class.
#
- # @example Instance variables in result payload
+ # @example Expose instance variables in result payload
# require 'lotus/interactor'
#
# class Signup
# include Lotus::Interactor
+ # expose :user, :params
#
# def initialize(params)
# @params = params
# @user = User.new(@params)
# @foo = 'bar'
@@ -192,17 +203,18 @@
# result = Signup.new(name: 'Luca').call
# result.success? # => true
#
# result.user # => #<User:0x007fa311105778 @id=1 @name="Luca">
# result.params # => { :name=>"Luca" }
- # result.foo # => "Bar"
+ # result.foo # => raises NoMethodError
#
# @example Failed precondition
# require 'lotus/interactor'
#
# class Signup
# include Lotus::Interactor
+ # expose :user
#
# def initialize(params)
# @params = params
# @user = User.new(@params)
# end
@@ -306,10 +318,11 @@
# @example
# require 'lotus/interactor'
#
# class CreateRecord
# include Lotus::Interactor
+ # expose :logger
#
# def initialize
# @logger = []
# end
#
@@ -339,11 +352,11 @@
# result.success? # => false
#
# result.errors # => ["Prepare data error", "Persist error"]
# result.logger # => [:prepare_data!, :persist!, :sync!]
def error(message)
- @_errors << message
+ @__result.add_error message
false
end
# Log an error AND interrupting the flow.
#
@@ -358,10 +371,11 @@
# @example
# require 'lotus/interactor'
#
# class CreateRecord
# include Lotus::Interactor
+ # expose :logger
#
# def initialize
# @logger = []
# end
#
@@ -415,22 +429,69 @@
end
# @since 0.3.5
# @api private
def _prepare!
- @__result.prepare!(_instance_variables)
+ @__result.prepare!(_exposures)
end
- # @since 0.3.5
+ # @since 0.5.0
# @api private
- def _instance_variables
+ def _exposures
Hash[].tap do |result|
- instance_variables.each do |iv|
- name = iv.to_s.sub(/\A@/, '')
- next if name.match(/\A__/)
-
- result[name.to_sym] = instance_variable_get(iv)
+ self.class.exposures.each do |name, ivar|
+ result[name] = instance_variable_get(ivar)
end
+ end
+ end
+ end
+
+ # @since 0.5.0
+ # @api private
+ module ClassMethods
+ # @since 0.5.0
+ # @api private
+ def self.extended(interactor)
+ interactor.class_eval do
+ include Utils::ClassAttribute
+
+ class_attribute :exposures
+ self.exposures = Utils::Hash.new
+ end
+ end
+
+ # Expose local instance variables into the returing value of <tt>#call</tt>
+ #
+ # @param instance_variable_names [Symbol,Array<Symbol>] one or more instance
+ # variable names
+ #
+ # @since 0.5.0
+ #
+ # @see Lotus::Interactor::Result
+ #
+ # @example Expose instance variable
+ #
+ # class Signup
+ # include Lotus::Interactor
+ # expose :user
+ #
+ # def initialize(params)
+ # @params = params
+ # @user = User.new(@params[:user])
+ # end
+ #
+ # def call
+ # # ...
+ # end
+ # end
+ #
+ # result = Signup.new(user: { name: "Luca" }).call
+ #
+ # result.user # => #<User:0x007fa85c58ccd8 @name="Luca">
+ # result.params # => NoMethodError
+ def expose(*instance_variable_names)
+ instance_variable_names.each do |name|
+ exposures[name] = "@#{ name }"
end
end
end
end