Search code examples
ruby-on-railsrubyruby-on-rails-5

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


I am building a system for category search. At that time, the following errors are occurring in the current system.

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

Controllers

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

routes

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

Views

<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>

Relationship of models

belongs_to :post
has_one :post_category
accepts_nested_attributes_for :post_category

PostCategory 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

What I want to do

Example. I want to find a column where category_name params(casual) and PostCategory column(casual) are the same, and from there, find only the ones that are true, and retrieve all the records of Post whose post_id corresponds to PostCategory column(casual, only true) and reflect them in the view.

Thank you.


Solution

  • First, there's a problem in your category method where it says :@category. That would probably need to say @category (without the colon), so that the method body's second line reads:

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

    That aside, it seems that you're trying to fetch all posts that belong to a certain category. What you're doing right now won't work because your query returns an array of booleans, and then you use booleans to look up posts. But you'd need ids to look up posts because you can't pass booleans to Post.find.

    Why not just do (not tested):

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

    or, in a single query (not tested either):

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

    But for that last one you may need to check the @category variable against a whitelist to avoid injections. EDIT: As Max suggests in the comments, you may want to change the where clause to where( post_categories: { @category => true }) to avoid injections.