Problem with join table in rails
I have a join model that connects Authors to Products. It's called contracts. I want to create the contract as soon as the product is created, so in my product model I have:
after_save :create_contract
def create_contract
contract = Contract.new(
:product_id => self.id,
:author_id => @author_id
)
contract.save
end
It seemed simple enough to me, but :author_id always comes up nil when it's ready to go into the database. I've tried a couple different ways of setting it, nothing seems to work. I'm guessing it's related to how I'm submitting it with the products form, which looks like this:
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :handle %><br />
<%= f.text_field :handle %>
</div>
<div class="field">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :keywords %><br />
<%= f.text_field :keywords %>
</div>
<div>
<%= collection_select( "contract", "author_id", @authors, "id", "full_name") %>
</div>
And in the controller:
def create
@author_id = params[:contract][:author_id]
@product = Product.new(params[:product])
...
end
Here's what I'm seeing in the log.
Parameters: {"utf8"=>"✓", "authenticity_token"=>"...", "product"=>{"title"=>"", "handle"=>"", "description"=>"", "keywords"=>""}, "contract"=>{"author_id"=>"1"}, "commit"=>"Create Product"}
SQL (1.1ms) INSERT INTO "products" ("created_at", "description", "handle", "keywords", "title", "updated_at") VALUES (?, ?, ?, ?, ?, ?) [["created_at", Mon, 08 Aug 2011 04:37:09 UTC +00:00], ["description", ""], ["handle", ""], ["keywords", ""], ["title", ""], ["updated_at", Mon, 08 Aug 2011 04:37:09 UTC +00:00]]
SQL (0.7ms) INSERT INTO "contracts" ("author_id", "created_at", "product_id", "updated_at") VALUES (?, ?, ?, ?) [["author_id", nil], ["created_at", Mon, 08 Aug 2011 04:37:09 UTC +00:00], ["product_id", 5], ["updated_at", Mon, 08 Aug 2011 04:37:09 UTC +00:00]]
Any ideas on where the problem is?
class Product < ActiveRecord::Base
has_many :authors, :through => :contracts
and
class Author < ActiveRecord::Base
has_many :product开发者_如何学JAVAs, :through => :contracts
and
class Contract < ActiveRecord::Base
belongs_to :author
belongs_to :product
end
So, jimworm's
nested_attributes works, with two changes:
<%= f.fields_for :contract do |c| %>
<%= c.collection_select :author_id, Author.all, :id, :name %>
<% end %>
(assuming <%= form_for(@product) do |f| %>
)
and then, in the product controller:
def new
@product = Product.new
contract = @product.contracts.build
...
Your @author_id
in create_contract
is the Product
model, and therefore not in the same scope as your controller.
Try putting the following in your models:
class Product < ActiveRecord::Base
has_one :contract, :dependent => :destroy
has_one :author, :through => :contract
accepts_nested_attributes_for :contract
end
class Contract < ActiveRecord::Base
belongs_to :product
belongs_to :author
end
class Author < ActiveRecord::Base
has_many :contracts, :dependent => :destroy
has_many :products, :through => :contracts
end
Then in your form:
...
<%= f.fields_for :contract do |c| %>
<%= c.collection_select :author_id, Author.all, :id, :name %>
<% end %>
...
Try this and see how it goes.
精彩评论