Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 898
linojon Avatar asked Sep 24 '11 15:09

linojon


1 Answers

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
like image 127
Kamesh Rao Yeduvakula Avatar answered Nov 03 '22 01:11

Kamesh Rao Yeduvakula