diff --git a/lib/mutations/command.rb b/lib/mutations/command.rb index c03cbbf..51fefe9 100644 --- a/lib/mutations/command.rb +++ b/lib/mutations/command.rb @@ -109,8 +109,16 @@ def execute # add_error("colors.foreground", :not_a_color) # => to create errors = {colors: {foreground: :not_a_color}} # or, supply a custom message: # add_error("name", :too_short, "The name 'blahblahblah' is too short!") - def add_error(key, kind, message = nil) - raise ArgumentError.new("Invalid kind") unless kind.is_a?(Symbol) + # or, supply an existing Mutations::ErrorHash or Mutations::ErrorArray: + # add_error("name", Mutations::ErrorArray.new([...])) + def add_error(key, error, message = nil) + if error.is_a? Symbol + error = ErrorAtom.new(key, error, message: message) + elsif error.is_a?(Mutations::ErrorAtom) || error.is_a?(Mutations::ErrorArray) || error.is_a?(Mutations::ErrorHash) + + else + raise ArgumentError.new("Invalid error of kind #{error.class}") + end @errors ||= ErrorHash.new @errors.tap do |errs| @@ -119,7 +127,7 @@ def add_error(key, kind, message = nil) inner = path.inject(errs) do |cur_errors,part| cur_errors[part.to_sym] ||= ErrorHash.new end - inner[last] = ErrorAtom.new(key, kind, :message => message) + inner[last] = error end end diff --git a/spec/command_spec.rb b/spec/command_spec.rb index 633abcc..9b656be 100644 --- a/spec/command_spec.rb +++ b/spec/command_spec.rb @@ -59,12 +59,12 @@ it "should execute custom validate method during run" do outcome = SimpleCommand.run(:name => "JohnLong", :email => "xxxx") - + assert !outcome.success? assert_nil outcome.result assert_equal :invalid, outcome.errors.symbolic[:email] end - + it "should execute custom validate method only if regular validations succeed" do outcome = SimpleCommand.validate(:name => "JohnTooLong", :email => "xxxx") @@ -217,6 +217,67 @@ def execute end end + describe "NestedErrorHashCommand" do + class NestedErrorHashCommand < Mutations::Command + required do + array :services do + model :object, class: Hash + end + end + + def validate + service_errors = Mutations::ErrorHash.new + service_errors[:name] = Mutations::ErrorAtom.new(:name, :exists, message: "Service with name foo already exists") + + add_error("services.foo", service_errors) + end + end + + it "should let you add sub-mutation errors" do + outcome = NestedErrorHashCommand.run('services' => [ + { 'name' => "foo" }, + ]) + + assert !outcome.success? + assert_nil outcome.result + assert_equal({'services' => { 'foo' => { 'name' => :exists }}}, outcome.errors.symbolic) + end + end + + describe "NestedErrorArrayCommand" do + class NestedErrorArrayCommand < Mutations::Command + required do + array :links do + hash do + required do + string :name + end + end + end + end + + def validate + links_errors = Mutations::ErrorArray.new + links_errors << Mutations::ErrorAtom.new(:name, :not_found, message: "Link foo not found") + links_errors << Mutations::ErrorAtom.new(:name, :not_found, message: "Link bar not found") + + add_error("links", links_errors) + end + end + + it "should let you add sub-mutation errors" do + outcome = NestedErrorArrayCommand.run('links' => [ + { 'name' => "foo" }, + { 'name' => "bar" }, + ]) + + assert !outcome.success? + assert_nil outcome.result + assert_equal({'links' => [:not_found, :not_found]}, outcome.errors.symbolic) + assert_equal({'links' => ["Link foo not found", "Link bar not found"]}, outcome.errors.message) + end + end + describe "PresentCommand" do class PresentCommand < Mutations::Command