Rails: Get next / previous record

前端 未结 9 968
说谎
说谎 2020-12-07 17:48

My app has Photos that belong to Users.

In a photo#show view I\'d like to show \"More from this user\", and show a next and previous photo from that user. I would be

相关标签:
9条回答
  • 2020-12-07 17:57

    Modify your app/models/application_record.rb to the following code:

    class ApplicationRecord < ActiveRecord::Base
      self.abstract_class = true
    
      def next
        self.class.where("id > ?", id).order("id ASC").first || self.class.first
      end
    
      def previous
       self.class.where("id < ?", id).order("id DESC").first || self.class.last
      end
    end
    

    Then you can use next() and previous() in all your models.

    0 讨论(0)
  • 2020-12-07 18:02

    You might want to check Nexter. It works on any dynamically created scope instead of relying on one hardcoded in your model.

    0 讨论(0)
  • 2020-12-07 18:04

    This should work, and I think it's more efficient than the other solutions in that it doesn't retrieve every record above or below the current one just to get to the next or previous one:

    def next
      # remember default order is ascending, so I left it out here
      Photo.offset(self.id).limit(1).first
    end
    
    def prev
      # I set limit to 2 because if you specify descending order with an 
      # offset/limit query, the result includes the offset record as the first
      Photo.offset(self.id).limit(2).order(id: :desc).last
    end
    

    This is my first answer ever posted on StackOverflow, and this question is pretty old...I hope somebody sees it :)

    0 讨论(0)
  • 2020-12-07 18:05
    class Photo < ActiveRecord::Base
      belongs_to :user
    
      default_scope { order('published_at DESC, id DESC') }
    
      def next
        current = nil
        user.photos.where('published_at >= ?', published_at).each do |p|
          if p.id == id then break else current = p end
        end
        return current
      end
    
      def previous
        current = nil
        user.photos.where('published_at <= ?', published_at).reverse.each do |p|
          if p.id == id then break else current = p end
        end
        return current
      end
    end
    

    I found that the answers already here did not serve my case. Imagine that you want a previous or next based on the date published, but some photos are published on the same date. This version will loop through the photos in the order they are rendered on the page, and take the ones before and after the current one in the collection.

    0 讨论(0)
  • 2020-12-07 18:16

    Try this:

    class User
      has_many :photos
    end
    
    
    class Photo
      belongs_to :user
    
      def next
        user.photos.where("id > ?", id).first
      end
    
      def prev
        user.photos.where("id < ?", id).last
      end
    
    end
    

    Now you can:

    photo.next
    photo.prev
    
    0 讨论(0)
  • 2020-12-07 18:16

    You can pass some options into the where method:

    For the next photo:

    Photo.where(:user_id => current_user.id, :created_at > current_photo.created_at).order("created_at").first
    

    Previous photo

    Photo.where(:user_id => current_user.id, :created_at < current_photo.created_at).order("created_at").last
    

    I may have the first/last mixed up.

    0 讨论(0)
提交回复
热议问题