views:

614

answers:

2

I have an Entry model and a Category model, where an Entry can have many Categories (through EntryCategories):

class Entry < ActiveRecord::Base
  belongs_to :journal

  has_many :entry_categories
  has_many :categories, :through => :entry_categories
end

class Category < ActiveRecord::Base
  has_many :entry_categories, :dependent => :destroy
  has_many :entries, :through => :entry_categories
end

class EntryCategory < ActiveRecord::Base
  belongs_to :category
  belongs_to :entry
end

When creating a new Entry, I create it by calling @journal.entries.build(entry_params), where entry_params is the parameters from the entry form. If any categories are selected, however, I get this error:

ActiveRecord::HasManyThroughCantDissociateNewRecords in Admin/entriesController#create

Cannot dissociate new records through 'Entry#entry_categories' on '#'. Both records must have an id in order to delete the has_many :through record associating them.

Note that the '#' on the second line is verbatim; it doesn't output an object.

I have tried naming my categories selectbox on the form to categories and category_ids but neither make a difference; if either is in the entry_params, the save will fail. If no categories are selected, or I remove categories from entry_params (@entry_attrs.delete(:category_ids)), the save works properly, but the categories don't save, obviously.

It seems to me that the problem is that an EntryCategory record is attempting to be made before the Entry record is saved? Shouldn't build be taking care of that?

Update:

Here's the relevant parts of schema.rb, as requested:

ActiveRecord::Schema.define(:version => 20090516204736) do

  create_table "categories", :force => true do |t|
    t.integer "journal_id",                                 :null => false
    t.string  "name",       :limit => 200,                  :null => false
    t.integer "parent_id"
    t.integer "lft"
    t.integer "rgt"
  end

  add_index "categories", ["journal_id", "parent_id", "name"], :name => "index_categories_on_journal_id_and_parent_id_and_name", :unique => true

  create_table "entries", :force => true do |t|
    t.integer  "journal_id",                                         :null => false
    t.string   "title",                                              :null => false
    t.string   "permaname",   :limit => 60,                          :null => false
    t.text     "raw_body",    :limit => 2147483647
    t.datetime "created_at",                                         :null => false
    t.datetime "posted_at"
    t.datetime "updated_at",                                         :null => false
  end

  create_table "entry_categories", :force => true do |t|
    t.integer "entry_id",    :null => false
    t.integer "category_id", :null => false
  end

  add_index "entry_categories", ["entry_id", "category_id"], :name => "index_entry_categories_on_entry_id_and_category_id", :unique => true

end

Also, saving an entry with categories works fine in the update action (by calling @entry.attributes = entry_params), so it does seem to me that the problem is only based on the Entry not existing at the point that the EntryCategory records are attempted to be created.

+1  A: 

Why do you call

self.journal.build(entry_params)

instead of

Entry.new(entry_params)

If you need to create a new entry associated to a specific Journal, given a @journal, you can do

@yournal.entries.build(entry_params)
Simone Carletti
It is actually @journal.entries.build, I messed up when typing the question, thanks for pointing that out.
Daniel Vandersluis
+1  A: 

I tracked down the cause of this error to be within the nested_has_many_through plugin. It seems that the version I had installed was buggy; after updating to the most recent version, my build works again.

Daniel Vandersluis