Permalink
Browse files

Initial release

  • Loading branch information...
0 parents commit 643d4fd07e86be5ca153356607af76ffd3849553 @dim dim committed Jan 12, 2012
@@ -0,0 +1 @@
+--colour
@@ -0,0 +1,2 @@
+source :rubygems
+gemspec
@@ -0,0 +1,48 @@
+PATH
+ remote: .
+ specs:
+ activeresource_connections (0.1.0)
+ activeresource (>= 3.1.0, < 3.3.0)
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ activemodel (3.1.3)
+ activesupport (= 3.1.3)
+ builder (~> 3.0.0)
+ i18n (~> 0.6)
+ activeresource (3.1.3)
+ activemodel (= 3.1.3)
+ activesupport (= 3.1.3)
+ activesupport (3.1.3)
+ multi_json (~> 1.0)
+ addressable (2.2.6)
+ builder (3.0.0)
+ crack (0.3.1)
+ diff-lcs (1.1.3)
+ i18n (0.6.0)
+ multi_json (1.0.4)
+ rake (0.9.2.2)
+ retryable (1.2.5)
+ rspec (2.8.0)
+ rspec-core (~> 2.8.0)
+ rspec-expectations (~> 2.8.0)
+ rspec-mocks (~> 2.8.0)
+ rspec-core (2.8.0)
+ rspec-expectations (2.8.0)
+ diff-lcs (~> 1.1.2)
+ rspec-mocks (2.8.0)
+ webmock (1.7.10)
+ addressable (~> 2.2, > 2.2.5)
+ crack (>= 0.1.7)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activeresource_connections!
+ bundler
+ rake
+ retryable
+ rspec
+ webmock
@@ -0,0 +1,41 @@
+ActiveResource Connections
+==========================
+
+Allow you to extend ActiveResource connections with your own customisations.
+Please see lib/active_resource/connections/retryable.rb for reference.
+
+Installation
+============
+
+Install as Gem:
+
+ gem install activeresource_connections
+
+Or, add to your Gemfile:
+
+ # Gemfile
+ gem "activeresource_connections"
+
+
+Examples
+========
+
+ # Gemfile
+ gem 'retryable'
+
+ # app/models/user.rb
+ class User < ActiveResource::Base
+ self.connection_class = ActiveResource::Connections::Retryable
+ end
+
+ # app/models/manager.rb
+ class Manager < User
+ end
+
+ p Manager.connection # => #<ActiveResource::Connections::Retryable ...>
+
+
+Footnote
+========
+
+Copyright (c) 2012 Black Square Media Ltd, released under the MIT license
@@ -0,0 +1,7 @@
+#!/usr/bin/env rake
+require 'rake'
+require 'rspec/mocks/version'
+require 'rspec/core/rake_task'
+
+RSpec::Core::RakeTask.new(:spec)
+task :default => :spec
Binary file not shown.
@@ -0,0 +1,25 @@
+# -*- encoding: utf-8 -*-
+Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.required_ruby_version = '>= 1.9.0'
+ s.required_rubygems_version = ">= 1.3.6"
+
+ s.name = "activeresource_connections"
+ s.summary = "Custom connections for ActiveResource models"
+ s.description = "Extend your ActiveResource model's connections"
+ s.version = '0.1.0'
+
+ s.authors = ["Dimitrij Denissenko"]
+ s.email = "dimitrij@blacksquaremedia.com"
+ s.homepage = "https://github.com/bsm/activeresource_connections"
+
+ s.files = Dir['lib/**/*']
+
+ s.add_dependency "activeresource", ">= 3.1.0", "< 3.3.0"
+
+ s.add_development_dependency "rake"
+ s.add_development_dependency "bundler"
+ s.add_development_dependency "rspec"
+ s.add_development_dependency "retryable"
+ s.add_development_dependency "webmock"
+end
@@ -0,0 +1,11 @@
+require 'active_resource'
+
+module ActiveResource::Connections
+ autoload :Retryable, 'active_resource/connections/retryable'
+ autoload :CoreExt, 'active_resource/connections/core_ext'
+
+ unless ActiveResource::Base.respond_to?(:connection_class)
+ ActiveResource::Base.send :include, CoreExt
+ end
+end
+
@@ -0,0 +1,45 @@
+module ActiveResource::Connections::CoreExt
+ extend ActiveSupport::Concern
+
+ included do
+
+ # @overload
+ def self.connection(refresh = false)
+ if defined?(@connection) || superclass == Object
+ @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
+ @connection.auth_type = auth_type if auth_type
+ @connection.timeout = timeout if timeout
+ @connection.ssl_options = ssl_options if ssl_options
+ @connection
+ else
+ superclass.connection
+ end
+ end
+
+ end
+
+ module ClassMethods
+
+ # 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
+
+ end
+end
@@ -0,0 +1,34 @@
+require 'active_resource/connections'
+begin
+ require 'retryable'
+rescue LoadError
+ warn "Unable to find `retryable`. Please add `gem 'retryable'` to your Gemfile."
+ raise
+end
+
+class ActiveResource::Connections::Retryable < ActiveResource::Connection
+
+ # @return [Hash] options
+ # @option [Float] :sleep
+ # The number of seconds to wait between retries
+ # @option [Integer] :tries
+ # The number attempts
+ # @option [Array] :on
+ # A list of error classes to retry on
+ # @option [Regexp] :match
+ # Retries if error message matches given expression
+ class_attribute :retriable_options
+ self.retriable_options = {
+ :sleep => 0.5,
+ :tries => 3,
+ :on => [ ActiveResource::TimeoutError, ActiveResource::SSLError, Timeout::Error, OpenSSL::SSL::SSLError,
+ Errno::ETIMEDOUT, Errno::ECONNRESET, Errno::EHOSTUNREACH, EOFError, SocketError ]
+ }
+
+ protected
+
+ def request(*)
+ retryable(retriable_options) { super }
+ end
+
+end
@@ -0,0 +1 @@
+require 'active_resource/connections'
@@ -0,0 +1,14 @@
+require 'spec_helper'
+
+describe ActiveResource::Connections::CoreExt do
+
+ it 'should allow resource models to have their own connections' do
+ Parent.connection.should_not be(Root.connection)
+ Child.connection.should be(Parent.connection)
+
+ Root.connection.should be_instance_of(ActiveResource::Connection)
+ Parent.connection.should be_instance_of(ActiveResource::Connections::Retryable)
+ Child.connection.should be_instance_of(ActiveResource::Connections::Retryable)
+ end
+
+end
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe ActiveResource::Connections::Retryable do
+
+ before do
+ described_class.stub :retriable_options => described_class.retriable_options.merge(:sleep => 0)
+ end
+
+ it 'should retry on connection failures' do
+ req = stub_request(:get, "http://api.example.com/parents.json").
+ to_timeout.then.
+ to_timeout.then.
+ to_return(:body => %([{"id":1, "name":"Dave"}]))
+ Parent.all
+ req.should have_been_made.times(3)
+ end
+
+ it 'should retry only a a few times' do
+ req = stub_request(:get, "http://api.example.com/parents.json").
+ to_timeout.then.to_timeout.then.to_timeout
+ lambda { Parent.all }.should raise_error(ActiveResource::TimeoutError)
+ req.should have_been_made.times(3)
+ end
+
+end
@@ -0,0 +1,19 @@
+$: << File.expand_path('../../lib', __FILE__)
+
+require 'rubygems'
+require 'bundler/setup'
+require 'active_resource/connections'
+require 'webmock/rspec'
+
+WebMock.disable_net_connect! :allow_localhost => true
+
+class Root < ActiveResource::Base
+ self.site = "http://api.example.com"
+end
+
+class Parent < Root
+ self.connection_class = ActiveResource::Connections::Retryable
+end
+
+class Child < Parent
+end

0 comments on commit 643d4fd

Please sign in to comment.