Reputation: 1991
RAILS 5 PROBLEM. I have a project and I wanted the user to have the option to add extra items to the form. My code renders correctly and it the link to add more fields does add more text field. The problem I have is that is not saving the to my database. I am using mysql2 gem on a MySQl database. I posted the console output. This is what I have:
forms_controller
# forms_controller.rb
def new
@form = Form.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @form }
end
end
def create
@form = Form.new(form_params)
respond_to do |format|
if @form.save
format.html { redirect_to(@form, :notice => 'form was successfully created.') }
format.xml { render :xml => @form, :status => :created, :location => @form }
else
format.html { render :action => "new" }
format.xml { render :xml => @form.errors, :status => :unprocessable_entity }
end
end
end
def form_params
params.require(:form).permit(:name, items_attributes: [:id, :item_name, :_destroy])
end
models
# form.rb
class Form < ApplicationRecord
has_many :items
accepts_nested_attributes_for :items, reject_if: :all_blank, allow_destroy: true
validates_presence_of :name
end
# item.rb
class Item < ApplicationRecord
belongs_to :form
end
views
<!-- _form.html.haml -->
= form_for @form do |f|
.field
= f.label :name
%br
= f.text_field :name
%h3 items
#items
= f.fields_for :items do |item|
= render 'item_fields', f: item
.links
= link_to_add_association 'add item', f, :items
= f.submit
.nested-fields
.field
= f.label :item_name
%br
= f.text_field :item_name
= link_to_remove_association "remove item", f
console
tarted POST "/forms" for 127.0.0.1 at 2016-09-08 23:04:17 -0600
Processing by FormsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"FmYPwlXy93iwBMkWvfyd3QJ+NKDcYnraUaKmMISbUIX3+KRL7KtpD33FW3CK+jxvn4AoUUMhx4zrGncJej5BOw==", "form"=>{"name"=>"sfsf", "items_attributes"=>{"1473397456358"=>{"item_name"=>"sfsf", "_destroy"=>"false"}}}, "commit"=>"Create Form"}
(0.2ms) BEGIN
(0.3ms) ROLLBACK
Rendering forms/new.html.haml within layouts/application
Rendered forms/_item_fields.html.haml (1.5ms)
Rendered forms/_item_fields.html.haml (1.2ms)
Rendered forms/_form.html.haml (8.5ms)
Rendered forms/new.html.haml within layouts/application (10.1ms)
Completed 200 OK in 68ms (Views: 54.5ms | ActiveRecord: 0.5ms)
Upvotes: 1
Views: 687
Reputation: 301
In Rails 5, whenever we define a belongs_to association, it is required to have the associated record present by default after this change.
It triggers validation error if associated record is not present.
class User < ApplicationRecord
end
class Post < ApplicationRecord
belongs_to :user
end
post = Post.create(title: 'Hi')
=> <Post id: nil, title: "Hi", user_id: nil, created_at: nil, updated_at: nil>
post.errors.full_messages.to_sentence
=> "User must exist"
****Opting out of this default behavior in Rails 5****
We can pass optional: true to the belongs_to association which would remove this validation check.
class Post < ApplicationRecord
belongs_to :user, optional: true
end
post = Post.create(title: 'Hi')
=> <Post id: 2, title: "Hi", user_id: nil>
Upvotes: 2
Reputation: 1991
The reason it wouldn't save is because I was using Rails 5 and I needed to add optional: true
to the belongs_to in the item model.
# form.rb
class Form < ApplicationRecord
has_many :items
accepts_nested_attributes_for :items, reject_if: :all_blank, allow_destroy: true
validates_presence_of :name
end
# item.rb
class Item < ApplicationRecord
belongs_to :form , optional: true
end
Upvotes: 1
Reputation: 27747
in your permit/require line (in your controller), item_attribute
should probably be item_attributes
(there's more than one) ie:
def form_params
params.require(:form).permit(:name, :date_sent, :quantity, :comment, item_attributes: [:id, :name, :form_id, :_destroy])
end
Upvotes: 2