public
Rubygem
Fork of mislav/will_paginate
Description: Most awesome pagination solution for Rails
Homepage: http://github.com/mislav/will_paginate/wikis
Clone URL: git://github.com/chriseppstein/will_paginate.git
crazy monkeypatching to enable named_scope on associations in Rails 
1.2.6/2.0.2 ... but finally it works!!
mislav (author)
Sat Apr 05 07:16:57 -0700 2008
commit  17a05b7d173364214125978ce1a7c73958407899
tree    2112eca3c9beba426e733c5acb5e0b4a6bee2a27
parent  ceefd5e69c8c4a136ede9d90c3da71f6442cbe1b
...
33
34
35
36
37
38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
40
41
42
43
44
45
46
47
48
49
 
 
 
 
 
 
 
 
 
 
 
 
50
51
 
52
53
54
...
33
34
35
 
 
 
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
 
 
 
 
 
84
85
86
87
88
89
90
91
92
93
94
95
96
 
97
98
99
100
0
@@ -33,22 +33,68 @@ module WillPaginate
0
       require 'will_paginate/finder'
0
       ActiveRecord::Base.class_eval { include Finder }
0
 
0
- # support paginating finders on associations
0
- a = ActiveRecord::Associations
0
- [a::AssociationCollection, a::HasManyThroughAssociation].each do |klass|
0
+ if patch_named_scope = !defined?(ActiveRecord::NamedScope)
0
+ # bring in a Rails 2.1 feature
0
+ require 'will_paginate/named_scope'
0
+
0
+ ActiveRecord::Base.class_eval do
0
+ include WillPaginate::NamedScope
0
+ end
0
+
0
+ ActiveRecord::Associations::AssociationProxy.class_eval do
0
+ protected
0
+ def with_scope(*args, &block)
0
+ @reflection.klass.send :with_scope, *args, &block
0
+ end
0
+ end
0
+ end
0
+
0
+ # support pagination on associations
0
+ [ ActiveRecord::Associations::AssociationCollection,
0
+ ActiveRecord::Associations::HasManyThroughAssociation ].each do |klass|
0
+ klass.class_eval do
0
+ protected
0
+ def method_missing(method, *args)
0
+ if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method))
0
+ if block_given?
0
+ super { |*block_args| yield(*block_args) }
0
+ else
0
+ super
0
+ end
0
+ elsif @reflection.klass.scopes.include?(method)
0
+ @reflection.klass.scopes[method].call(self, *args)
0
+ else
0
+ with_scope construct_scope do
0
+ if block_given?
0
+ @reflection.klass.send(method, *args) { |*block_args| yield(*block_args) }
0
+ else
0
+ @reflection.klass.send(method, *args)
0
+ end
0
+ end
0
+ end
0
+ end
0
+ end if patch_named_scope
0
+
0
         klass.class_eval do
0
           include Finder::ClassMethods
0
           alias_method_chain :method_missing, :paginate
0
         end
0
       end
0
 
0
- unless defined? ActiveRecord::NamedScope
0
- require 'will_paginate/named_scope'
0
-
0
- ActiveRecord::Base.class_eval do
0
- include WillPaginate::NamedScope
0
+ ActiveRecord::Associations::HasAndBelongsToManyAssociation.class_eval do
0
+ protected
0
+ def method_missing(method, *args, &block)
0
+ if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method))
0
+ super
0
+ elsif @reflection.klass.scopes.include?(method)
0
+ @reflection.klass.scopes[method].call(self, *args)
0
+ else
0
+ @reflection.klass.with_scope(:find => { :conditions => @finder_sql, :joins => @join_sql, :readonly => false }) do
0
+ @reflection.klass.send(method, *args, &block)
0
+ end
0
+ end
0
         end
0
- end
0
+ end if ActiveRecord::VERSION::MAJOR < 2 and patch_named_scope
0
     end
0
   end
0
 
...
226
227
228
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
230
231
...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
0
@@ -226,6 +226,38 @@ class FinderTest < ActiveRecordTestCase
0
     assert_equal 1, entries.size
0
     assert_equal 2, entries.total_entries
0
   end
0
+
0
+ def test_paginate_in_named_scope_on_habtm_association
0
+ project = projects(:active_record)
0
+ assert_queries(2) do
0
+ entries = project.developers.poor.paginate :page => 1, :per_page => 1
0
+
0
+ assert_equal 1, entries.size, 'one developer should be found'
0
+ assert_equal 1, entries.total_entries, 'only one developer should be found'
0
+ end
0
+ end
0
+
0
+ def test_paginate_in_named_scope_on_hmt_association
0
+ project = projects(:active_record)
0
+ expected = [replies(:brave)]
0
+
0
+ assert_queries(2) do
0
+ entries = project.replies.recent.paginate :page => 1, :per_page => 1
0
+ assert_equal expected, entries
0
+ assert_equal 1, entries.total_entries, 'only one reply should be found'
0
+ end
0
+ end
0
+
0
+ def test_paginate_in_named_scope_on_has_many_association
0
+ project = projects(:active_record)
0
+ expected = [topics(:ar)]
0
+
0
+ assert_queries(2) do
0
+ entries = project.topics.mentions_activerecord.paginate :page => 1, :per_page => 1
0
+ assert_equal expected, entries
0
+ assert_equal 1, entries.total_entries, 'only one topic should be found'
0
+ end
0
+ end
0
 
0
   def test_readonly
0
     assert_nothing_raised { Developer.paginate :readonly => true, :page => 1 }
...
1
2
3
4
5
6
7
 
 
 
...
 
 
 
 
1
2
3
4
5
6
0
@@ -1,7 +1,6 @@
0
-action_controller:
0
- id: 2
0
- name: Active Controller
0
-
0
 active_record:
0
   id: 1
0
   name: Active Record
0
+action_controller:
0
+ id: 2
0
+ name: Active Controller
...
1
2
 
 
3
4
5
...
1
2
3
4
5
6
7
0
@@ -1,5 +1,7 @@
0
 class Reply < ActiveRecord::Base
0
   belongs_to :topic, :include => [:replies]
0
+
0
+ named_scope :recent, :conditions => ['replies.created_at > ?', 15.minutes.ago]
0
   
0
   validates_presence_of :content
0
 end
...
1
2
3
 
 
4
...
1
2
3
4
5
6
0
@@ -1,4 +1,6 @@
0
 class Topic < ActiveRecord::Base
0
   has_many :replies, :dependent => :destroy, :order => 'replies.created_at DESC'
0
   belongs_to :project
0
+
0
+ named_scope :mentions_activerecord, :conditions => ['topics.title LIKE ?', '%ActiveRecord%']
0
 end
...
55
56
57
58
 
59
60
61
...
55
56
57
 
58
59
60
61
0
@@ -55,7 +55,7 @@ class ActiveRecordTestConnector
0
 
0
   def self.prepare(conn)
0
     class << conn
0
- IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/]
0
+ IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SHOW FIELDS /]
0
 
0
       def execute_with_counting(sql, name = nil, &block)
0
         $query_count ||= 0

Comments

    No one has commented yet.