Rails:在我的show view中,“Next post”和“Previous post”链接如何?

我是Rails新人……微笑

在我的博客应用程序中,我希望在我的节目视图的底部有一个“Previous post”链接和一个“Next post”链接。

我如何做到这一点?

谢谢!

如果每个标题都是唯一的,并且您需要按字母顺序排列,请在Post模型中试用。

 def previous_post self.class.first(:conditions => ["title < ?", title], :order => "title desc") end def next_post self.class.first(:conditions => ["title > ?", title], :order => "title asc") end 

然后你可以链接到视图中的那些。

 <%= link_to("Previous Post", @post.previous_post) if @post.previous_post %> <%= link_to("Next Post", @post.next_post) if @post.next_post %> 

未经testing,但它应该让你接近。 如果您需要不同的sorting顺序,您可以将title更改为任何唯一属性( created_atid等)。

我使用了下面的模型方法来避免id + 1不存在但id + 2的问题。

 def previous Post.where(["id < ?", id]).last end def next Post.where(["id > ?", id]).first end 

在我的视图代码中,我只是这样做的:

  - if @post.previous = link_to "< Previous", @post.previous - if @post.next = link_to "Next >", @post.next 

我的方法将允许您自动使用模型范围。 例如,您可能只想显示“已发布”的post。

在你的模型中:

 def self.next(post) where('id < ?', post.id).last end def self.previous(post) where('id > ?', post.id).first end 

在你看来

 <%= link_to 'Previous', @posts.previous(@post) %> <%= link_to 'Next', @posts.next(@post) %> 

在你的控制器中

 @photos = Photo.published.order('created_at') 

相关的RSpectesting:

 describe '.next' do it 'returns the next post in collection' do fourth_post = create(:post) third_post = create(:post) second_post = create(:post) first_post = create(:post) expect(Post.next(second_post)).to eq third_post end it 'returns the next post in a scoped collection' do third_post = create(:post) decoy_post = create(:post, :published) second_post = create(:post) first_post = create(:post) expect(Post.unpublished.next(second_post)).to eq third_post end end describe '.previous' do it 'returns the previous post in collection' do fourth_post = create(:post) third_post = create(:post) second_post = create(:post) first_post = create(:post) expect(Post.previous(third_post)).to eq second_post end it 'returns the previous post in a scoped collection' do third_post = create(:post) second_post = create(:post) decoy_post = create(:post, :published) first_post = create(:post) expect(Post.unpublished.previous(second_post)).to eq first_post end end 

请注意:当您收到collections中的第一个/最后一个post时,会出现小问题。 我build议视图助手有条件地显示上一个或下一个button,只要它存在。

我就是这么做的 首先,向您的Post模型中添加一些指定的范围 :

 def previous Post.find_by_id(id - 1, :select => 'title, slug etc...') end def next Post.find_by_id(id + 1, :select => 'title, slug etc...') end 

请注意使用:select选项来限制字段,因为您可能不想检索完全填充的Post实例来显示链接。

然后在我的posts_helper我有这个方法:

 def sidebar_navigation_links next_post = @post.next previous_post = @post.previous links = '' if previous_post links << content_tag(:h3, 'Previous') links << content_tag(:ul, content_tag(:li, content_tag(:a, previous_post.title, :href => previous_post.permalink))) end if next_post links << content_tag(:h3, 'Next', :class => 'next') if previous_post links << content_tag(:h3, 'Next') if previous_post.nil? links << content_tag(:ul, content_tag(:li, content_tag(:a, next_post.title, :href => next_post.permalink))) end content_tag(:div, links) end 

我相信这可以被重构为不太冗长,但意图是明确的。 很明显,您的标记要求与我的标记要求不同,例如,您可能不会select使用无序列表。

重要的是使用if语句,因为如果你在第一篇文章,那么他们将不会有以前的post,反之,如果你在最后一篇文章,他们将不会有下一篇文章。

最后,只需从视图中调用帮助器方法:

 <%= sidebar_navigation_links %> 

试试will_paginate Gem。 它提供了所有你需要分页的条目。 在这里学习

如果您想添加下一个和上一个button,您也可以在这里查看示例代码。

我特别为这种任务创build了gem proximal_records ,它可以在模型中的任何dynamic创build的范围内工作。

https://github.com/dmitry/proximal_records

基本示例:

 class Article < ActiveRecord::Base include ProximalRecords end scope = Article.title_like('proximal').order('created_at DESC, title ASC') current_record = scope.to_a[5] p, n = current_record.proximal_records(scope) # will find record 5 and 7 

你真的只需要运行2个查询,每个“prev”和“next”。 让我们假设你有一个created_at列。

伪代码:

 # get prev select * from posts where created_at < #{this_post.created_at} order by created_at desc limit 1 # get next select * from posts where created_at > #{this_post.created_at} order by created_at desc limit 1 

当然“this_post”是目前的职位。

如果您的post与auto_increment列一起存储,并且您不重复使用ID,则可以使用id列代替created_at – id列已经被编入索引。 如果你想使用created_at列,那么你一定会想在该列上有一个索引。