Next, Previous Entries Using a Named Scale

I have a model for which I want to get the next record and previous record (s). I want to do this with named_scope on the model, and also pass as the argument X the number of next / previous records to return.

For example, let's say I have 5 entries:

  • Record1
  • Record2
  • Record3
  • Record4
  • Record5

I want to be able to call Model.previous or Model.previous (1) to return Record2. Similarly, I want to be able to call Model.next or Model.next (1) to return Record4. As another example, I want to be able to call Model.previous (2) to return Record3. I think you get the point.

How can i do this?

+4
source share
3 answers

To implement something like Model.previous, the class itself must have a "current" state. This would make sense if the β€œcurrent” record (perhaps in the publication planning system?) Were Record3 in your example, but your example does not offer this.

If you want to take an instance of the model and get the next or previous record, the following example:

class Page < ActiveRecord::Base def previous(offset = 0) self.class.first(:conditions => ['id < ?', self.id], :limit => 1, :offset => offset, :order => "id DESC") end def next(offset = 0) self.class.first(:conditions => ['id > ?', self.id], :limit => 1, :offset => offset, :order => "id ASC") end end 

If so, you can do something like:

 @page = Page.find(4) @page.previous 

Also would work:

 @page.previous(1) @page.next @page.next(1) 

Obviously, this suggests that the idea of β€‹β€‹β€œnext” and β€œprevious” is an β€œid” field that probably will not spread very well throughout the life of the application.

If you want to use this in a class, perhaps you can extend it in a named scope that takes the "current" record as an argument. Something like that:

 named_scope :previous, lambda { |current, offset| { :conditions => ['id < ?', current], :limit => 1, :offset => offset, :order => "id DESC" }} 

This means you could call:

 Page.previous(4,1) 

Where "4" is the identifier of the entry you want to start with, and 1 is the number you want to go back to.

+11
source

I added this function to my gem by_star last month . It may have some other features that interest you, so check this out .

It works with your existing record, and then calls previous or next :

 Page.find(:last).previous 
0
source

I wrote a stone for this for arbitrary order conditions, order_query :

 class Issue < ActiveRecord::Base include OrderQuery order_query :order_display, [ [:priority, %w(high medium low)], [:valid_votes_count, :desc, sql: '(votes - suspicious_votes)'], [:updated_at, :desc], [:id, :desc] ] def valid_votes_count votes - suspicious_votes end end Issue.order_display #=> ActiveRecord::Relation<...> Issue.reverse_order_display #=> ActiveRecord::Relation<...> # get the order object, scope default: Post.all p = Issue.find(31).order_list(scope) #=> OrderQuery::RelativeOrder<...> p.before #=> ActiveRecord::Relation<...> p.previous #=> Issue<...> p.position #=> 5 p.next #=> Issue<...> p.after #=> ActiveRecord::Relation<...> 
0
source

Source: https://habr.com/ru/post/1308618/


All Articles