Reputation: 2693
Good day,
I'm trying to create simple form with list of links in RoR 4 which can be edited and removed.
I've allowed "destroy" at the main post model file controller->posts.rb
class Post < ActiveRecord::Base
has_many(:links, :dependent => :destroy)
accepts_nested_attributes_for :links, :reject_if => lambda { |a| a[:link].blank? }, :allow_destroy => true
and I'm accepting the parameters for destroy at the create and update controller
def create
@new_post = Post.new(params[:post].permit(:title, :body, :tag_list, links_attributes:[:link, :_destroy]))
if @new_post.save
redirect_to posts_path, :notice =>"Saved!"
else
render new
end
end
def update
@post_to_update = Post.find(params[:id])
if @post_to_update.update(params[:post].permit(:title, :body, :tag_list, links_attributes:[:link, :_destroy]))
redirect_to posts_path, :notice =>"Updated!"
else
render edit
end
end
I'm using jQuery to remove the link field and set its destroy value as "true"
<h1> Edit post </h1>
<%= form_for @post_to_edit do |f|%>
Title <%= f.text_field :title %> </br>
Body <%= f.text_area :body %> </br>
<%= f.fields_for :links do |b| %>
<li class = "enter_link">
<%= b.text_field :link %>
<%= b.hidden_field :_destroy %>
<%= link_to_function "Remove", "remove_fields(this)" %></br>
</li>
<% end %>
Tags <%= f.text_field :tag_list %>
<%= f.submit "Update that bitch!" %>
<% end %>
Javascript
function remove_fields(link) {
$(link).prev("input[type=hidden]").val("true");
$(link).closest(".enter_link").hide();
}
And here's the problem: suppose I've got a list of 3 links
"link 1"
"link 2"
"link 3"
And I wish to edit that list by removing link number 2 and 3. once I press update the destroy parameters is passed on to the controller, but it wont delete the original lines.
Now I'll get the following list
"link 1"
"link 2"
"link 3"
**"link 1" (again, after removing link number 2 and 3)**
As always, your help is appreciated.
Upvotes: 3
Views: 4882
Reputation: 1716
change this:
def update
@post_to_update = Post.find(params[:id])
if @post_to_update.update(params[:post].permit(:title, :body, :tag_list, links_attributes:[:link, :_destroy]))
redirect_to posts_path, :notice =>"Updated!"
else
render edit
end
end
to this:
def update
@post_to_update = Post.find(params[:id])
if @post_to_update.update(
params[:post].permit(:title, :body, :tag_list,
## add `:id` to this one
links_attributes:[:id, :link, :_destroy])
##
)
redirect_to posts_path, :notice =>"Updated!"
else
render edit
end
end
you have to permit the id
in your links_attributes
params, so that the records don't get duplicated and for _destroy
to work
Upvotes: 2
Reputation: 2064
Let me make your life easier and recommend this gem called Cocoon (https://github.com/nathanvda/cocoon)
It creates simple nested forms.
Simply paste this code into your Post form view.
f.fields_for :links do |link|
render 'link_fields', :f => link
link_to_add_association 'add link', f, :tasks
With cocoon a partial is needed for the nested form, so create a file called _link_fields.html.erb
and inside make sure you place everything inside a div. Their documentation isnt clear on this, but from experience I do know its required.
<div class="nested-fields">
f.label :link
f.text_field :link
link_to_remove_association "remove link", f
</div>
And thats it!
Upvotes: 2