Question

Working through my first Rails app. It will be used for searching and viewing data on books within certain categories.

Two resources: Categories and Books. I created a many-to-many HMT (has many through) relationship (following this RailsCast), as each category will have many books and each book will belong to more than one category. Here's the relevant controller code:

Category model (category.rb)

class Category < ActiveRecord::Base

  has_ancestry
  has_many :categorizations
  has_many :books, :through => :categorizations

end

Book model (book.rb)

class Book < ActiveRecord::Base

has_many :categorizations
has_many :categories, :through => :categorizations

accepts_nested_attributes_for :categories
end

Join model (categorization.rb)

class Categorization < ActiveRecord::Base
  belongs_to :book
  belongs_to :category
end

And here's the database schema:
schema.rb

create_table "books", force: true do |t|
  t.string   "title"
  t.string   "url"
  t.integer  "rank_overall"
  t.integer  "rank_category"
  t.decimal  "price"
  t.integer  "reviews"
  t.decimal  "rating"
  t.date     "published"
  t.string   "img_cover"
  t.string   "author"
  t.datetime "created_at"
  t.datetime "updated_at"
  t.string   "asin"
  t.integer  "length"
end

create_table "categories", force: true do |t|
  t.string   "name"
  t.text     "content"
  t.string   "ancestry"
  t.datetime "created_at"
  t.datetime "updated_at"
end

add_index "categories", ["ancestry"], name: "index_categories_on_ancestry", using: :btree

create_table "categorizations", force: true do |t|
  t.integer  "book_id"
  t.integer  "category_id"
  t.integer  "rank"
  t.datetime "created_at"
  t.datetime "updated_at"
end

add_index "categorizations", ["book_id"], name: "index_categorizations_on_book_id", using: :btree
add_index "categorizations", ["category_id"], name: "index_categorizations_on_category_id", using: :btree

I have a show view that shows each category. In this view I'd like to show the books that are in each corresponding category. I have these simple loops:

.col-1-3
  %strong TITLE
  %ul
    - @books.each do |book|
      %li= book.title
.col-1-3
    %strong AUTHOR
  %ul 
    - @books.each do |book|
      %li= book.author
.col-1-3
  %strong ULR
  %ul 
    - @books.each do |book|
      %li= book.url

And in my category model I have the following:

def show
  @books = Book.order("title").includes(:categorizations).select("books.*")
end

def book_params
  params.require(:book).permit(:books => [{:title => [:book_id]}, {:id => [:category_id]}, :author, :url] )
end

Here's the problem, from the loops in my view I'm receiving information from all the books (ie: titles, authors, and urls of all the books in the database) and I only want that from the books that are in that particular category.

I believe I need to change the logic in my categories_controller.rb, is this correct? I realize that I'm selecting all the books .select("books.*") but I don't know how to edit this to conditionally call only the books that match the category of that being displayed in the show view.

Grateful for insights.

Update: Realized that this information is also quite helpful. When assigning categories to books (upon book creation) I use this code:

= check_box_tag "book[category_ids][]", category.id, @book.category_ids.include?(category.id), id: dom_id(category)

Perhaps it's possible to somehow reference dom_id(category) inside of the category model?

Forgive my "newbishness." I'm a front-end guy who is only now beginning to really venture into the back-end.

Was it helpful?

Solution

One possible solution is to change the show action in categories like this

@books=Category.find(params[:id]).books

Assuming the :id param is the id for the category (which would be the convention if you are in the categories controller).

If you don't need the information about the category and you only need the books, you could do a join (not a include) with categorizations and use a where like categorizations: {category_id: params[:id]}. That's not as clear as the 1st option, but it saves a query if you are not showing info about the category.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top