Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

crazy monkeypatching to enable named_scope on associations in Rails 1…

….2.6/2.0.2 ... but finally it works!!
  • Loading branch information...
commit 17a05b7d173364214125978ce1a7c73958407899 1 parent ceefd5e
@mislav authored
View
64 lib/will_paginate.rb
@@ -33,22 +33,68 @@ def enable_activerecord
require 'will_paginate/finder'
ActiveRecord::Base.class_eval { include Finder }
- # support paginating finders on associations
- a = ActiveRecord::Associations
- [a::AssociationCollection, a::HasManyThroughAssociation].each do |klass|
+ if patch_named_scope = !defined?(ActiveRecord::NamedScope)
+ # bring in a Rails 2.1 feature
+ require 'will_paginate/named_scope'
+
+ ActiveRecord::Base.class_eval do
+ include WillPaginate::NamedScope
+ end
+
+ ActiveRecord::Associations::AssociationProxy.class_eval do
+ protected
+ def with_scope(*args, &block)
+ @reflection.klass.send :with_scope, *args, &block
+ end
+ end
+ end
+
+ # support pagination on associations
+ [ ActiveRecord::Associations::AssociationCollection,
+ ActiveRecord::Associations::HasManyThroughAssociation ].each do |klass|
+ klass.class_eval do
+ protected
+ def method_missing(method, *args)
+ if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method))
+ if block_given?
+ super { |*block_args| yield(*block_args) }
+ else
+ super
+ end
+ elsif @reflection.klass.scopes.include?(method)
+ @reflection.klass.scopes[method].call(self, *args)
+ else
+ with_scope construct_scope do
+ if block_given?
+ @reflection.klass.send(method, *args) { |*block_args| yield(*block_args) }
+ else
+ @reflection.klass.send(method, *args)
+ end
+ end
+ end
+ end
+ end if patch_named_scope
+
klass.class_eval do
include Finder::ClassMethods
alias_method_chain :method_missing, :paginate
end
end
- unless defined? ActiveRecord::NamedScope
- require 'will_paginate/named_scope'
-
- ActiveRecord::Base.class_eval do
- include WillPaginate::NamedScope
+ ActiveRecord::Associations::HasAndBelongsToManyAssociation.class_eval do
+ protected
+ def method_missing(method, *args, &block)
+ if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method))
+ super
+ elsif @reflection.klass.scopes.include?(method)
+ @reflection.klass.scopes[method].call(self, *args)
+ else
+ @reflection.klass.with_scope(:find => { :conditions => @finder_sql, :joins => @join_sql, :readonly => false }) do
+ @reflection.klass.send(method, *args, &block)
+ end
+ end
end
- end
+ end if ActiveRecord::VERSION::MAJOR < 2 and patch_named_scope
end
end
View
32 test/finder_test.rb
@@ -226,6 +226,38 @@ def test_paginate_in_named_scope
assert_equal 1, entries.size
assert_equal 2, entries.total_entries
end
+
+ def test_paginate_in_named_scope_on_habtm_association
+ project = projects(:active_record)
+ assert_queries(2) do
+ entries = project.developers.poor.paginate :page => 1, :per_page => 1
+
+ assert_equal 1, entries.size, 'one developer should be found'
+ assert_equal 1, entries.total_entries, 'only one developer should be found'
+ end
+ end
+
+ def test_paginate_in_named_scope_on_hmt_association
+ project = projects(:active_record)
+ expected = [replies(:brave)]
+
+ assert_queries(2) do
+ entries = project.replies.recent.paginate :page => 1, :per_page => 1
+ assert_equal expected, entries
+ assert_equal 1, entries.total_entries, 'only one reply should be found'
+ end
+ end
+
+ def test_paginate_in_named_scope_on_has_many_association
+ project = projects(:active_record)
+ expected = [topics(:ar)]
+
+ assert_queries(2) do
+ entries = project.topics.mentions_activerecord.paginate :page => 1, :per_page => 1
+ assert_equal expected, entries
+ assert_equal 1, entries.total_entries, 'only one topic should be found'
+ end
+ end
def test_readonly
assert_nothing_raised { Developer.paginate :readonly => true, :page => 1 }
View
7 test/fixtures/projects.yml
@@ -1,7 +1,6 @@
-action_controller:
- id: 2
- name: Active Controller
-
active_record:
id: 1
name: Active Record
+action_controller:
+ id: 2
+ name: Active Controller
View
2  test/fixtures/reply.rb
@@ -1,5 +1,7 @@
class Reply < ActiveRecord::Base
belongs_to :topic, :include => [:replies]
+
+ named_scope :recent, :conditions => ['replies.created_at > ?', 15.minutes.ago]
validates_presence_of :content
end
View
2  test/fixtures/topic.rb
@@ -1,4 +1,6 @@
class Topic < ActiveRecord::Base
has_many :replies, :dependent => :destroy, :order => 'replies.created_at DESC'
belongs_to :project
+
+ named_scope :mentions_activerecord, :conditions => ['topics.title LIKE ?', '%ActiveRecord%']
end
View
2  test/lib/activerecord_test_connector.rb
@@ -55,7 +55,7 @@ def self.load_schema
def self.prepare(conn)
class << conn
- IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/]
+ IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SHOW FIELDS /]
def execute_with_counting(sql, name = nil, &block)
$query_count ||= 0
Please sign in to comment.
Something went wrong with that request. Please try again.