Hi Rails-talkers, I am having some trouble finding the right way to delete a relationship in a has_many :through. I''m running on edge rails here. 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 class Addition < ActiveRecord::Base belongs_to :recipe belongs_to :ingredient end In my controller: def dropingredient ingredient = @recipe.additions.find( :first, :conditions => [''ingredient_id = ? AND amount = ?'', params[:iid].to_i, params[:amount].to_f] ) @recipe.additions.delete(ingredient) redirect_to :action => ''show'', :id => @recipe.id end Produces this: Mysql::Error: Unknown column ''id'' in ''where clause'': UPDATE additions SET recipe_id = NULL WHERE (recipe_id = 16 AND id IN (NULL)) What am I missing? Thanks, --Dean - Unscrambler of eggs --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
Haven''t use has_many :through much, so I may have got this wrong, but don''t you want to be doing something like: def dropingredient @recipe.additions.find( :first, :conditions => [''ingredient_id = ? AND amount = ?'', params[:iid].to_i, params[:amount].to_f] ).destroy redirect_to :action => ''show'', :id => @recipe.id end My suggestion would be to walk back the cat through the console, checking the result of each step. It''s saved me more times than I can remember. So: >> @recipe >> @recipe.additions >> @recipe.additions(:first, :conditions => [''ingredient_id = 16 AND amount = 2'']) >> @recipe.additions(:first, :conditions => [''ingredient_id = 16 AND amount = 2'']).destroy HTH Dean wrote:> Hi Rails-talkers, > > I am having some trouble finding the right way to delete a relationship > in a > has_many :through. I''m running on edge rails here. > > 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 > > class Addition < ActiveRecord::Base > belongs_to :recipe > belongs_to :ingredient > end > > In my controller: > > def dropingredient > ingredient = @recipe.additions.find( :first, > :conditions => [''ingredient_id = ? AND amount = ?'', > params[:iid].to_i, > params[:amount].to_f] ) > @recipe.additions.delete(ingredient) > redirect_to :action => ''show'', :id => @recipe.id > end > > Produces this: > > Mysql::Error: Unknown column ''id'' in ''where clause'': UPDATE additions > SET > recipe_id = NULL WHERE (recipe_id = 16 AND id IN (NULL)) > > What am I missing? > > Thanks, > --Dean - Unscrambler of eggs > > > > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
Chris T wrote:> Haven''t use has_many :through much, so I may have got this wrong, but > don''t you want to be doing something like: > > def dropingredient > @recipe.additions.find( :first, > :conditions => [''ingredient_id = ? AND amount = ?'', > params[:iid].to_i, params[:amount].to_f] ).destroy > redirect_to :action => ''show'', :id => @recipe.id > end > > My suggestion would be to walk back the cat through the console, > checking the result of each step. It''s saved me more times than I can > remember. So: > >> @recipe > >> @recipe.additions > >> @recipe.additions(:first, :conditions => [''ingredient_id = 16 AND > amount = 2'']) > >> @recipe.additions(:first, :conditions => [''ingredient_id = 16 AND > amount = 2'']).destroy > > HTHThe doc for has_many lists is a delete method: http://api.rubyonrails.com/classes/ActiveRecord/Associations/ClassMethods.html#M000530 # 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. ;-( --Dean> Dean wrote: > > Hi Rails-talkers, > > > > I am having some trouble finding the right way to delete a relationship > > in a > > has_many :through. I''m running on edge rails here. > > > > 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 > > > > class Addition < ActiveRecord::Base > > belongs_to :recipe > > belongs_to :ingredient > > end > > > > In my controller: > > > > def dropingredient > > ingredient = @recipe.additions.find( :first, > > :conditions => [''ingredient_id = ? AND amount = ?'', > > params[:iid].to_i, > > params[:amount].to_f] ) > > @recipe.additions.delete(ingredient) > > redirect_to :action => ''show'', :id => @recipe.id > > end > > > > Produces this: > > > > Mysql::Error: Unknown column ''id'' in ''where clause'': UPDATE additions > > SET > > recipe_id = NULL WHERE (recipe_id = 16 AND id IN (NULL)) > > > > What am I missing? > > > > Thanks, > > --Dean - Unscrambler of eggs > > > > > > > > > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
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: http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M000907 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 Dean wrote:> Chris T wrote: > >> Haven''t use has_many :through much, so I may have got this wrong, but >> don''t you want to be doing something like: >> >> def dropingredient >> @recipe.additions.find( :first, >> :conditions => [''ingredient_id = ? AND amount = ?'', >> params[:iid].to_i, params[:amount].to_f] ).destroy >> redirect_to :action => ''show'', :id => @recipe.id >> end >> >> My suggestion would be to walk back the cat through the console, >> checking the result of each step. It''s saved me more times than I can >> remember. So: >> >> @recipe >> >> @recipe.additions >> >> @recipe.additions(:first, :conditions => [''ingredient_id = 16 AND >> amount = 2'']) >> >> @recipe.additions(:first, :conditions => [''ingredient_id = 16 AND >> amount = 2'']).destroy >> >> HTH >> > > The doc for has_many lists is a delete method: > > http://api.rubyonrails.com/classes/ActiveRecord/Associations/ClassMethods.html#M000530 > > # 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. ;-( > > --Dean > > >> Dean wrote: >> >>> Hi Rails-talkers, >>> >>> I am having some trouble finding the right way to delete a relationship >>> in a >>> has_many :through. I''m running on edge rails here. >>> >>> 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 >>> >>> class Addition < ActiveRecord::Base >>> belongs_to :recipe >>> belongs_to :ingredient >>> end >>> >>> In my controller: >>> >>> def dropingredient >>> ingredient = @recipe.additions.find( :first, >>> :conditions => [''ingredient_id = ? AND amount = ?'', >>> params[:iid].to_i, >>> params[:amount].to_f] ) >>> @recipe.additions.delete(ingredient) >>> redirect_to :action => ''show'', :id => @recipe.id >>> end >>> >>> Produces this: >>> >>> Mysql::Error: Unknown column ''id'' in ''where clause'': UPDATE additions >>> SET >>> recipe_id = NULL WHERE (recipe_id = 16 AND id IN (NULL)) >>> >>> What am I missing? >>> >>> Thanks, >>> --Dean - Unscrambler of eggs >>> >>> >>> >>> > > > > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
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 Vince 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 --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
Ike wrote:> 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 Vince > > 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 > endDon''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. HTH, --Dean --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---