Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/her/model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
27 changes: 27 additions & 0 deletions lib/her/model/orm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ def save
@metadata = parsed_data[:metadata]
@response_errors = parsed_data[:errors]

populate_errors @response_errors if respond_to?(:populate_validation_errors)

return false if !response.success? || @response_errors.any?
if self.changed_attributes.present?
@previously_changed = self.changed_attributes.clone
Expand Down Expand Up @@ -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 respond_to?(: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
#
Expand Down Expand Up @@ -194,6 +215,12 @@ def build(attributes = {})
resource
end

# Enables populate validation errors using @response_errors
def populate_validation_errors
class_attribute :populate_validation_errors
self.populate_validation_errors = true
end

private
# @private
def blank_relation
Expand Down
16 changes: 16 additions & 0 deletions spec/model/orm_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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 => "[email protected]" }, :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
Expand All @@ -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 => "[email protected]")
@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
Expand Down