Reputation: 3515
Hi I'm having trouble by making the update and destroy method in my posts_controller, I'm able to create new Posts but I'm not able to update and I want to know how to destroy the model while destroying all the associations with the other model it.
My models: Post Model
class Post < ApplicationRecord
has_many :comments, dependent: :destroy
has_many :has_categories
has_many :categories, through: :has_categories
validates :title, presence: true,
length: { minimum: 5 }
after_create :save_categories
def categories=(value)
@categories = value
end
private
def save_categories
@categories.each do |category_id|
HasCategory.create(category_id: category_id, post_id: self.id)
end
end
end
Has_Category model
class HasCategory < ApplicationRecord
belongs_to :post
belongs_to :category
end
Category Model
class Category < ApplicationRecord
validates :name, presence: true
has_many :has_categories
has_many :posts, through: :has_categories
end
So in my partial form for the new and the edit actions is like this
<%= form_with model: @post, local: true do |form| %>
<!--Inputs before the categories-->
<div>
<label>Categories</label>
<% @categories.each do |category| %>
<div>
<%= check_box_tag "categories[]", category.id %> <%= category.name %>
</div>
<% end %>
</div>
<div>
<%= form.submit %>
</div>
<% end %>
My posts_controller create and update method
def create
@post = Post.new(post_params)
@post.categories = params[:categories]
if @post.save
redirect_to @post
else
render :new
end
end
def update
@post = Post.find(params[:id])
@post.categories = params[:categories]
if @post.update(post_params)
redirect_to @post
else
render :edit
end
end
My create action is working but the update action is just updating the inputs before the check_box_tag. I know that the save_categories method on my Post model is the one who is taking the array I'm receiving from the form and creating the HasCategory association, How should I make the update action or even the destroy action given the situation that Is a many to many association?
Upvotes: 0
Views: 528
Reputation: 4640
The line has_many :categories, through: :has_categories
gives you category_ids
for post. So you can change your form:
<%= form_with model: @post, local: true do |form| %>
<!--Inputs before the categories-->
<div>
<label>Categories</label>
<%= f.collection_check_boxes(:category_ids, @categories, :id, :name)
</div>
<div>
<%= form.submit %>
</div>
<% end %>
and controller:
def create
# you need it here for correct rerendering `new` on validation error
@categories = Category.all # or maybe you have here more complicated query
@post = Post.new(post_params)
if @post.save
redirect_to @post
else
render :new
end
end
def update
# you need it here for correct rerendering `edit` on validation error
@categories = Category.all # or maybe you have here more complicated query
@post = Post.find(params[:id])
if @post.update(post_params)
redirect_to @post
else
render :edit
end
end
private
def post_params
params.require(:post).permit(:name, :some_other_post_params, category_ids: [])
end
You need to remove callback and categories=(value)
method from the Post model. And define @categories
in the new
and edit
actions. If it equals Category.all
you can just put it to the form: f.collection_check_boxes(:category_ids, Category.all, :id, :name)
, without defining @variable
Upvotes: 0