I''m trying to use has_many :through, since my join model deserves being more than just an intersection table. But when I try to break the association, the break only seems "temporary": Let''s say my two tables are Users and Colors, and the join model is Favorites. user = Users.find(1) user.colors.length>> 2c = user.colors.first>> #<Color:....>user.colors.delete(c) user.colors.length>> 1Now what do I do here to make this persist? If I reload my page, user.colors.length == 2 again, and the old color is still a part of the collection. I''ve tried reloading the collection after deleting, hoping that would refresh the associations: user.colors(true) but I get 2 again, not 1. Any ideas? (I know, I know, I''m a moron...) Thanks Jeff -- Posted via http://www.ruby-forum.com/.
Markus Kolb
2006-Jul-10 20:36 UTC
[Rails] Re: Deleting join association of has_many :through
Jeff Cohen wrote on 10.07.2006 22:12:> I''m trying to use has_many :through, since my join model deserves being[...]> user.colors.length >>> 2 > c = user.colors.first >>> #<Color:....> > > user.colors.delete(c) > user.colors.length >>> 1 > > Now what do I do here to make this persist? > > If I reload my page, user.colors.length == 2 again, and the old color is > still a part of the collection.I think there is a problem in your table relations. :through: Specifies a Join Model to perform the query through. Options for :class_name and :foreign_key are ignored, as the association uses the source reflection. You can only use a :through query through a belongs_to or has_many association. Have you noticed the last sentence?
Jeff Cohen
2006-Jul-10 20:47 UTC
[Rails] Re: Deleting join association of has_many :through
Markus Kolb wrote:> > :through: Specifies a Join Model to perform the query through. Options > for :class_name and :foreign_key are ignored, as the association uses > the source reflection. You can only use a :through query through a > belongs_to or has_many association. > > Have you noticed the last sentence?I think I''m doing it right. class User has_many :favorites has_many :colors, :through => :favorites end class Color has_many :favorites has_many :users, :through => :favorites end class Favorite belongs_to :user belongs_to :color end Are you saying I''ve still got the relationships wrong somehow? def delete_color color = Color.find(params[:color_id]) user.colors.delete(color) # this works in script/console as expected # at this point, user.colors.length is correct redirect :action => :show # this will show 2 favorite colors again: user.colors.length is wrong end -- Posted via http://www.ruby-forum.com/.
Rick Olson
2006-Jul-10 22:35 UTC
[Rails] Re: Deleting join association of has_many :through
> Are you saying I''ve still got the relationships wrong somehow? > > def delete_color > color = Color.find(params[:color_id]) > user.colors.delete(color) # this works in script/console as expected > # at this point, user.colors.length is correct > redirect :action => :show # this will show 2 favorite colors again: > user.colors.length is wrong > end >You''ll want to delete the Favorite object that joins them. user.favorites.find_by_color_id(params[:color_id]).destroy -- Rick Olson http://techno-weenie.net
Markus Kolb
2006-Jul-11 00:27 UTC
[Rails] Re: Deleting join association of has_many :through
Rick Olson wrote on 11.07.2006 00:34:>> Are you saying I''ve still got the relationships wrong somehow? >> >> def delete_color >> color = Color.find(params[:color_id]) >> user.colors.delete(color) # this works in script/console as expected >> # at this point, user.colors.length is correct >> redirect :action => :show # this will show 2 favorite colors again: >> user.colors.length is wrong >> end >> > > You''ll want to delete the Favorite object that joins them. > > user.favorites.find_by_color_id(params[:color_id]).destroy >But it should be possible over colors collection, too. Do you need a user.colors.save afterwards?
Jeff Cohen
2006-Jul-11 01:33 UTC
[Rails] Re: Deleting join association of has_many :through
Markus Kolb wrote:> Rick Olson wrote on 11.07.2006 00:34: >> >> You''ll want to delete the Favorite object that joins them. >> >> user.favorites.find_by_color_id(params[:color_id]).destroy >> > > But it should be possible over colors collection, too. > Do you need a user.colors.save afterwards?user.colors.save isn''t possible (method missing), but that was a good clue. user.save! does the trick. Thanks Markus! Jeff softiesonrails.com -- Posted via http://www.ruby-forum.com/.
Markus Kolb
2006-Jul-11 12:46 UTC
[Rails] Re: Deleting join association of has_many :through
Jeff Cohen wrote on 11.07.2006 03:33:> Markus Kolb wrote: >> Rick Olson wrote on 11.07.2006 00:34: >>> You''ll want to delete the Favorite object that joins them. >>> >>> user.favorites.find_by_color_id(params[:color_id]).destroy >>> >> But it should be possible over colors collection, too. >> Do you need a user.colors.save afterwards? > > user.colors.save isn''t possible (method missing), but that was a good > clue. > > user.save! does the trick.Can you have a look in the log? I''m interested in what SQL commands are executed on this save if only colors association changed and no other user data. Does it only update the association to colors or everything from user model? Thanks Markus
Hi, i have a situation similar to this: class User has_many :favorites has_many :colors, :through => :favorites end class Color has_many :favorites has_many :users, :through => :favorites end class Favorite belongs_to :user belongs_to :color end When i need to destroy a favorite association, i find it like this: fav = user.favorites.find_by_color_id(color_id]) but i cannot destroy it: calling "fav.destroy" raises a SQL error, because there is no ID field in table Favorite. How should that fav be deleted ? Thanks, Marcus -- Posted via http://www.ruby-forum.com/.
On 7/21/06, Marcus Ob <mrqzzz@yahoo.it> wrote:> Hi, > i have a situation similar to this: > > class User > has_many :favorites > has_many :colors, :through => :favorites > end > > class Color > has_many :favorites > has_many :users, :through => :favorites > end > > class Favorite > belongs_to :user > belongs_to :color > end > > > When i need to destroy a favorite association, i find it like this: > fav = user.favorites.find_by_color_id(color_id]) > > but i cannot destroy it: > calling "fav.destroy" raises a SQL error, because there is no ID field > in table Favorite. > > How should that fav be deleted ? > > Thanks, > Marcus > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >user.favorites.destroy_all(["color_id=?", color_id])
Josh Susser
2006-Jul-21 21:01 UTC
[Rails] Re: Deleting join association of has_many :through
Marcus Ob wrote:> Hi, > i have a situation similar to this: > > class User > has_many :favorites > has_many :colors, :through => :favorites > end > > class Color > has_many :favorites > has_many :users, :through => :favorites > end > > class Favorite > belongs_to :user > belongs_to :color > end > > > When i need to destroy a favorite association, i find it like this: > fav = user.favorites.find_by_color_id(color_id]) > > but i cannot destroy it: > calling "fav.destroy" raises a SQL error, because there is no ID field > in table Favorite. > > How should that fav be deleted ?If you have no :id field, then your join model is broken. You need an :id in favorites for has_many :through to work right. -- Josh Susser http://blog.hasmanythrough.com -- Posted via http://www.ruby-forum.com/.
Marcus Ob
2006-Jul-21 21:57 UTC
[Rails] Re: Deleting join association of has_many :through
Pat Maddox wrote:> On 7/21/06, Marcus Ob <mrqzzz@yahoo.it> wrote: >> has_many :users, :through => :favorites >> >> Posted via http://www.ruby-forum.com/. >> _______________________________________________ >> Rails mailing list >> Rails@lists.rubyonrails.org >> http://lists.rubyonrails.org/mailman/listinfo/rails >> > > user.favorites.destroy_all(["color_id=?", color_id])Thank you, but it''s not working: I tried user.favorites.destroy_all(["color_id=?", color_id]) But it raises an error: "wrong number of arguments (1 for 0)". Without arguments, it wont complain user.favorites.destroy_all But i get an error because there is no ID column: Mysql::Error: #42S22Unknown column ''id'' in ''where clause'': DELETE FROM favorites WHERE id = NULL The only thing working is user.colors.clear which deletes all favorite colors of user, but i don''t want to clear *all* records, only a specific one. Any other ideas? Thanks, Marcus. -- Posted via http://www.ruby-forum.com/.
Marcus Ob
2006-Jul-21 21:59 UTC
[Rails] Re: Deleting join association of has_many :through
Josh Susser wrote:> Marcus Ob wrote: >> Hi, >> i have a situation similar to this: >> >> class User >> has_many :favorites >> has_many :colors, :through => :favorites >> end >> >> class Color >> has_many :favorites >> has_many :users, :through => :favorites >> end >> >> class Favorite >> belongs_to :user >> belongs_to :color >> end >> >> >> When i need to destroy a favorite association, i find it like this: >> fav = user.favorites.find_by_color_id(color_id]) >> >> but i cannot destroy it: >> calling "fav.destroy" raises a SQL error, because there is no ID field >> in table Favorite. >> >> How should that fav be deleted ? > > If you have no :id field, then your join model is broken. You need an > :id in favorites for has_many :through to work right. > > -- > Josh Susser > http://blog.hasmanythrough.comI have id fields in both master tables (users and colors) and the join table (favorites) has a pk composed by the two fields user_id+color_id Is that wrong? Thanks, Marcus. -- Posted via http://www.ruby-forum.com/.
Pat Maddox
2006-Jul-21 22:14 UTC
[Rails] Re: Deleting join association of has_many :through
On 7/21/06, Marcus Ob <mrqzzz@yahoo.it> wrote:> Pat Maddox wrote: > > On 7/21/06, Marcus Ob <mrqzzz@yahoo.it> wrote: > > user.favorites.destroy_all(["color_id=?", color_id]) > > > Thank you, but it''s not workingSorry, it should be delete_all As far as using composite primary keys...don''t. Sounds like you''re creating a rails app from scratch, so there''s no reason at all you should be using them. Pat
Marcus Ob
2006-Jul-21 22:24 UTC
[Rails] Re: Re: Deleting join association of has_many :through
Pat Maddox wrote:> On 7/21/06, Marcus Ob <mrqzzz@yahoo.it> wrote: >> Pat Maddox wrote: >> > On 7/21/06, Marcus Ob <mrqzzz@yahoo.it> wrote: >> > user.favorites.destroy_all(["color_id=?", color_id]) >> >> >> Thank you, but it''s not working > > Sorry, it should be delete_all > > As far as using composite primary keys...don''t. Sounds like you''re > creating a rails app from scratch, so there''s no reason at all you > should be using them. > > PatSo using has_many_through, should i use set the pk to an id field for table "favorites", and leave color_id and user_id as fk ? I was using a composite pk color_id+user_id in favorites table because it was explained to do so for HABTM. Thanks, Marcus. -- Posted via http://www.ruby-forum.com/.
Pat Maddox
2006-Jul-21 22:30 UTC
[Rails] Re: Re: Deleting join association of has_many :through
On 7/21/06, Marcus Ob <mrqzzz@yahoo.it> wrote:> Pat Maddox wrote: > > On 7/21/06, Marcus Ob <mrqzzz@yahoo.it> wrote: > >> Pat Maddox wrote: > >> > On 7/21/06, Marcus Ob <mrqzzz@yahoo.it> wrote: > >> > user.favorites.destroy_all(["color_id=?", color_id]) > >> > >> > >> Thank you, but it''s not working > > > > Sorry, it should be delete_all > > > > As far as using composite primary keys...don''t. Sounds like you''re > > creating a rails app from scratch, so there''s no reason at all you > > should be using them. > > > > Pat > > So using has_many_through, should i use set the pk to an id field for > table "favorites", and leave color_id and user_id as fk ?Yes. You will also probably want to make a multicolumn index on color_id and user_id for performance reasons. This is really a secondary concern though and you shouldn''t do that until you see how you''re actually using the table. Pat
Marcus Ob
2006-Jul-21 22:58 UTC
[Rails] Re: Re: Re: Deleting join association of has_many :through
Pat Maddox wrote:> On 7/21/06, Marcus Ob <mrqzzz@yahoo.it> wrote: >> > >> > As far as using composite primary keys...don''t. Sounds like you''re >> > creating a rails app from scratch, so there''s no reason at all you >> > should be using them. >> > >> > Pat >> >> So using has_many_through, should i use set the pk to an id field for >> table "favorites", and leave color_id and user_id as fk ? > > Yes. > > You will also probably want to make a multicolumn index on color_id > and user_id for performance reasons. This is really a secondary > concern though and you shouldn''t do that until you see how you''re > actually using the table. > > PatPat (and Josh), thank you very much, that solved my user.favorites.find_by_color_id(color_id).destroy I am still stuck in the user.favorites << Color.find_by_id(some_id) user.save which does not save any record. Any suggestions? Thanks for the great help. Marcus. -- Posted via http://www.ruby-forum.com/.
Pat Maddox
2006-Jul-21 23:09 UTC
[Rails] Re: Re: Re: Deleting join association of has_many :through
On 7/21/06, Marcus Ob <mrqzzz@yahoo.it> wrote:> Pat Maddox wrote: > > On 7/21/06, Marcus Ob <mrqzzz@yahoo.it> wrote: > >> > > >> > As far as using composite primary keys...don''t. Sounds like you''re > >> > creating a rails app from scratch, so there''s no reason at all you > >> > should be using them. > >> > > >> > Pat > >> > >> So using has_many_through, should i use set the pk to an id field for > >> table "favorites", and leave color_id and user_id as fk ? > > > > Yes. > > > > You will also probably want to make a multicolumn index on color_id > > and user_id for performance reasons. This is really a secondary > > concern though and you shouldn''t do that until you see how you''re > > actually using the table. > > > > Pat > > Pat (and Josh), thank you very much, that solved my > user.favorites.find_by_color_id(color_id).destroy > > I am still stuck in the > user.favorites << Color.find_by_id(some_id) > user.save > which does not save any record. > > Any suggestions? > Thanks for the great help. > Marcus. > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >disclaimer: I still haven''t used has_many :through yet. Maybe the code you showed is supposed to work, I''m not sure. Anyway, it ought to be user.favorites << Favorite.new(:color => Color.find(some_id)) If you''re just creating the favorite at that point in time and won''t be using the favorites method, you should just do Favorite.create(:user => user, :color => Color.find(some_id)) You might be able to do user.colors << Color.find(some_id) but again, since that would rely on has_many :through, I''m not sure. Pat
Josh Susser
2006-Jul-21 23:32 UTC
[Rails] Re: Re: Re: Deleting join association of has_many :through
Marcus Ob wrote:> Pat (and Josh), thank you very much, that solved my > user.favorites.find_by_color_id(color_id).destroyAll tables in Rails except for habtm need a single column pk. You can create indexes as you will, but the pk must be a single column, and if you can go with the default of an auto-inc int named :id things will be much easier for you.> I am still stuck in the > user.favorites << Color.find_by_id(some_id) > user.save > which does not save any record.That''s just the way has_many :through is. Read this: http://blog.hasmanythrough.com/articles/2006/04/17/join-models-not-proxy-collections -- Josh Susser http://blog.hasmanythrough.com -- Posted via http://www.ruby-forum.com/.
Marcus Ob
2006-Jul-21 23:49 UTC
[Rails] Re: Re: Re: Deleting join association of has_many :through
Josh Susser wrote:> Marcus Ob wrote: >> Pat (and Josh), thank you very much, that solved my >> user.favorites.find_by_color_id(color_id).destroy > > All tables in Rails except for habtm need a single column pk. You can > create indexes as you will, but the pk must be a single column, and if > you can go with the default of an auto-inc int named :id things will be > much easier for you. > >> I am still stuck in the >> user.favorites << Color.find_by_id(some_id) >> user.save >> which does not save any record. > > That''s just the way has_many :through is. Read this: > http://blog.hasmanythrough.com/articles/2006/04/17/join-models-not-proxy-collections > > -- > Josh Susser > http://blog.hasmanythrough.comI see, thank you Josh. And thank you Pat. I guess perhaps this is the code to add a new favorite: fav=Favorite.new(:user_id=>user.id, :color_id=>some_color.id) fav.save Best regards, Marcus. -- Posted via http://www.ruby-forum.com/.