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