i''ve got several methods in my models i use to find based on certain criteria...i''ve done this so the controller code is less cluttered, plus the DRY factor. example: class Foo < ActiveRecord::Base def find_by_something(something) find :all, :joins => ..., :conditions => ... end def find_by_something_else(something_else) find :all, :joins => ..., :conditions => ... end def find_by_something_and_bar(something, bar) find :all, :joins => ..., :conditions => ... end now my question: is there a way to do Foo.find_by_something(something) in a paginator? would I have to modify all my methods to accept a limit and offset parameter? thanks _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
I''ve been trying to do the same thing. Is this possible or is the only way to do this is putting your queries in the controller?> now my question: > > is there a way to do Foo.find_by_something(something) in a paginator? > would > I have to modify all my methods to accept a limit and offset parameter? > > thanks-- Posted via http://www.ruby-forum.com/.
Chris Hall wrote:> i''ve got several methods in my models i use to find based on certain > criteria...i''ve done this so the controller code is less cluttered, plus > the DRY factor. > > example: > > class Foo < ActiveRecord::Base > > def find_by_something(something) > find :all, :joins => ..., :conditions => ... > end > > def find_by_something_else(something_else) > find :all, :joins => ..., :conditions => ... > end > > def find_by_something_and_bar(something, bar) > find :all, :joins => ..., :conditions => ... > end > > now my question: > > is there a way to do Foo.find_by_something(something) in a paginator? > would I have to modify all my methods to accept a limit and offset > parameter?This question seems to be asked a couple times a week on this list but never resolved. I also banged my head against this and ultimately gave up and put my conditions in the controller/pagination rather than in the model where I''d like it to be. I believe it can''t be done with the current paginator. Hopefully, someone more knowledgeable can prove me wrong :-) John
I had a hard time with custom pagination at first. It was intimidating and I didn''t find any of the online guides particularly helpful. So here''s mine. :-) Kevin''s custom-pagination-in-four-easy-steps: def list # step 1: read and set the variables you''ll need page = (params[:page] ||= 1).to_i items_per_page = 20 offset = (page - 1) * items_per_page # step 2: do your custom find without doing any kind of limits or offsets # i.e. get everything on every page, don''t worry about pagination yet @items = Item.find_with_some_custom_method(@some_variable) # step 3: create a Paginator, the second variable has to be the number of ALL items on all pages @item_pages = Paginator.new(self, @items.length, items_per_page, page) # step 4: only send a subset of @items to the view # this is where the magic happens... and you don''t have to do another find @items = @items[ offset..(offset + items_per_page - 1)] end HTH, Kevin Skoglund> I''ve been trying to do the same thing. Is this possible or is the > only > way to do this is putting your queries in the controller? > > >> now my question: >> >> is there a way to do Foo.find_by_something(something) in a paginator? >> would >> I have to modify all my methods to accept a limit and offset >> parameter? >> >> thanks >>
Kevin Skoglund wrote:> I had a hard time with custom pagination at first. It was intimidating > and I didn''t find any of the online guides particularly helpful. So > here''s mine. :-) > > Kevin''s custom-pagination-in-four-easy-steps: > > def list > > # step 1: read and set the variables you''ll need > page = (params[:page] ||= 1).to_i > items_per_page = 20 > offset = (page - 1) * items_per_page > > # step 2: do your custom find without doing any kind of limits or > offsets > # i.e. get everything on every page, don''t worry about pagination yet > @items = Item.find_with_some_custom_method(@some_variable) > > # step 3: create a Paginator, the second variable has to be the > number of ALL items on all pages > @item_pages = Paginator.new(self, @items.length, items_per_page, page) > > # step 4: only send a subset of @items to the view > # this is where the magic happens... and you don''t have to do > another find > @items = @items[ offset..(offset + items_per_page - 1)] > > endI suppose this is ok for small result sets, but the major problem with this approach is that for pagination of larger sets of data, this is going to be extremely inefficient. The way the rails paginator works is it gets a count of ALL the records, but then only selects what is going to be displayed using the sql ''LIMIT'' clause. John
>> I had a hard time with custom pagination at first. It was >> intimidating and I didn''t find any of the online guides >> particularly helpful. So here''s mine. :-) >> Kevin''s custom-pagination-in-four-easy-steps: >> def list >> # step 1: read and set the variables you''ll need >> page = (params[:page] ||= 1).to_i >> items_per_page = 20 >> offset = (page - 1) * items_per_page >> # step 2: do your custom find without doing any kind of limits >> or offsets >> # i.e. get everything on every page, don''t worry about >> pagination yet >> @items = Item.find_with_some_custom_method(@some_variable) >> # step 3: create a Paginator, the second variable has to be >> the number of ALL items on all pages >> @item_pages = Paginator.new(self, @items.length, >> items_per_page, page) >> # step 4: only send a subset of @items to the view >> # this is where the magic happens... and you don''t have to do >> another find >> @items = @items[ offset..(offset + items_per_page - 1)] >> end > > I suppose this is ok for small result sets, but the major problem > with this approach is that for pagination of larger sets of data, > this is going to be extremely inefficient. The way the rails > paginator works is it gets a count of ALL the records, but then > only selects what is going to be displayed using the sql ''LIMIT'' > clause. > > JohnYes, it is for small sets of data which require custom finds. For larger sets of data which also require custom finds, you''ll have to modify step 2 to execute an SQL count of your custom find instead, modify the 2nd variable in step 3 to use that count, and then modify step 4 to do the full find with the SQL limit clause added. I don''t know of a way around having to rewrite your object methods. One thing that might help you is to set sensible default values in the object methods so that you don''t also have to immediately also rewrite all of your calls to that object method. Something like: def self.find_by_custom_method( some_variable, limit = nil, offset = nil ) ... end Then you can upgrade and paginate other calls at your leisure without breaking them. Kevin
yeah, i figured that''d be the way i have to go. thanks all for the ideas. On 12/19/05, Kevin Skoglund <kevin-WGmuFPN42W8gMxX8nMqP6gC/G2K4zDHf@public.gmane.org> wrote:> > >> I had a hard time with custom pagination at first. It was > >> intimidating and I didn''t find any of the online guides > >> particularly helpful. So here''s mine. :-) > >> Kevin''s custom-pagination-in-four-easy-steps: > >> def list > >> # step 1: read and set the variables you''ll need > >> page = (params[:page] ||= 1).to_i > >> items_per_page = 20 > >> offset = (page - 1) * items_per_page > >> # step 2: do your custom find without doing any kind of limits > >> or offsets > >> # i.e. get everything on every page, don''t worry about > >> pagination yet > >> @items = Item.find_with_some_custom_method(@some_variable) > >> # step 3: create a Paginator, the second variable has to be > >> the number of ALL items on all pages > >> @item_pages = Paginator.new(self, @items.length, > >> items_per_page, page) > >> # step 4: only send a subset of @items to the view > >> # this is where the magic happens... and you don''t have to do > >> another find > >> @items = @items[ offset..(offset + items_per_page - 1)] > >> end > > > > I suppose this is ok for small result sets, but the major problem > > with this approach is that for pagination of larger sets of data, > > this is going to be extremely inefficient. The way the rails > > paginator works is it gets a count of ALL the records, but then > > only selects what is going to be displayed using the sql ''LIMIT'' > > clause. > > > > John > > Yes, it is for small sets of data which require custom finds. > > For larger sets of data which also require custom finds, you''ll have > to modify step 2 to execute an SQL count of your custom find instead, > modify the 2nd variable in step 3 to use that count, and then modify > step 4 to do the full find with the SQL limit clause added. I don''t > know of a way around having to rewrite your object methods. > > One thing that might help you is to set sensible default values in > the object methods so that you don''t also have to immediately also > rewrite all of your calls to that object method. Something like: > > def self.find_by_custom_method( some_variable, limit = nil, offset > nil ) > ... > end > > Then you can upgrade and paginate other calls at your leisure without > breaking them. > > Kevin > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >_______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails