0

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 :products, :through => :contracts

and

class Contract < ActiveRecord::Base
  belongs_to :author
  belongs_to :product
end
5
  • And I wanted to add, that when I set the author_id directly in the model, as opposed to an instance variable, it was still coming up nil. Commented Aug 11, 2011 at 16:31
  • You can edit your question if you want to update it :) Could you show the complete models you made, or just show how you made the association between them (if they are too big)? I suppose there is something wrong over there. Commented Aug 11, 2011 at 16:35
  • It was just quicker to hit the comment button. I've added the associations. Commented Aug 11, 2011 at 16:39
  • Uhm, maybe it's the has_many: contracts line I'm missing? Commented Aug 11, 2011 at 16:40
  • Yeah, that wasn't it. Still not working. Commented Aug 11, 2011 at 16:46

2 Answers 2

1

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
 ...
Sign up to request clarification or add additional context in comments.

Comments

0

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.

1 Comment

It's not creating the contract at all this way, which is weird.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.