2017-10-13 63 views
10

我有一个名为posts的资源,其中有很多。但是,每个帖子可以有多个标签。我希望用户只能从选择的标记中转到上一篇文章和下一篇文章。我在之前的数据库中使用过所有文章,但是当我点击一个标签并显示了所有标签时,prev/next不遵守标签。Rails 5上一篇或下一篇文章只从某个标记

如果我访问与routes.rb,get 'tags/:tag', to: 'posts#index', as: :tag中定义的代码相关联的url,它将列出索引中的所有标签。我不希望这样,我希望用户能够点击上一个或下一个,并且只对与标签关联的帖子执行此操作。

注:我使用的是friendly_id宝石

控制器/ posts_controller.rb

def index 
    @posts = Post.all 

    if params[:tag] 
     @posts = Post.tagged_with(params[:tag]) 
    else 
     @posts = Post.all 
    end 

    end 

型号/ post.rb

# tags 
    acts_as_taggable # Alias for acts_as_taggable_on :tags 

def next 
    Post.where("id > ?", id).order(id: :asc).limit(1).first 
end 

def prev 
    Post.where("id < ?", id).order(id: :desc).limit(1).first 
end 

show.html .erb

<%= link_to "← Previous Question", @post.prev, :class => 'button previous-question' %> 

<%= link_to "Next Question →", @post.next, :class => 'button next-question' %> 

的routes.rb

# TAGS 
    get 'tags/:tag', to: 'posts#index', as: :tag 
+0

',但是当我点击广告代码,并显示所有tags'你能解释一下痘痘吗?它会显示所有标签?你能为此添加代码吗? –

+0

我已更新帖子@NarasimhaReddy – mazing

+0

因此,当标签被点击并且其相关帖子被显示时,你想为这些帖子列表分页? – arjun

回答

4

你可以把这个在你的控制器,然后,Post.where(["id < ?", id]).last用于先前和Post.where(["id > ?", id]).first这为下。

你要做的是控制器的工作。您可以根据您的排序来扩展这些。

我还发现this gem。对你来说会好得多。

+0

这仅限于帖子,我已经有此功能。我想要的是前一个或下一个取决于标签。 – mazing

+0

你是什么意思取决于标签? – arjun

+0

如果用户在帖子控制器中点击上一个或下一个,因为它全部在数据库中,所以它工作正常。 但是,如果用户点击某个标签,如“水果”,如果用户点击“水果”标签,它应该只显示标签为“水果”的帖子。 所有帖子都有标签,如果用户点击任何标签,我只想在“上一个和下一个按钮”中显示相关帖子。对不起,如果它之前没有清楚 – mazing

7

我认为你将不得不通过围绕tag参数(虽然你也许应该让一个辅助方法)

型号/ post.rb

def next tag 
    Post.where("id > ?", id).tagged_with(tag).order(id: :asc).limit(1).first 
end 

def prev tag 
    Post.where("id < ?", id).tagged_with(tag).order(id: :desc).limit(1).first 
end 

显示

<%= link_to "← Previous Question", post_path(@post.prev(current_tag).id, tag: current_tag), :class => 'button previous-question' %> 

<%= link_to "Next Question →", post_path(@post.next(current_tag).id, tag: current_tag), :class => 'button next-question' %> 

controllers/posts_controller.rb

class PostsController < ApplicationController 
    helper_method :current_tag 

    #def show 
    #def index 

    private 

    def current_tag 
    params[:tag] 
    end 
end 
+0

你能解释一下更多的是怎么回事?另外..我得到这个错误。到底是怎么回事?在为model.rb编写代码时,next和tag之间是否应该有空格? 'ActionController :: UrlGenerationError at/posts/1 没有路由匹配{:action =>“show”,:controller =>“posts”,:id => nil,:tag => nil},可能的不匹配约束: [:id]' – mazing

+0

next和tag之间应该有空格,因为它是方法的参数。 (如果你愿意的话,你可以把它放在括号内,尽管这在红宝石中不需要)。至于这个错误,我想我在视图中的实现中搞砸了。你需要将id传递给url_helper(我想,让我编辑它)。但是,我不知道为什么标签参数是零。基本上, – Sean

+0

。我们正在做的是将标签沿着每个请求传递为'current_tag',然后在'next'或'post'中,我们正在重新计算'tagged_with'作用域,'current_tag'是争论。 – Sean

4

这是Sean的回答。它现在应该工作。当prevnext方法返回nil

型号/ post.rb出现问题

def next tag 
    result = Post.where("id > ?", id).tagged_with(tag).order(id: :asc).limit(1).first 

    result || very_first(tag) 
end 

def prev tag 
    result = Post.where("id < ?", id).tagged_with(tag).order(id: :desc).limit(1).first 

    result || very_last(tag) 
end 

def very_first tag 
    Post.tagged_with(tag).order(id: :asc).limit(1).first 
end 

def very_last tag 
    Post.tagged_with(tag).order(id: :asc).limit(1).last 
end 

显示

<% if @post.prev(current_tag) %> 
    <%= link_to "← Previous Question", post_path(@post.prev(current_tag).id, tag: current_tag), :class => 'button previous-question' %> 
<% end %> 

<% if @post.next(current_tag) %> 
    <%= link_to "Next Question →", post_path(@post.next(current_tag).id, tag: current_tag), :class => 'button next-question' %> 
<% end %> 

控制器/ posts_controller。rb

class PostsController < ApplicationController 
    helper_method :current_tag 

    #def show 
    #def index 

    private 

    def current_tag 
    params[:tag] 
    end 
end 

P.S.对不起肖恩,我不能对你的解答发表评论,所以我只是复制和修复它

+0

NameError at/posts/testpost 未定义的局部变量或方法'结果'为# mazing

+0

Petr的答案中存在拼写错误,结果未在'prev'方法中初始化,查看'next'方法定义并做同样的 - '结果= Post.where(“id <?”,id).tagged_with(tag).order(id::desc).limit(1).first' –

+0

顺便把所有这些方法放在Post模型本身并不是一个很好的想法,因为时间表示在大型项目上,更好地创建一些PostPresenter并将代码移动到那里 –

3

您也可以嵌套资源的做法,改变你这样的路线:

resource :tag do 
    resource :post 
end 

它应该给你的路由结构因此/tags/:tag_id/posts将指向给定标记的所有帖子,并且/tags/:tag_id/posts/:id将指向用该标记标记的确切帖子(或问题?)。

然后在posts控制器,你应该添加before_filter :set_tag这样

before_filer :set_tag 

def set_tag 
    @tag = Tag.find(params[:tag_id]) 
end 

指数的行动应该是这样的

def index 
    @posts = @tag.posts 
end 

,并会一直显示该标签的帖子。

在帖子控制器的显示操作中,您可以像上面的回答一样获取下一个和上一个帖子链接。

您还应该更改视图中使用的所有帖子网址助手以包含当前标记,例如, posts_path - >tag_posts_path(@tag)其中tag是在before_filter中设置的当前标签。

我强烈建议您不要将所有这些方法放在模型上,并为帖子创建演示者对象,例如,

class PostPresenter 
    attr_reader :post 
    alias_method :current, :post 

    def initialize(post) 
    @post = post 
    @repo = post.class 
    end 

    def next 
    @repo.where('id > ?', post.id).first 
    end 

    def previous 
    @repo.where('id < ?', post.id).first 
    end 
end 

@presenter = PostPresenter.new(@post)

和下一篇文章的链接

<%= link_to "Next Question →", 
     tag_post_path(@presenter.next), 
     class: 'button next-question' if @presenter.next.present? %> 
相关问题