Reputation: 27
I want to make a feature to show posts with specific categories, A, B, C..., where there can be more than one category. Currently, I can add only one.
How can I add more and show them?
This is the migration:
class CreateCategories < ActiveRecord::Migration[6.0]
def change
create_table :categories do |t|
t.string :name
t.text :description
t.boolean :display_in_navbar, default: true
t.timestamps
end
end
end
class CreatePosts < ActiveRecord::Migration[6.0]
def change
create_table :posts do |t|
t.string :title
t.text :body
t.string :author
t.boolean :featured
t.integer :likes
t.string :source
t.references :category, null: false, foreign_key: true
t.timestamps
end
end
end
My models:
class Category < ApplicationRecord
has_and_belongs_to_many :posts
end
class Post < ApplicationRecord
has_and_belongs_to :categories
end
And the view:
<table>
<thead>
<tr>
<th>Title</th>
<th>Body</th>
<th>Author</th>
<th>Featured</th>
<th>Likes</th>
<th>Source</th>
<th>Category</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.body %></td>
<td><%= post.author %></td>
<td><%= post.featured %></td>
<td><%= post.likes %></td>
<td><%= post.source %></td>
<td><%= post.category.name %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
This is _form.html.erb:
<table>
<thead>
<tr>
<th>Title</th>
<th>Body</th>
<th>Author</th>
<th>Featured</th>
<th>Likes</th>
<th>Source</th>
<th>Category</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.body %></td>
<td><%= post.author %></td>
<td><%= post.featured %></td>
<td><%= post.likes %></td>
<td><%= post.source %></td>
<td><%= post.category.name %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
and _post.json.jbuilder:
json.extract! post, :id, :title, :body, :author, :featured, :likes, :source, :category_id, :created_at, :updated_at
json.url post_url(post, format: :json)
Upvotes: 2
Views: 196
Reputation: 168
Run rails g migration CreatePostCategory post:references category:references
and remove reference of category from post rails g migration RemoveCategoryFromPosts category:references
, this will look like as below.
class RemoveCategoryFromPost < ActiveRecord::Migration
def change
remove_reference :posts, :category, index: true, foreign_key: true
end
end
then run rails db:migrate
. This will work for you.
Model will remain same.
class Category < ApplicationRecord
has_and_belongs_to_many :posts
end
class Post < ApplicationRecord
has_and_belongs_to :categories
end
Upvotes: 1
Reputation: 165110
Looking at the has_and_belongs_to_many
guide, notice the references don't go into categories
nor posts
, but to a join table in the middle, in this case categories_posts
.
create_table :categories_posts, id: false do |t|
t.belongs_to :category
t.belongs_to :post
end
Or use create_join_table
to do the equivalent.
create_join_table :categories, :posts do |t|
t.index :category_id
t.index :post_id
end
And remove the reference to category in the posts table.
Upvotes: 4