I am having real difficulty getting my head around the issue of setting the attribute in my join model?
My models:
class Contract < AR::Base
has_many :codelines
has_many :codes, :through => :codelines
accepts_nested_attributes_for :codes
attr_accessible :codes_attributes, :codes; :authnum, :st_date, :end_date
end
class Codeline < AR::Base
belongs_to :contract
belongs_to :code
units_alloc ...... this is the attribute I would like to set
end
class Code < AR::Base
has_many :codelines
has_many :contracts, :through => :codelines
end
The new action of my app/controllers/contracts_controller.rb
def new
@contract = Contract.new
@contract.codes.build
end
the partial for my view in app/views/contracts/_fields.html.haml
<fieldset><legend>Enter Billing Code Details</legend>
= f.fields_for :codes do |ff|
.field
= ff.label :name, "Code Name"
%br/
= ff.text_field :code_name
.field
.
.
= f.fields_for :codelines do |ff|
.field
= ff.label :name, "Units Alloc"
%br/
= ff.text_field :units_alloc, :precision => 6, :scale => 2, :size => 10
</fieldset>
From reading Rails Guides and watching railscasts #196 and #197 and researching nested attributes on the internet I came to the understanding that the @contract.codes.build line in the new action of my app/controllers/contracts_controller.rb not only built the code object but that it also built the codelines object. If I leave my new action of my app/controllers/contracts_controller.rb as above that is exactly what happens. My codelines table is populated as follows:
id contract_id code_id units_alloc
1 1 1 .... @contract.codes.build
But if you look at my view I would actually like to set units_alloc and this line @contract.codes.build does not give me access to units_alloc since it is in the codeline model. I added @contract.codelines.build to the new action of my app/controllers/contracts_controller.rb and now the units_alloc shows in my view and I am able to set it. But now I have two rows in my codelines table. One resulting from the @contract.codes.build where both the code object and codeline object are built and the second row is as a result of the @contract.codelines.build and my codelines table is as follows:
id contract_id code_id units_alloc
1 1 1 .... @contract.codes.build
2 1 80.00 .... @contract.codelines.build
Should'nt I be able to get access to units_alloc through the first build given by @contract.codes.build, where both the code object and the codeline object is built?
Does anyone know if my understanding of this issue is correct or could you point me to a resource where all will be revealed?
Just as an after thought I built the code object through codelines and I got the same result.
Thanks for any suggestions.
Update I can get my codelines table to have only one record with all the associated id's set as follows:
My console:
@contract = Contract.new(authnum: "900700", st_date: "2012-01-01", end_date:
"2012-30-06")
@contract.save
@code = Code.new(code_name: "S-5463", status: "Active", description:
"This and That")
@code.save
@codeline = @code.codelines.build(:units_alloc => "80.00", :contract => @contract)
@codeline.save
@codeline
=> #<Codeline id: 91, contract_id: 64, code_id: 54, units_alloc: 80.00>
Using pgadmin3 I check my codelines table and I get just one record, namely:
id contract_id code_id units_alloc
91 64 54 80.00
Now the test is to get my contracts_controller new/create action to do the same.
I found a solution at this site, debugging nested_forms.
It is the ninth bullet down where you read that if you are working with a has_many :through association then you need to base your nested_form on the join model or something close to that.
I quickly ran a test by refactoring some code here and there and I now have a workable nested form that serves up the correct params to the controller which in turns processes it correctly and my codelines table now has just one record.