Skip to content

Loading…

Allow extending ActiveResource connections by assigning custom ones #4421

Closed
wants to merge 1 commit into from

2 participants

@dim

...n classes.

APIs aren't always easy, sometimes they want you to do something very special, something there is no hook in ActiveResource::Connection for. Extending connections isn't very slick at the moment, it requires you to overload ActiveResource::Base.connection in your models or some dirty patching.

The solution above allows users to assign a connection class in their models, allowing a new dimension of API customisations. I could also think of opportunities for new gems, with Connection classes that use other HTTP libraries, e.g. activeresource-excon-connection, etc. These would then be applicable on a model-by-model basis.

dim

@tenderlove
Ruby on Rails member

Hi, can you send this pull request to master? Merging directly to stable branches is not a good idea, especially with new features such as this.

@dim

Hey, I couldn't run the tests on master. I'll try it again.

@tenderlove
Ruby on Rails member

If you're having troubles getting the tests to run on master, feel free to ask for help! :-D

@dim

Sure, here's what I'm getting:

~/Work/rails/activeresource$ bundle exec rake
~/Work/rails/activesupport/lib/active_support/test_case.rb:21:in `<class:TestCase>': undefined method `register_spec_type' for ActiveSupport::TestCase:Class (NoMethodError)

Will debug too.

@dim

So tests work with MRI 1.9.3, but fail with 1.9.2. I think register_spec_type is new in the stdlib, so it probably would be better to bundle the minitest gem.

@dim

Submitted #4428

@dim dim closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 12, 2012
  1. @dim
View
20 activeresource/lib/active_resource/base.rb
@@ -421,6 +421,24 @@ def site=(site)
end
end
+ # Gets the class used to establish connection.
+ def connection_class
+ if defined?(@connection_class) && @connection_class
+ @connection_class
+ elsif superclass != Object
+ superclass.connection_class
+ else
+ ActiveResource::Connection
+ end
+ end
+
+ # Sets the connection class for this model to the value in the +klass+ argument.
+ # The +klass+ should inherit from ActiveResource::Connection.
+ def connection_class=(klass)
+ @connection = nil
+ @connection_class = klass
+ end
+
# Gets the \proxy variable if a proxy is required
def proxy
# Not using superclass_delegating_reader. See +site+ for explanation
@@ -547,7 +565,7 @@ def ssl_options
# or not (defaults to <tt>false</tt>).
def connection(refresh = false)
if defined?(@connection) || superclass == Object
- @connection = Connection.new(site, format) if refresh || @connection.nil?
+ @connection = connection_class.new(site, format) if refresh || @connection.nil?
@connection.proxy = proxy if proxy
@connection.user = user if user
@connection.password = password if password
View
16 activeresource/test/cases/base_test.rb
@@ -7,6 +7,7 @@
require "fixtures/proxy"
require "fixtures/address"
require "fixtures/subscription_plan"
+require "fixtures/hierarchy"
require 'active_support/json'
require 'active_support/ordered_hash'
require 'active_support/core_ext/hash/conversions'
@@ -49,6 +50,21 @@ def test_site_variable_can_be_reset
assert_nil actor.site
end
+ def test_connection_class_assignable_and_inheritable
+ assert_same ActiveResource::Connection, RootResource.connection_class
+ assert_same ParentConnection, ParentResource.connection_class
+ assert_same ParentConnection, ChildResource.connection_class
+ end
+
+ def test_connection_class_changes_connection
+ assert_not_same ParentResource.connection, RootResource.connection
+ assert_same ChildResource.connection, ParentResource.connection
+
+ assert_instance_of ActiveResource::Connection, RootResource.connection
+ assert_instance_of ParentConnection, ParentResource.connection
+ assert_instance_of ParentConnection, ChildResource.connection
+ end
+
def test_proxy_accessor_accepts_uri_or_string_argument
proxy = URI.parse('http://localhost')
View
1 activeresource/test/fixtures/beast.rb
@@ -12,3 +12,4 @@ class Forum < BeastResource
class Topic < BeastResource
self.site += '/forums/:forum_id'
end
+
View
13 activeresource/test/fixtures/hierarchy.rb
@@ -0,0 +1,13 @@
+class ParentConnection < ActiveResource::Connection
+end
+
+class RootResource < ActiveResource::Base
+ self.site = 'http://api.example.com'
+end
+
+class ParentResource < RootResource
+ self.connection_class = ParentConnection
+end
+
+class ChildResource < ParentResource
+end
Something went wrong with that request. Please try again.