From 6685ebea89c8caaec2c19ec1063dfb4c73c6464c Mon Sep 17 00:00:00 2001 From: Jimmy Ngu Date: Mon, 4 Aug 2014 13:17:22 +0800 Subject: [PATCH 1/5] errors populatable by @response_errors if formatted properly --- lib/her/model/orm.rb | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/lib/her/model/orm.rb b/lib/her/model/orm.rb index fa91b2df..a0fc97db 100644 --- a/lib/her/model/orm.rb +++ b/lib/her/model/orm.rb @@ -45,6 +45,8 @@ def save @metadata = parsed_data[:metadata] @response_errors = parsed_data[:errors] + populate_errors @response_errors if self.populate_validation_errors + return false if !response.success? || @response_errors.any? if self.changed_attributes.present? @previously_changed = self.changed_attributes.clone @@ -78,12 +80,31 @@ def destroy assign_attributes(self.class.parse(parsed_data[:data])) if parsed_data[:data].any? @metadata = parsed_data[:metadata] @response_errors = parsed_data[:errors] + + populate_errors @response_errors if self.populate_validation_errors + @destroyed = true end end self end + # Populate validation errors if @response_errors is formatted in this format + # + # { + # :email => ["can't be empty","is invalid"], + # :password => ["is too short"] + # } + # + def populate_errors(response_errors) + self.errors.clear + response_errors.each do |attribute,errors| + errors.each do |error| + self.errors.add(attribute,error) + end if errors.is_a? Array + end if response_errors.is_a? Hash + end + module ClassMethods # Create a new chainable scope # @@ -194,6 +215,12 @@ def build(attributes = {}) resource end + # Enables populate validation errors using @response_errors + def populate_validation_errors + cattr_accessor :populate_validation_errors + self.populate_validation_errors = true + end + private # @private def blank_relation From 8595e702f0c8eae5fbc81e7c864b3bd8165ed453 Mon Sep 17 00:00:00 2001 From: Jimmy Ngu Date: Mon, 4 Aug 2014 13:48:28 +0800 Subject: [PATCH 2/5] sanity check --- lib/her/model/orm.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/her/model/orm.rb b/lib/her/model/orm.rb index a0fc97db..a20b9e6b 100644 --- a/lib/her/model/orm.rb +++ b/lib/her/model/orm.rb @@ -45,7 +45,7 @@ def save @metadata = parsed_data[:metadata] @response_errors = parsed_data[:errors] - populate_errors @response_errors if self.populate_validation_errors + populate_errors @response_errors if respond_to?(:populate_validation_errors) return false if !response.success? || @response_errors.any? if self.changed_attributes.present? @@ -81,7 +81,7 @@ def destroy @metadata = parsed_data[:metadata] @response_errors = parsed_data[:errors] - populate_errors @response_errors if self.populate_validation_errors + populate_errors @response_errors if respond_to?(:populate_validation_errors) @destroyed = true end From 980ee5bc43ed440cfa2165771ce8a7f47fd09376 Mon Sep 17 00:00:00 2001 From: Jimmy Ngu Date: Mon, 4 Aug 2014 13:48:39 +0800 Subject: [PATCH 3/5] disabled by default --- lib/her/model.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/her/model.rb b/lib/her/model.rb index 9d08d0dc..e4e38aa8 100644 --- a/lib/her/model.rb +++ b/lib/her/model.rb @@ -67,6 +67,9 @@ module Model # Configure ActiveModel callbacks extend ActiveModel::Callbacks define_model_callbacks :create, :update, :save, :find, :destroy, :initialize + + # Enable population of validation errors using well-formed @response_errors + # populate_validation_errors end end end From 7eed9e110a819912142913d91e630f122dc78946 Mon Sep 17 00:00:00 2001 From: Jimmy Ngu Date: Mon, 4 Aug 2014 13:48:43 +0800 Subject: [PATCH 4/5] specs --- spec/model/orm_spec.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/spec/model/orm_spec.rb b/spec/model/orm_spec.rb index 5bf523a9..f04282e6 100644 --- a/spec/model/orm_spec.rb +++ b/spec/model/orm_spec.rb @@ -73,12 +73,18 @@ builder.adapter :test do |stub| stub.get("/users") { |env| [200, {}, { :data => [{ :id => 1, :name => "Tobias Fünke" }, { :id => 2, :name => "Lindsay Fünke" }], :metadata => { :total_pages => 10, :next_page => 2 }, :errors => ["Oh", "My", "God"] }.to_json] } stub.post("/users") { |env| [200, {}, { :data => { :name => "George Michael Bluth" }, :metadata => { :foo => "bar" }, :errors => ["Yes", "Sir"] }.to_json] } + stub.post("/user_with_validation_errors") { |env| [422, {}, { :data => { :name => "George Michael Bluth", :email => "george@micheal.com" }, :metadata => { :foo => "bar" }, :errors => {:name => ['already exists', 'too long'], :email => ['is invalid']} }.to_json] } end end spawn_model :User do uses_api api end + + spawn_model :UserWithValidationErrors do + uses_api api + populate_validation_errors + end end it "handles metadata on a collection" do @@ -100,6 +106,16 @@ @user = User.create(:name => "George Michael Bluth") @user.response_errors.should == ["Yes", "Sir"] end + + it "handles error data on a resource" do + @user = UserWithValidationErrors.create(:name => "George Michael Bluth", :email => "george@micheal.com") + @user.response_errors.should == {:name => ['already exists', 'too long'], :email => ['is invalid']} + + # ActiveSupport validations + @user.errors.messages.should == {:name => ['already exists', 'too long'], :email => ['is invalid']} + @user.errors.full_messages.should == ["Name already exists", "Name too long", "Email is invalid"] + end + end context "mapping data, metadata and error data in string keys to Ruby objects" do From 0ebe727e706dcff9d7ce711001699110badf6b0b Mon Sep 17 00:00:00 2001 From: Jimmy Ngu Date: Mon, 4 Aug 2014 14:10:16 +0800 Subject: [PATCH 5/5] use class_attribute for backwards compatibility --- lib/her/model/orm.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/her/model/orm.rb b/lib/her/model/orm.rb index a20b9e6b..9b3194f4 100644 --- a/lib/her/model/orm.rb +++ b/lib/her/model/orm.rb @@ -217,7 +217,7 @@ def build(attributes = {}) # Enables populate validation errors using @response_errors def populate_validation_errors - cattr_accessor :populate_validation_errors + class_attribute :populate_validation_errors self.populate_validation_errors = true end