2017-10-13 64 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? %> 
相關問題