Rails:Couldn't find all Post with 'id': (false, true) (found 1 results, but was looking for 2)

Rails:Couldn't find all Post with 'id': (false, true) (found 1 results, but was looking for 2)

我正在构建一个类别搜索系统。 当时,当前系统出现以下错误。

Couldn't find all Post with 'id': (false, true) (found 1 results, but was looking for 2).

控制器

def category
  @category = params[:category_name]
  @posts=Post.find(PostCategory.group(:post_id).pluck(:@category))
  #↑The error point.
end

路线

get '/category/:category_name', to: 'pages#category'

观看次数

<li><a href="category/casual">casual</a></li>
<li><a href="category/natural">natural</a></li>
<li><a href="category/clean">clean</a></li>
<li><a href="category/rock">rock</a></li>
<li><a href="category/formal">formal</a></li>
<li><a href="category/street">street</a></li>
<li><a href="category/hip_hop">hip_hop</a></li>
<li><a href="category/sports">sports</a></li>
<li><a href="category/outdoors">outdoors</a></li>
<li><a href="category/surf">surf</a></li>

模型关系

belongs_to :post
has_one :post_category
accepts_nested_attributes_for :post_category

帖子类别table

create_table "post_categories", force: :cascade do |t|
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.boolean "casual", default: false, null: false
    t.boolean "natural", default: false, null: false
    t.boolean "clean", default: false, null: false
    t.boolean "rock", default: false, null: false
    t.boolean "formal", default: false, null: false
    t.boolean "street", default: false, null: false
    t.boolean "hip_hop", default: false, null: false
    t.boolean "sports", default: false, null: false
    t.boolean "outdoors", default: false, null: false
    t.boolean "surf", default: false, null: false
    t.integer "post_id"
    t.index ["post_id"], name: "index_post_categories_on_post_id"
  end

我想做什么

例子。 我想找到 category_name params(casual)PostCategory column(casual) 相同的列,然后从那里只找到为真的那些,并检索 Post 的所有记录 post_id 对应于 PostCategory column(casual, only true) 并在视图中反映它们。

谢谢。

首先,您的 category 方法存在问题,其中显示 :@category。这可能需要说 @category(没有冒号),以便方法主体的第二行显示为:

@posts=Post.find(PostCategory.group(:post_id).pluck(@category))
                                                    ^

除此之外,您似乎正在尝试获取属于特定类别的所有帖子。你现在正在做的事情是行不通的,因为你查询 returns 一个布尔值数组,然后你使用布尔值来查找帖子。但是你需要 ID 来查找帖子,因为你不能将布尔值传递给 Post.find.

为什么不直接做(未测试):

@posts = Post.find(PostCategory.where(@category => true).pluck(:post_id))

或者,在单个查询中(也未测试):

@posts = Post.joins(:post_category).where("post_categories.#{@category}" => true)

但是对于最后一个,您可能需要根据白名单检查 @category 变量以避免注入。编辑:正如 Max 在评论中所建议的那样,您可能希望将 where 子句更改为 where( post_categories: { @category => true }) 以避免注入。

不需要修改数据库来添加类别的更好解决方案是设置更合理的规范化 table / 加入 table 设置:

# rails g model category name:string:uniq
class Category < ApplicationRecord
  has_many :categorizations
  has_many :posts, through: :categorizations

  validates :name, 
     uniqueness: true,
     presence: true
end

# rails g model categorization post:belongs_to category:belongs_to
class Categorization < ApplicationRecord
  belongs_to :category
  belongs_to :post

  validates :post_id, 
     uniqueness: { scope: :category_id }
end

class Post < ApplicationRecord
  has_many :categorizations
  has_many :categories, through: :categorizations
end

处理这个问题的 Rails 要么在 categories#show 动作上处理(或使用嵌套路由):

resources :categories
class CategoriesController < ApplicationController
  def show
    @category = Category.find_by!(name: params[:id])
    @posts = @category.posts 
  end
end

这当然意味着您有某种适当的设置,以确保类别的名称可以在 URL 的路径中使用。像 FriendlyID 这样的宝石是你的朋友。

@posts=Post.find(PostCategory.group(:post_id).pluck(:category))