diff options
Diffstat (limited to 'activeresource')
-rw-r--r-- | activeresource/examples/performance.rb | 70 | ||||
-rw-r--r-- | activeresource/lib/active_resource/base.rb | 39 | ||||
-rw-r--r-- | activeresource/lib/active_resource/connection.rb | 2 | ||||
-rw-r--r-- | activeresource/lib/active_resource/http_mock.rb | 14 | ||||
-rw-r--r-- | activeresource/lib/active_resource/observing.rb | 8 | ||||
-rw-r--r-- | activeresource/lib/active_resource/validations.rb | 10 | ||||
-rw-r--r-- | activeresource/lib/active_resource/version.rb | 2 | ||||
-rw-r--r-- | activeresource/test/cases/http_mock_test.rb | 2 | ||||
-rw-r--r-- | activeresource/test/connection_test.rb | 2 |
9 files changed, 120 insertions, 29 deletions
diff --git a/activeresource/examples/performance.rb b/activeresource/examples/performance.rb new file mode 100644 index 0000000000..e4df7a38a4 --- /dev/null +++ b/activeresource/examples/performance.rb @@ -0,0 +1,70 @@ +require 'rubygems' +require 'active_resource' +require 'benchmark' + +TIMES = (ENV['N'] || 10_000).to_i + +# deep nested resource +attrs = { + :id => 1, + :name => 'Luis', + :age => 21, + :friends => [ + { + :name => 'JK', + :age => 24, + :colors => ['red', 'green', 'blue'], + :brothers => [ + { + :name => 'Mateo', + :age => 35, + :children => [{ :name => 'Edith', :age => 5 }, { :name => 'Martha', :age => 4 }] + }, + { + :name => 'Felipe', + :age => 33, + :children => [{ :name => 'Bryan', :age => 1 }, { :name => 'Luke', :age => 0 }] + } + ] + }, + { + :name => 'Eduardo', + :age => 20, + :colors => [], + :brothers => [ + { + :name => 'Sebas', + :age => 23, + :children => [{ :name => 'Andres', :age => 0 }, { :name => 'Jorge', :age => 2 }] + }, + { + :name => 'Elsa', + :age => 19, + :children => [{ :name => 'Natacha', :age => 1 }] + }, + { + :name => 'Milena', + :age => 16, + :children => [] + } + ] + } + ] +} + +class Customer < ActiveResource::Base + self.site = "http://37s.sunrise.i:3000" +end + +module Nested + class Customer < ActiveResource::Base + self.site = "http://37s.sunrise.i:3000" + end +end + +Benchmark.bm(40) do |x| + x.report('Model.new (instantiation)') { TIMES.times { Customer.new } } + x.report('Nested::Model.new (instantiation)') { TIMES.times { Nested::Customer.new } } + x.report('Model.new (setting attributes)') { TIMES.times { Customer.new attrs } } + x.report('Nested::Model.new (setting attributes)') { TIMES.times { Nested::Customer.new attrs } } +end diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb index 160763779e..7f2a844723 100644 --- a/activeresource/lib/active_resource/base.rb +++ b/activeresource/lib/active_resource/base.rb @@ -1239,9 +1239,10 @@ module ActiveResource @attributes[key.to_s] = case value when Array - resource = find_or_create_resource_for_collection(key) + resource = nil value.map do |attrs| if attrs.is_a?(Hash) + resource ||= find_or_create_resource_for_collection(key) resource.new(attrs) else attrs.duplicable? ? attrs.dup : attrs @@ -1251,7 +1252,7 @@ module ActiveResource resource = find_or_create_resource_for(key) resource.new(value) else - value.dup rescue value + value.duplicable? ? value.dup : value end end self @@ -1367,36 +1368,44 @@ module ActiveResource end # Tries to find a resource in a non empty list of nested modules - # Raises a NameError if it was not found in any of the given nested modules - def find_resource_in_modules(resource_name, module_names) + # if it fails, then the resource is created + def find_or_create_resource_in_modules(resource_name, module_names) receiver = Object namespaces = module_names[0, module_names.size-1].map do |module_name| receiver = receiver.const_get(module_name) end const_args = RUBY_VERSION < "1.9" ? [resource_name] : [resource_name, false] if namespace = namespaces.reverse.detect { |ns| ns.const_defined?(*const_args) } - return namespace.const_get(*const_args) + namespace.const_get(*const_args) else - raise NameError + create_resource_for(resource_name) end end # Tries to find a resource for a given name; if it fails, then the resource is created def find_or_create_resource_for(name) resource_name = name.to_s.camelize - ancestors = self.class.name.split("::") - if ancestors.size > 1 - find_resource_in_modules(resource_name, ancestors) - else - self.class.const_get(resource_name) - end - rescue NameError + const_args = RUBY_VERSION < "1.9" ? [resource_name] : [resource_name, false] if self.class.const_defined?(*const_args) - resource = self.class.const_get(*const_args) + self.class.const_get(*const_args) else - resource = self.class.const_set(resource_name, Class.new(ActiveResource::Base)) + ancestors = self.class.name.split("::") + if ancestors.size > 1 + find_or_create_resource_in_modules(resource_name, ancestors) + else + if Object.const_defined?(*const_args) + Object.const_get(*const_args) + else + create_resource_for(resource_name) + end + end end + end + + # Create and return a class definition for a resource inside the current resource + def create_resource_for(resource_name) + resource = self.class.const_set(resource_name, Class.new(ActiveResource::Base)) resource.prefix = self.class.prefix resource.site = self.class.site resource diff --git a/activeresource/lib/active_resource/connection.rb b/activeresource/lib/active_resource/connection.rb index e286362f87..765575d866 100644 --- a/activeresource/lib/active_resource/connection.rb +++ b/activeresource/lib/active_resource/connection.rb @@ -278,7 +278,7 @@ module ActiveResource def legitimize_auth_type(auth_type) return :basic if auth_type.nil? auth_type = auth_type.to_sym - auth_type.among?(:basic, :digest) ? auth_type : :basic + auth_type.in?([:basic, :digest]) ? auth_type : :basic end end end diff --git a/activeresource/lib/active_resource/http_mock.rb b/activeresource/lib/active_resource/http_mock.rb index e085a05f6d..3bfd536b29 100644 --- a/activeresource/lib/active_resource/http_mock.rb +++ b/activeresource/lib/active_resource/http_mock.rb @@ -9,8 +9,8 @@ module ActiveResource # requests. # # To test your Active Resource model, you simply call the ActiveResource::HttpMock.respond_to - # method with an attached block. The block declares a set of URIs with expected input, and the output - # each request should return. The passed in block has any number of entries in the following generalized + # method with an attached block. The block declares a set of URIs with expected input, and the output + # each request should return. The passed in block has any number of entries in the following generalized # format: # # mock.http_method(path, request_headers = {}, body = nil, status = 200, response_headers = {}) @@ -29,7 +29,7 @@ module ActiveResource # <tt>request_headers</tt> listed above. # # In order for a mock to deliver its content, the incoming request must match by the <tt>http_method</tt>, - # +path+ and <tt>request_headers</tt>. If no match is found an InvalidRequestError exception + # +path+ and <tt>request_headers</tt>. If no match is found an +InvalidRequestError+ exception # will be raised showing you what request it could not find a response for and also what requests and response # pairs have been recorded so you can create a new mock for that request. # @@ -80,7 +80,7 @@ module ActiveResource class << self - # Returns an array of all request objects that have been sent to the mock. You can use this to check + # Returns an array of all request objects that have been sent to the mock. You can use this to check # if your model actually sent an HTTP request. # # ==== Example @@ -105,7 +105,7 @@ module ActiveResource end # Returns the list of requests and their mocked responses. Look up a - # response for a request using responses.assoc(request). + # response for a request using <tt>responses.assoc(request)</tt>. def responses @@responses ||= [] end @@ -299,6 +299,8 @@ module ActiveResource end end + # Returns true if code is 2xx, + # false otherwise. def success? code.in?(200..299) end @@ -311,6 +313,8 @@ module ActiveResource headers[key] = value end + # Returns true if the other is a Response with an equal body, equal message + # and equal headers. Otherwise it returns false. def ==(other) if (other.is_a?(Response)) other.body == body && other.message == message && other.headers == headers diff --git a/activeresource/lib/active_resource/observing.rb b/activeresource/lib/active_resource/observing.rb index 3c74d49c80..1bfceb8dc8 100644 --- a/activeresource/lib/active_resource/observing.rb +++ b/activeresource/lib/active_resource/observing.rb @@ -5,6 +5,14 @@ module ActiveResource included do %w( create save update destroy ).each do |method| + # def create_with_notifications(*args, &block) + # notify_observers(:before_create) + # if result = create_without_notifications(*args, &block) + # notify_observers(:after_create) + # end + # result + # end + # alias_method_chain(create, :notifications) class_eval(<<-EOS, __FILE__, __LINE__ + 1) def #{method}_with_notifications(*args, &block) notify_observers(:before_#{method}) diff --git a/activeresource/lib/active_resource/validations.rb b/activeresource/lib/active_resource/validations.rb index a373e53f11..ca265d053e 100644 --- a/activeresource/lib/active_resource/validations.rb +++ b/activeresource/lib/active_resource/validations.rb @@ -8,9 +8,9 @@ module ActiveResource # Active Resource validation is reported to and from this object, which is used by Base#save # to determine whether the object in a valid state to be saved. See usage example in Validations. class Errors < ActiveModel::Errors - # Grabs errors from an array of messages (like ActiveRecord::Validations) + # Grabs errors from an array of messages (like ActiveRecord::Validations). # The second parameter directs the errors cache to be cleared (default) - # or not (by passing true) + # or not (by passing true). def from_array(messages, save_cache = false) clear unless save_cache humanized_attributes = Hash[@base.attributes.keys.map { |attr_name| [attr_name.humanize, attr_name] }] @@ -73,7 +73,7 @@ module ActiveResource # 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 + # fields so as to make the resource valid. @remote_errors = nil if perform_validation && valid? || !perform_validation save_without_validation @@ -84,7 +84,7 @@ module ActiveResource rescue ResourceInvalid => error # cache the remote errors because every call to <tt>valid?</tt> clears # all errors. We must keep a copy to add these back after local - # validations + # validations. @remote_errors = error load_remote_errors(@remote_errors, true) false @@ -92,7 +92,7 @@ module ActiveResource # Loads the set of remote errors into the object's Errors based on the - # content-type of the error-block received + # content-type of the error-block received. def load_remote_errors(remote_errors, save_cache = false ) #:nodoc: case self.class.format when ActiveResource::Formats[:xml] diff --git a/activeresource/lib/active_resource/version.rb b/activeresource/lib/active_resource/version.rb index 82dcb5d575..f26e2312b9 100644 --- a/activeresource/lib/active_resource/version.rb +++ b/activeresource/lib/active_resource/version.rb @@ -3,7 +3,7 @@ module ActiveResource MAJOR = 3 MINOR = 1 TINY = 0 - PRE = "beta" + PRE = "beta1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.') end diff --git a/activeresource/test/cases/http_mock_test.rb b/activeresource/test/cases/http_mock_test.rb index dfb097315e..cd5155924a 100644 --- a/activeresource/test/cases/http_mock_test.rb +++ b/activeresource/test/cases/http_mock_test.rb @@ -193,7 +193,7 @@ class HttpMockTest < ActiveSupport::TestCase end def request(method, path, headers = {}, body = nil) - if method.among?(:put, :post) + if method.in?([:put, :post]) @http.send(method, path, body, headers) else @http.send(method, path, headers) diff --git a/activeresource/test/connection_test.rb b/activeresource/test/connection_test.rb index 6e79845aa0..7c36393cf2 100644 --- a/activeresource/test/connection_test.rb +++ b/activeresource/test/connection_test.rb @@ -50,7 +50,7 @@ class ConnectionTest < Test::Unit::TestCase # 404 is a missing resource. assert_response_raises ActiveResource::ResourceNotFound, 404 - # 405 is a missing not allowed error + # 405 is a method not allowed error assert_response_raises ActiveResource::MethodNotAllowed, 405 # 409 is an optimistic locking error |