association id not getting set using accepts_nested_attributes_for and decent_exposure
When I post a form to create a new inquiry with a child comment (in the app, inquiries can have multiple comments), the comment is not getting built. It works when remove the presence validations. So it has to do with the order in which things are built and saved. How to preserve the validations and keep the code clean?
(The following is an example so it may not be exactly runable)
models/inquiry.rb
class Inquiry < ActiveRecord::Base
has_many :comments
accepts_nested_attributes_for :comments
models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :inquiry
belongs_to :user
validates_presence_of :user_id, :inquiry_id
controllers/inquiry_controller.rb
expose(:inquiries)
expose(:inquiry)
def new
inquiry.comments.build :user => current_user
end
def create
# inquiry.save => false
# inquiry.valid? => false
# inquiry.errors => {:"comments.inquiry_id"=>["can't be blank"]}
end
开发者_开发技巧
views/inquiries/new.html.haml
= simple_form_for inquiry do |f|
= f.simple_fields_for :comments do |c|
= c.hidden_field :user_id
= c.input :body, :label => 'Comment'
= f.button :submit
database schema
create_table "inquiries", :force => true do |t|
t.string "state"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "comments", :force => true do |t|
t.integer "inquiry_id"
t.integer "user_id"
t.text "body"
t.datetime "created_at"
t.datetime "updated_at"
end
Basically, before saving you are also testing the presence of inquiry_id, the return association from comment to inquiry, that cannot be set until the comment is saved. An alternate way to achieve this and still have your validations intact would be the following:
comment = Comment.new({:user => current_user, :body => params[:body]
comment.inquiry = inquiry
comment.save!
inquiry.comments << comment
inquiry.save!
Or an alternate way would be
= simple_form_for inquiry do |f|
= f.simple_fields_for :comments do |c|
= c.hidden_field :user_id
= c.hidden_field :inquiry_id, inquiry.id
= c.input :body, :label => 'Comment'
= f.button :submit
Basically adding the following line in your comments form
= c.hidden_field :inquiry_id, inquiry.id
精彩评论