Hi all, I''ve got a list of machines with columns like so: Hostname, Operating System, Location I have setup pagination with paginating_find and that works nicely. I have also setup column sorting with my own little helper and controller code. Because I wrote the helper myself I have got it to preserve the page parameter when changing sort mode. So when you move to a certain page and do a sort, the page is kept in the same place. However, if I sort a column and then change to a different page, the sorting reverts to the default which makes changing the page useless a lot of the time. What is the preferred method to combine column sorting and pagination easily? This must be a fairly common exercise but I can''t get my head round how to do it. Any help would be appreciated. Thanks Matt --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Matt Harrison wrote:> Hi all, > > I''ve got a list of machines with columns like so: > > Hostname, Operating System, Location > > I have setup pagination with paginating_find and that works nicely. I > have also setup column sorting with my own little helper and > controller code. Because I wrote the helper myself I have got it to > preserve the page parameter when changing sort mode. > > So when you move to a certain page and do a sort, the page is kept in > the same place. However, if I sort a column and then change to a > different page, the sorting reverts to the default which makes > changing the page useless a lot of the time. > > What is the preferred method to combine column sorting and pagination > easily? This must be a fairly common exercise but I can''t get my head > round how to do it. > > Any help would be appreciated.Can''t believe no-one has any ideas about this, maybe it just got buried under all the other mail. Grateful someone could take a sec to help me :) Thanks Matt --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Matt, I find that the best is to just reset to the beginning with any change of sort or pagination. It''s too confusing not to. For example, if you are showing 5 records per page in a 50 record set and you are on page 4, then you suddenly switch to 25 records per page, what should it do? Throw an error (there is no page 4 anymore)? Or have you on page 2? Or back to page 1? And with sorting, if I''m on page 4 of 7 pages sorted by last name, then suddenly switch to sorting by first name, staying on page 4... at least to me... is more confusing than just reverting back to page one. Of course, you could stay on page 4 with the new sort. So sorting seems to be more of a design choice. But pagination changes: go back to page 1. -Danimal On Sep 8, 12:43 pm, Matt Harrison <iwasinnamuk...-ja4MoDZtUtVl57MIdRCFDg@public.gmane.org> wrote:> Matt Harrison wrote: > > Hi all, > > > I''ve got a list of machines with columns like so: > > > Hostname, Operating System, Location > > > I have setup pagination with paginating_find and that works nicely. I > > have also setup column sorting with my own little helper and > > controller code. Because I wrote the helper myself I have got it to > > preserve the page parameter when changing sort mode. > > > So when you move to a certain page and do a sort, the page is kept in > > the same place. However, if I sort a column and then change to a > > different page, the sorting reverts to the default which makes > > changing the page useless a lot of the time. > > > What is the preferred method to combine column sorting and pagination > > easily? This must be a fairly common exercise but I can''t get my head > > round how to do it. > > > Any help would be appreciated. > > Can''t believe no-one has any ideas about this, maybe it just got buried > under all the other mail. > > Grateful someone could take a sec to help me :) > > Thanks > > Matt--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
As for some technical ways to do it... go look at ActiveScaffold and see how they handle it. For me, I have a combination of URL parameters and session values that get passed around. The session values are so some things will stay no matter what (like pagination) and the parameters are for one-time adjustments (like moving to other pages). For example, if I have a model Widgets with a widgets controller, I might have a URL like: http://localhost:3000/widgets?page=1&per_page=25&sort=updated_at&sort_direction=ASC Then I have a before_filter that builds the @widgets collection using WillPaginate and some custom sorting code. I can change the "per_page" value and it is stored in a session variable. But the "page" and "sort" and "sort_direction" are only stored in the params hash. So if I go to some other page then come back to: http://localhost:3000/widgets/ without any params, it will still be 25 records per page, but by default on page 1 with the default sort and default direction. I hope that helps you along. I suspect there may be some good plugins or gems for handling pagination and sorting well. I started with WillPaginate and then added in the sorting code myself. At least for me, it works and works well. -Danimal On Sep 8, 12:43 pm, Matt Harrison <iwasinnamuk...-ja4MoDZtUtVl57MIdRCFDg@public.gmane.org> wrote:> Matt Harrison wrote: > > Hi all, > > > I''ve got a list of machines with columns like so: > > > Hostname, Operating System, Location > > > I have setup pagination with paginating_find and that works nicely. I > > have also setup column sorting with my own little helper and > > controller code. Because I wrote the helper myself I have got it to > > preserve the page parameter when changing sort mode. > > > So when you move to a certain page and do a sort, the page is kept in > > the same place. However, if I sort a column and then change to a > > different page, the sorting reverts to the default which makes > > changing the page useless a lot of the time. > > > What is the preferred method to combine column sorting and pagination > > easily? This must be a fairly common exercise but I can''t get my head > > round how to do it. > > > Any help would be appreciated. > > Can''t believe no-one has any ideas about this, maybe it just got buried > under all the other mail. > > Grateful someone could take a sec to help me :) > > Thanks > > Matt--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Danimal wrote:> Matt, > > I find that the best is to just reset to the beginning with any change > of sort or pagination. It''s too confusing not to. For example, if you > are showing 5 records per page in a 50 record set and you are on page > 4, then you suddenly switch to 25 records per page, what should it do? > Throw an error (there is no page 4 anymore)? Or have you on page 2? Or > back to page 1? > > And with sorting, if I''m on page 4 of 7 pages sorted by last name, > then suddenly switch to sorting by first name, staying on page 4... at > least to me... is more confusing than just reverting back to page one. > Of course, you could stay on page 4 with the new sort. So sorting > seems to be more of a design choice. But pagination changes: go back > to page 1. > > -DanimalHi, thanks for the reply. I agree that there are some cases where it should reset the page or the sort. OTOH picture this: I''m on page 1 and I sort by hostname ASC, it gives me the hostnames starting at A etc. Then I want to move through this sorted list so I go to page 2, and my sort has been reset because I can''t work out how to modify the links generated by paginating_find. I''m not fiddling with the page size yet so that isn''t an issue, and it probably should go back to page 1 if I change the sort order, however I really would think that keeping the sort order when changing pages is kinda important. I might be going mad with this so let me know if i''m babbling :P Thanks Matt --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Matt, No, you are making sense. I think you and I got mixed up backwards. If you are KEEPING sort order but CHANGING pages, then don''t change the sort. If you are KEEPING pages but CHANGING sort order, then I would argue, force a page change to page 1. So, in your example, if you sort by hostname ASC then go to page 2, it should maintain the hostname sort. But if you are on page 2 and then change your sort to IP address, it should jump you to page 1 (although as I stated in my previous post, you could stay on page 2 in this instance). It''s not a big deal programmatically because you take your collection of objects first (i.e. via find() ), then you sort, then you paginate. The only thing that could mess this up is if your dataset changes between pages. If that is a concern, then you''d want to think through the best way to handle that, which could be one of multiple options. So, to reiterate, here''s how I handle it. Here is my index method for widgets: [code] def index @widgets = paginate_and_sort Widgets.find(:all) # or whatever means to get an array of widget objects end [/code] Then, I have this defined on application.rb (cause I use it all over): [code] def paginate_and_sort(collection) per_page = (session[:per_page] || 5).to_i page = (params[:page] ||= 1).to_i page = 1 if (page - 1) * per_page > collection.size or page < 1 offset = (page - 1) * per_page @sorted_on = params[:sort] unless params[:sort_direction] == "reset" @sorted_dir = params[:sort_direction] if (["ASC", "DESC"].include?(@sorted_dir)) collection = if @sorted_dir == "DESC" collection.sort {|a,b| b.send(params[:sort]) <=> a.send(params[:sort])} else collection.sort {|a,b| a.send(params[:sort]) <=> b.send(params[:sort])} end else collection = collection.sort {|a,b| b.updated_at <=> a.updated_at } end WillPaginate::Collection.new(page, per_page, collection.length).concat(collection[offset..(offset + per_page - 1)]) end [/code] I then set the session[:per_page] elsewhere, i.e. when the user changes that in a different action, I set it as a session variable. So note that though not the cleanest code, it works and works well. I build the values needed for will_paginate then I sort the collection either by the sort & direction or by updated_at (that''s my default, yours may differ). Then pass that into will_paginate which will return a pseudo-array of the paginated objects. HTH! -Danimal On Sep 9, 10:39 am, Matt Harrison <iwasinnamuk...-ja4MoDZtUtVl57MIdRCFDg@public.gmane.org> wrote:> Danimal wrote: > > Matt, > > > I find that the best is to just reset to the beginning with any change > > of sort or pagination. It''s too confusing not to. For example, if you > > are showing 5 records per page in a 50 record set and you are on page > > 4, then you suddenly switch to 25 records per page, what should it do? > > Throw an error (there is no page 4 anymore)? Or have you on page 2? Or > > back to page 1? > > > And with sorting, if I''m on page 4 of 7 pages sorted by last name, > > then suddenly switch to sorting by first name, staying on page 4... at > > least to me... is more confusing than just reverting back to page one. > > Of course, you could stay on page 4 with the new sort. So sorting > > seems to be more of a design choice. But pagination changes: go back > > to page 1. > > > -Danimal > > Hi, thanks for the reply. > > I agree that there are some cases where it should reset the page or the > sort. OTOH picture this: > > I''m on page 1 and I sort by hostname ASC, it gives me the hostnames > starting at A etc. Then I want to move through this sorted list so I go > to page 2, and my sort has been reset because I can''t work out how to > modify the links generated by paginating_find. > > I''m not fiddling with the page size yet so that isn''t an issue, and it > probably should go back to page 1 if I change the sort order, however I > really would think that keeping the sort order when changing pages is > kinda important. > > I might be going mad with this so let me know if i''m babbling :P > > Thanks > > Matt--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Danimal wrote:> Matt, > > No, you are making sense. I think you and I got mixed up backwards. > > If you are KEEPING sort order but CHANGING pages, then don''t change > the sort. > If you are KEEPING pages but CHANGING sort order, then I would argue, > force a page change to page 1. > > So, in your example, if you sort by hostname ASC then go to page 2, it > should maintain the hostname sort. But if you are on page 2 and then > change your sort to IP address, it should jump you to page 1 (although > as I stated in my previous post, you could stay on page 2 in this > instance). > > It''s not a big deal programmatically because you take your collection > of objects first (i.e. via find() ), then you sort, then you paginate. > > The only thing that could mess this up is if your dataset changes > between pages. If that is a concern, then you''d want to think through > the best way to handle that, which could be one of multiple options. > > So, to reiterate, here''s how I handle it. Here is my index method for > widgets: > > [code] > def index > @widgets = paginate_and_sort Widgets.find(:all) # or whatever means > to get an array of widget objects > end > [/code] > > Then, I have this defined on application.rb (cause I use it all over): > > [code] > def paginate_and_sort(collection) > per_page = (session[:per_page] || 5).to_i > page = (params[:page] ||= 1).to_i > page = 1 if (page - 1) * per_page > collection.size or page < 1 > offset = (page - 1) * per_page > @sorted_on = params[:sort] unless params[:sort_direction] == "reset" > @sorted_dir = params[:sort_direction] > if (["ASC", "DESC"].include?(@sorted_dir)) > collection = if @sorted_dir == "DESC" > collection.sort {|a,b| b.send(params[:sort]) <=> > a.send(params[:sort])} > else > collection.sort {|a,b| a.send(params[:sort]) <=> > b.send(params[:sort])} > end > else > collection = collection.sort {|a,b| b.updated_at <=> > a.updated_at } > end > > WillPaginate::Collection.new(page, per_page, > collection.length).concat(collection[offset..(offset + per_page - 1)]) > end > [/code] > > I then set the session[:per_page] elsewhere, i.e. when the user > changes that in a different action, I set it as a session variable. > > So note that though not the cleanest code, it works and works well. I > build the values needed for will_paginate then I sort the collection > either by the sort & direction or by updated_at (that''s my default, > yours may differ). Then pass that into will_paginate which will return > a pseudo-array of the paginated objects. > > HTH! > > -DanimalWell I''m glad we''re on the same page (excuse the pun). I''ve managed to fix the "changing page resets sort" problem by using the session as the store instead of params. That means I don''t have to fiddle with paginating_find and get the params passed. I''m onto the next problem now: /machines/index => Shows a list of machine which are paginated and can be sorted. /machines/view/1 => Views a machine by ID and lists records associated with the machine. I want to paginate and sort the list of records but I''m not sure if this can be done with associated records. Ideally it would be in the records controller but for some reason I chose to put it in the machines/view action. Any suggestions on paginating and sorting an associated collection? Incidentally, the records also have uploads associated with them so I will have to do it again with the uploads list. Thanks for the help so far and I''d appreciate any further advice :) Thanks Matt --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---