【问题标题】:No route matches {:action=>"show_post_category", :category_id=>5, :controller=>"posts"}没有路线匹配 {:action=>"show_post_category", :category_id=>5, :controller=>"posts"}
【发布时间】:2017-11-21 14:53:38
【问题描述】:

在练习 Rails 时,我遇到了一个无法解决的问题,如下所示: - 当我点击类别名称时,我想显示所有帖子属于该类别(通过外键 category_id),我在'post'控制器中编写了一个方法:

def show_post_category
  if params[:category_id]
    @categories = Category.find_by(params[:category_id])
    @posts = @categories.posts
  else
    @posts= Post.all
  end
end

在视图中,我编写了显示类别名称超链接的代码:

<% @categories = Category.all %>
<% @categories.each do |c| %>                      
  <li>
    <%= link_to c.name, :controller => "posts", :action => "show_post_category", :category_id => c.id %>
  </li>     
<% end %>

但是,当我单击类别名称时,会显示错误

'No route matches {:action=>"show_post_category", :category_id=>5,:controller=>"posts"}.

这是路由文件中的代码:

Rails.application.routes.draw do
  resources :posts
  resources :categories   
  resources :categories do
    posts do
      get 'show_post_category'
    end
  end 
end

我的代码哪里有问题?请给我解决方案。

非常感谢,

【问题讨论】:

  • get 'show_post_category' -> get '/show_post_category/:category_id'

标签: ruby-on-rails ruby


【解决方案1】:
def show_post_category
    if params[:id].present?
        @posts = Category.find(params[:id]).posts
    else
        @posts= Post.all
    end
end

甚至更短

def show_post_category
    @posts = params[:id].present? ? Category.find(params[:id]).posts : Post.all
end

更改路线:get 'show_post_category/:id'

并将each 替换为map

<% @categories = Category.all %>
<% @categories.map do |c| %>                      
    <li>
        <%= link_to c.name, :controller => "posts", :action => "show_post_category", :id => c.id %>
    </li>     
<% end %>

【讨论】:

  • 谢谢米哈伊尔·卡特琳
【解决方案2】:

这听起来确实令人沮丧!

也许您应该尝试指定这是来自 routes.rb 文件的集合,如下所示:

  resources :categories do
    resources :posts do
      collection do
        get 'show_post_category'
      end
    end
  end

让我知道这对你有什么作用。

如果您想深入了解,这里有一些更有帮助的文档:http://guides.rubyonrails.org/routing.html

【讨论】:

  • 非常感谢 Schwad,我会参考您的建议。
【解决方案3】:

你可以做得更好。

要创建一个显示属于某个类别的所有帖子的路由,您需要以下路由:

GET /categories/:category_id/posts

这是声明nested resource 的一种宁静方式。

您可以通过以下方式声明路线:

resources :posts do
  resources :categories, only: :index, module: :posts
end

module: :posts 告诉 Rails 我们要使用单独的 Categories::PostsController#index 而不是 PostsController

class Categories::PostsController < ApplicationController
  before_action :set_category

  # GET /categories/:category_id/posts
  def index
    @posts = @category.posts
  end

  private

  def set_category
    @category = Category.includes(:posts).find(params[:category_id])
  end 
end

在此处使用模块确实是可选的,但恕我直言,它是“参数嗅探”的出色解决方案:

class PostsController < ApplicationController
  # GET /posts
  # and
  # GET /categories/:category_id/posts
  def index
    if params[:category_id]
       @posts = Category.includes(:posts).find(params[:category_id])
    else
       @posts = Post.all
    end
  end
end

后者违反了单一责任原则。

【讨论】:

  • 谢谢你 Max,我会尝试你的建议并让你知道。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-08
  • 2012-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-22
  • 2013-08-23
相关资源
最近更新 更多