-
Notifications
You must be signed in to change notification settings - Fork 5
Home
This is a forked repository. Have a look at
humaneq’s hyperactiveresource wiki
for more information.
HyRes is aimed at Rails 2.3.X which does not have modular Validations (as Rails 3.0 does).
So for HyRes’s validations etc to work you must replace your copy of ActiveResource’s validations.rb with the (stripped down) code to follow.
For Use with Rails 3.0… stay tuned.
module ActiveResource
class RecordInvalid < ClientError #:nodoc:
attr_reader :record
def initialize(record)
@record = record
super("Validation failed: #{@record.errors.full_messages.join(", ")}")
end
end
class ResourceInvalid < ClientError #:nodoc:
end
# Module to support validation and errors with Active Resource objects. The module overrides
# Base#save to rescue ActiveResource::ResourceInvalid exceptions and parse the errors returned
# in the web service response. The module also adds an +errors+ collection that mimics the interface
# of the errors provided by ActiveRecord::Errors.
#
# ==== Example
#
# Consider a Person resource on the server requiring both a +first_name+ and a +last_name+ with a
# <tt>validates_presence_of :first_name, :last_name</tt> declaration in the model:
#
# person = Person.new(:first_name => "Jim", :last_name => "")
# person.save # => false (server returns an HTTP 422 status code and errors)
# person.valid? # => false
# person.errors.empty? # => false
# person.errors.count # => 1
# person.errors.full_messages # => ["Last name can't be empty"]
# person.errors.on(:last_name) # => "can't be empty"
# person.last_name = "Halpert"
# person.save # => true (and person is now saved to the remote service)
#
module Validations
def self.included(base) # :nodoc:
base.class_eval do
alias_method_chain :save, :validation
end
end
# Validate a resource and save (POST) it to the remote web service.
def save_with_validation(perform_validation = true)
# clear the remote validations so they don't interfere with the local
# ones. Otherwise we get an endless loop and can never change the
# fields so as to make the resource valid
@remote_errors = nil
if perform_validation && valid? || !perform_validation
save_without_validation
true
else
false
end
rescue ResourceInvalid => error
@remote_errors = error.response.body
errors.from_xml(@remote_errors)
false
end
# overload the Active Record valid? method to reload any remote errors we
# still have hanging around since the last time we touched the remote
# system
def valid?
super
errors.from_xml(@remote_errors, true) if defined?(@remote_errors) && @remote_errors
errors.empty?
end
end
end
There’s a TODO list on the README file – I’ll update those as I go.
There’s one known bug(that I know):
steps to reproduce:
Site < HyperactiveResource
self.site = ‘http://localhost:3000/’
endSite.create()
fails with a 500 internal server error (see backtrace at bottom) because the remote API receives: Parameters: {"site"=>"\n"}
So – creating a new thing with an empty set of attributes fails miserably.
Looking at ARes it encodes just the same xml as HyRes… but for some reason ARes never actually sends a create request for an empty object…
It looks like the issue is actually Hash::to_xml which can be shown thus:
>> my_hash = {}
=> {}
>> my_hash.to_xml
=> “<?xml version=\”1.0\" encoding=\“UTF-8\”?>\n\n\n"
The remote site interprets this as: Parameters: {"hash"=>"\n"}
and can’t interpret the “\n” back into a hash as it automatically tries to stringify_keys! (which, of course, a string doesn’t have). :P
so the workaround is to always make sure there is at least one field filled in… not so good if you need to get a valid id before entering stuff… but ok for most normal situations.
backtrace follows:
ActiveResource::ServerError: Failed with 500 Internal Server Error
from /usr/lib/ruby/gems/1.8/gems/activeresource-2.3.2/lib/active_resource/connection.rb:180:in `handle_response’
from /usr/lib/ruby/gems/1.8/gems/activeresource-2.3.2/lib/active_resource/connection.rb:151:in `request’
from /usr/lib/ruby/gems/1.8/gems/activeresource-2.3.2/lib/active_resource/connection.rb:134:in `post’
from /home/taryn/projects/partnerportal/vendor/plugins/hyperactiveresource/lib/hyperactive_resource.rb:340:in `create’
from /usr/lib/ruby/gems/1.8/gems/activeresource-2.3.2/lib/active_resource/base.rb:796:in `save_without_validation’
from /usr/lib/ruby/gems/1.8/gems/activeresource-2.3.2/lib/active_resource/validations.rb:43:in `save’
from /home/taryn/projects/partnerportal/vendor/plugins/hyperactiveresource/lib/hyperactive_resource.rb:209:in `save’
from /usr/lib/ruby/gems/1.8/gems/activeresource-2.3.2/lib/active_resource/base.rb:465:in `create’
from /usr/lib/ruby/gems/1.8/gems/activeresource-2.3.2/lib/active_resource/base.rb:465:in `tap’
from /usr/lib/ruby/gems/1.8/gems/activeresource-2.3.2/lib/active_resource/base.rb:465:in `create’
from (irb):1