collection.delete(object, …) - removes one or more objects from the
collection by setting their foreign keys to NULL. This will also
destroy the objects if they’re declared as belongs_to and dependent
on this model.
Where collection is @recipe.additions in my example. Even using
destroy rails is still looking for an addition.id, which isn’t
necessary for a join table. I ended up adding an id column to my join
table and I’ll figure it out later. ;-(
Dumb question here, and perhaps a little off topic, but in trying to
understand the “has_many :ingredients, :through => :additions” which
table does additions belong to? (My question is one of my own not
understanding ‘has_many:through’) .Is there a recipes.additions which
equals ingredients.id ? And if so, why would you use ‘through’ and not
‘foreign_key’
-Ralph V.
class Recipe < ActiveRecord::Base
has_many :additions
has_many :ingredients, :through => :additions
end
class Ingredient < ActiveRecord::Base
has_many :additions
has_many :recipes, :through => :additions
end
has_many :additions
has_many :ingredients, :through => :additions
end
class Ingredient < ActiveRecord::Base
has_many :additions
has_many :recipes, :through => :additions
end
Don’t forget the additions model
class Addition < ActiveRecrod::Base
belongs_to :recipe
belongs_to :ingredient
end
Additions is a model all by itself. has_many :through exists to
augment a has_and_belongs_to with extra data. The additions table
replaces the intermediary table ingredients_recipes that would be used
in a h&btm. It gets its own file in the models directory and you can
add any extra data to the table you want.
For example, when you add an ingredient to your recipe you usually add
it in an amount (eg, 2 Tbs). That data is stored in the additions
table now.
recipe.additions is an array of all the additions - the rows from the
additions table that belong to the recipe. You can then call
recipe.additions[0].ingredient to access the first ingredient.
recipe.additions[0].amount would get you the amount of the first
ingredient you added to the recipe.
The delete method is different from destroy in that it deletes the item
without instantiating it first (and so skips any callbacks, dependency
checking etc., which is which destroy is generally preferred in rails
unless there’s a specific reason you want to skip them). Also the delete
method you’re referring to is a class method, which is why it needs an
id (or an array of them). There’s nothing to stop you from using this,
but having found the object through @recipe.additions.find(:first,…)
it makes sense to destroy (or delete if you prefer) the object, rather
than using the class method which essentially does the find again. IMHO
it’s more elegant (and more idiomatic Rails). See: ActiveRecord::Base for
details of this instance method:
Deletes the record in the database and freezes this instance to
reflect that no changes should be made (since they can?t be
persisted).
Re the id column, yes that’s right – you must have an id column on the
association table (in fact all tables, except has_and_belongs_to_many
join tables) for has_many :through to work, as it’s a model in it’s own
right.
HTH
Chris
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.