David Lee
2005-Mar-20 12:56 UTC
habtm havoc (?how to save additional cols in lookup table)
Hi all I''m a noob but I''ve done a bit of homework on this one - hope you ninja overlords can help. I''ll try to be precise in my description of the problem, which makes it a little long. So I''ve included a synopsis. Sorry for not lurking very long before posting ... Synopsis: Don''t know how to save the extra (non-id column) information contained in a has_and_belongs_to_many lookup table __ Detail: I have a recipients table & a newsletters table, with a has_and_belongs_to_many relationship (specified in both models) implemented using the lookup table newsletters_recipients. I have in this lookup table two extra columns : msg_format (html or text), and join_id. If i use plain id for this table it will clobber the id''s of the joined tables. This way i can access it readily. (http://rails.rubyonrails.com/classes/ActiveRecord/Associations/ ClassMethods.html#M000339) That''s all working. In the ''view subscriptions'' page, we display all newsletters associated with a recipient. The ''msg_format'' drop down executes this function in the controller onchange: def toggle_msg_format recipient = Recipient.find(@params["id"]) recipient.newsletters.each { |item| if item.join_id == @params["join_id"] item.msg_format = #toggle it (item.msg_format == ''html'' ? ''text'' : ''html'') if item.save render_text ''it saved'' + item.inspect end end } end So: - item.inspect shows the change applied - item.save seems to work - the database is unaffected (** this is the problem **) - I''m aware this code is more convoluted than it should be - please help there if you can __________ thanks. Links to online resources appreciated as much as anything. I''ve scoured what I know, but there may be more .. cheers DL _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
Pedro Santos
2005-Mar-20 17:10 UTC
Re: habtm havoc (?how to save additional cols in lookup table)
I am having a similar problem. See my email of yesterday to the list. After updating information in a join table, I could not find a way to save it into the database. Regards, Pedro on 05/03/20 12:56 PM, David Lee at david-4y1Gq2eXLBXvnOemgxGiVw@public.gmane.org wrote:> Hi all > > I''m a noob but I''ve done a bit of homework on this one - hope you ninja > overlords can help. I''ll try to be precise in my description of the > problem, which makes it a little long. So I''ve included a synopsis. > Sorry for not lurking very long before posting ... > > Synopsis: Don''t know how to save the extra (non-id column) information > contained in a has_and_belongs_to_many lookup table > __ > Detail: I have a recipients table & a newsletters table, with a > has_and_belongs_to_many relationship (specified in both models) > implemented using the lookup table newsletters_recipients. > > I have in this lookup table two extra columns : msg_format (html or > text), and join_id. If i use plain id for this table it will clobber > the id''s of the joined tables. This way i can access it readily. > (http://rails.rubyonrails.com/classes/ActiveRecord/Associations/ > ClassMethods.html#M000339) > > That''s all working. In the ''view subscriptions'' page, we display all > newsletters associated with a recipient. The ''msg_format'' drop down > executes this function in the controller onchange: > > def toggle_msg_format > recipient = Recipient.find(@params["id"]) > recipient.newsletters.each { |item| > if item.join_id == @params["join_id"] > item.msg_format = #toggle it > (item.msg_format == ''html'' ? ''text'' : ''html'') > if item.save > render_text ''it saved'' + item.inspect > end > end > } > end > > So: > - item.inspect shows the change applied > - item.save seems to work > - the database is unaffected (** this is the problem **) > - I''m aware this code is more convoluted than it should be - please > help there if you can > __________ > > thanks. Links to online resources appreciated as much as anything. I''ve > scoured what I know, but there may be more .. > > cheers > > DL > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
David Lee wrote:> Synopsis: Don''t know how to save the extra (non-id column) information > contained in a has_and_belongs_to_many lookup table > > I have in this lookup table two extra columns : msg_format (html or > text), and join_id. If i use plain id for this table it will clobber the > id''s of the joined tables. This way i can access it readily.has_and_belongs_to_many hides the intermediate model of a many-to-many association. It''s appropriate for simple associations, but if you have a richer model your best bet is to introduce an explicit Subscription. recipient has_many subscriptions newsletter has_many subscriptions subscription belongs_to recipient, newsletter class Subscription < ActiveRecord::Base belongs_to :recipient belongs_to :newsletter def toggle_format! self.format = format == ''html'' ? ''text'' : ''html'' end end class Recipient < ActiveRecord::Base has_many :subscriptions # Useful for read-only convenience: has_and_belongs_to_many :newsletters, :join_table => ''subscriptions'' end class Newsletter < ActiveRecord::Base has_many :subscriptions # Useful for read-only convenience: has_and_belongs_to_many :recipients, :join_table => ''subscriptions'' end class RecipientController < ApplicationController def subscriptions @subscriptions = Recipient.find(@params[''id'']).subscriptions end # Assuming this is admin interface and we can toggle any # subscription''s message format. To restrict the subscription # to a recipient, use # Recipient.find(recipient_id).subscriptions.find(id) # or # Subscription.find_by_id_and_recipient_id(id, recipient_id) # instead. def toggle_format subscription = Subscription.find(@params[''id'']) subscription.toggle_format! if subscription.save flash[:notice] = ''Toggled message format.'' else flash[:error] = ''Sorry. No toggle for you.'' end redirect_to :action => ''subscriptions'' end end jeremy
thanks Jeremy, this is perfect. D On 21/03/2005, at 7:17 AM, Jeremy Kemper wrote:> David Lee wrote: >> Synopsis: Don''t know how to save the extra (non-id column) information >> contained in a has_and_belongs_to_many lookup table >> >> I have in this lookup table two extra columns : msg_format (html or >> text), and join_id. If i use plain id for this table it will clobber >> the >> id''s of the joined tables. This way i can access it readily. > > has_and_belongs_to_many hides the intermediate model of a many-to-many > association. It''s appropriate for simple associations, but if you have > a richer model your best bet is to introduce an explicit Subscription. > recipient has_many subscriptions > newsletter has_many subscriptions > subscription belongs_to recipient, newsletter > > > class Subscription < ActiveRecord::Base > belongs_to :recipient > belongs_to :newsletter > > def toggle_format! > self.format = format == ''html'' ? ''text'' : ''html'' > end > end > > class Recipient < ActiveRecord::Base > has_many :subscriptions > > # Useful for read-only convenience: > has_and_belongs_to_many :newsletters, :join_table => ''subscriptions'' > end > > class Newsletter < ActiveRecord::Base > has_many :subscriptions > > # Useful for read-only convenience: > has_and_belongs_to_many :recipients, :join_table => ''subscriptions'' > end > > > class RecipientController < ApplicationController > def subscriptions > @subscriptions = Recipient.find(@params[''id'']).subscriptions > end > > # Assuming this is admin interface and we can toggle any > # subscription''s message format. To restrict the subscription > # to a recipient, use > # Recipient.find(recipient_id).subscriptions.find(id) > # or > # Subscription.find_by_id_and_recipient_id(id, recipient_id) > # instead. > def toggle_format > subscription = Subscription.find(@params[''id'']) > subscription.toggle_format! > if subscription.save > flash[:notice] = ''Toggled message format.'' > else > flash[:error] = ''Sorry. No toggle for you.'' > end > redirect_to :action => ''subscriptions'' > end > end > > > jeremy > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
Hi again, many thanks Jeremy, I''d more or less arrived at this myself by the time i got your reply but you helped to make sense of it all and assure me i was on the right track. I''ve done as recommended (habtm relationship is a read-only convenience). I''ve also added : primary_key ''subscription_id'' to the Subscription model. I did this because using the habtm relationship, an id in the join table will clobber the ids in the tables it joins. Now when I attempt any of> @subscriptions = Recipient.find(@params[''id'']).subscriptionsor, @recipient = Recipient.find(1) @subscriptions = @recipient.subscriptions # or .newsletters i get a: NoMethodError in Recipient#subscriptions_list undefined method `subscriptions'' for #<Recipient:0x23659f4> likewise, @recipient.inspect shows no hint of an attached subscriptions collection or one of newsletters .. any ideas why? cheers D On 21/03/2005, at 7:17 AM, Jeremy Kemper wrote:> @subscriptions = Recipient.find(@params[''id'']).subscriptions
http://rafb.net/paste/results/eRpYzS30.html ^^ code may help. thanks anyone .. D On 21/03/2005, at 7:51 PM, David Lee wrote:> Hi again, > > many thanks Jeremy, I''d more or less arrived at this myself by the > time i got your reply but you helped to make sense of it all and > assure me i was on the right track. > > I''ve done as recommended (habtm relationship is a read-only > convenience). > > I''ve also added : primary_key ''subscription_id'' to the Subscription > model. I did this because using the habtm relationship, an id in the > join table will clobber the ids in the tables it joins. > > Now when I attempt any of > >> @subscriptions = Recipient.find(@params[''id'']).subscriptions > or, > @recipient = Recipient.find(1) > @subscriptions = @recipient.subscriptions # or .newsletters > > i get a: > > NoMethodError in Recipient#subscriptions_list > > undefined method `subscriptions'' for #<Recipient:0x23659f4> > > likewise, @recipient.inspect shows no hint of an attached > subscriptions collection or one of newsletters .. > > any ideas why? > > cheers > > D > > On 21/03/2005, at 7:17 AM, Jeremy Kemper wrote: > >> @subscriptions = Recipient.find(@params[''id'']).subscriptions > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
further info: it seems its the primary key definition. Removing it solves (this) problem, though it creates more.. inference: specifying a primary key in your model **totally breaks Rails'' ability to join for you**. Is this correct? On 21/03/2005, at 8:15 PM, David Lee wrote:> http://rafb.net/paste/results/eRpYzS30.html > > ^^ code may help. thanks anyone .. > > D > > > On 21/03/2005, at 7:51 PM, David Lee wrote: > >> Hi again, >> >> many thanks Jeremy, I''d more or less arrived at this myself by the >> time i got your reply but you helped to make sense of it all and >> assure me i was on the right track. >> >> I''ve done as recommended (habtm relationship is a read-only >> convenience). >> >> I''ve also added : primary_key ''subscription_id'' to the Subscription >> model. I did this because using the habtm relationship, an id in the >> join table will clobber the ids in the tables it joins. >> >> Now when I attempt any of >> >>> @subscriptions = Recipient.find(@params[''id'']).subscriptions >> or, >> @recipient = Recipient.find(1) >> @subscriptions = @recipient.subscriptions # or .newsletters >> >> i get a: >> >> NoMethodError in Recipient#subscriptions_list >> >> undefined method `subscriptions'' for #<Recipient:0x23659f4> >> >> likewise, @recipient.inspect shows no hint of an attached >> subscriptions collection or one of newsletters .. >> >> any ideas why? >> >> cheers >> >> D >> >> On 21/03/2005, at 7:17 AM, Jeremy Kemper wrote: >> >>> @subscriptions = Recipient.find(@params[''id'']).subscriptions >> >> _______________________________________________ >> Rails mailing list >> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org >> http://lists.rubyonrails.org/mailman/listinfo/rails >> > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
On 21/03/2005, at 8:15 PM, David Lee wrote:> http://rafb.net/paste/results/eRpYzS30.html > > ^^ code may help. thanks anyone .. > > D > > > On 21/03/2005, at 7:51 PM, David Lee wrote: > >> Hi again, >> >> many thanks Jeremy, I''d more or less arrived at this myself by the >> time i got your reply but you helped to make sense of it all and >> assure me i was on the right track. >> >> I''ve done as recommended (habtm relationship is a read-only >> convenience). >> >> I''ve also added : primary_key ''subscription_id'' to the Subscription >> model. I did this because using the habtm relationship, an id in the >> join table will clobber the ids in the tables it joins. >> >> Now when I attempt any of >> >>> @subscriptions = Recipient.find(@params[''id'']).subscriptions >> or, >> @recipient = Recipient.find(1) >> @subscriptions = @recipient.subscriptions # or .newsletters >> >> i get a: >> >> NoMethodError in Recipient#subscriptions_list >> >> undefined method `subscriptions'' for #<Recipient:0x23659f4> >> >> likewise, @recipient.inspect shows no hint of an attached >> subscriptions collection or one of newsletters .. >> >> any ideas why? >> >> cheers >> >> D >> >> On 21/03/2005, at 7:17 AM, Jeremy Kemper wrote: >> >>> @subscriptions = Recipient.find(@params[''id'']).subscriptions >> >> _______________________________________________ >> Rails mailing list >> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org >> http://lists.rubyonrails.org/mailman/listinfo/rails >> > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
on 05/03/20 8:17 PM, Jeremy Kemper at jeremy-w7CzD/W5Ocjk1uMJSBkQmQ@public.gmane.org wrote:> has_and_belongs_to_many hides the intermediate model of a many-to-many > association. It''s appropriate for simple associations, but if you have > a richer model your best bet is to introduce an explicit Subscription. > recipient has_many subscriptions > newsletter has_many subscriptions > subscription belongs_to recipient, newsletter >Are you saying that if I have a Stores class and a Products class, and I want a habtm relationship that includes the quantity of each product on each store I cannot use the logical way of having a join table with store_id product_id quantity because I initially set the quantity with store.push_with_attributes(product, ''quantity'' => n) but then have no way of updating the quantity? I am a newbie, but this seems very "not rails" to me... Is there really no elegant solution in rails to such a simple situation? Can the experts on rails help here? Why isnĀ“t a method like store.products.find_by_something(??).quantity defined? Thanks, Pedro