2017-10-13 1 views
10

私は多くの人が投稿するという名前のリソースを持っています。ただし、各投稿は複数のタグを持つことができます。選択したタグからのみ、以前の投稿と次の投稿に移動できるようにします。私は以前のデータベースのすべての投稿のために働いていますが、タグをクリックしてすべてのタグを表示すると、prev/nextはタグの内容に従いません。Rails 5前または次の投稿特定のタグからのみ

routes.rbに定義されているコードget 'tags/:tag', to: 'posts#index', as: :tagに関連付けられたURLにアクセスすると、インデックス内のすべてのタグが一覧表示されます。私はこれを望んでいない、私は、ユーザーが前または次をクリックすることができますし、タグに関連付けられているポストでのみ行うことができます。

注:私は

コントローラ/ 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 friendly_id宝石を使用しています.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

'私は、タグをクリックすると、それはあなたがlitle多くを説明することができ、すべてのtags'を示していたときに?どこにすべてのタグが表示されますか?これのためのコードを追加できますか? –

+0

投稿を更新しました@NarasimhaReddy – mazing

+0

タグをクリックして関連する投稿が表示されたときに、それらの投稿の一覧をページ分割する必要がありますか? – arjun

答えて

4

あなたは、その後、あなたのコントローラで以前と次のためにPost.where(["id > ?", id]).firstこのためPost.where(["id < ?", id]).lastこれを置くことができます。

あなたがしようとしていることは、コントローラの仕事です。ソートに基づいてそれらを拡張することができます。

また、this gemが見つかりました。あなたが使う方がはるかに良いでしょう。

+0

これは投稿専用です。この機能は既に動作しています。私が望むのは、タグに応じて前または次です。 – mazing

+0

タグによってはどういう意味ですか? – arjun

+0

データベース内にあるので、ユーザーが前または次をクリックしてポストコントローラにいればうまくいきます。 しかし、ユーザーが「果物」などの特定のタグをクリックした場合、ユーザーが「果物」をクリックすると「果物」とタグ付けされた投稿のみが表示されるはずです。 すべての投稿にタグがあります。ユーザーがタグをクリックした場合、関連する投稿を「前と次のボタン」に表示したいだけです。申し訳ありませんが、前にはっきりしなかった場合 – mazing

7

私は

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' %> 
を示し

モデル/ post.rbあなたは(あなたはおそらくそれヘルパーメソッドにする必要がありますが)そのtagパラメータの周囲を通過する必要があるとしていると思います

コントローラ/ 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のためにそれを書いたので、次とタグの間にスペースがあるべきですか? 'ActionController :: UrlGenerationError at/posts/1 {:action =>" show "、:controller =>" posts "、:id => nil、:tag => nil}と一致するルートはありません。 [:id] ' – mazing

+0

メソッドの引数であるため、nextとtagの間にスペースが必要です。 (あなたが望むなら、それは括弧で入れることができますが、それはルビーでは必要ありません)。エラーについては、私の見解では実装がうまくいかないと思う。 idをurl_helperに渡す必要があります(私はそれを編集させてください)。しかし、なぜタグパラメータがnilであるのかわかりません。 – Sean

+0

基本的には。私たちがやっていることは、各リクエストに沿って 'current_tag'としてタグを渡し、' next'または 'post'の中で、' current_tag'を引数として 'tagged_with'の範囲を再評価することです。 – Sean

4

ここにSea​​nの答えが更新されました。今はうまくいくはずです。問題はprevまたはnext方法が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

名前エラー/ポスト/テストポスト 未定義のローカル変数またはメソッド 'result 'for# mazing

+0

Petrの答えにタイプミスがあります。結果は' prev'メソッドで初期化されていません。 'next'メソッド定義を見てください。同様に 'result = Post.where(" id <? "、id).tagged_with(tag).order(id::desc).limit(1).first' –

+0

ところで、これらすべてのメソッドをポストモデルそのものは、大きなプロジェクトでは時間がたっぷりと表示されるので、ポストプレゼンターを作成してそのコードを移動するのは良い考えではありません。 –

3

また、ネストされたリソースのアプローチを取ると、このようなあなたのルートを変更することができます。

resource :tag do 
    resource :post 
end 

は、それはあなたのルート構造を与える必要がありますその結果、/tags/:tag_id/postsは特定のタグのすべての投稿を指し、/tags/:tag_id/posts/:idはそのタグでタグ付けされた正確な投稿(または質問?)を指します。

その後ポストコントローラで、あなたが追加する必要がありますbefore_filter :set_tag

before_filer :set_tag 

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

このようなindexアクションは、この

def index 
    @posts = @tag.posts 
end 

ようになり、常にそのタグの記事を表示します。

投稿者の表示アクションでは、上記の回答のように、次と前の投稿リンクを取得できます。

また、現在のタグを含めるようにビューで使用されるすべての投稿urlヘルパーを変更する必要があります。 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? %> 
関連する問題