I have two classes, Listing and Warranty. A Listing (think of it as a product) may or may not have a Warranty from a lookup table. When I want the Warranty.company for a given Listing I want to say the following: @listing = Listing.find(4) @company = @listing.warranty.company In order to do that I did the following: class Listing < ActiveRecord::Base belongs_to :warranty end and of course my Listing table has a warranty_id column. This feels wrong. For one thing, it implies a parent-child relationship and implies that any Listings with a given Warranty can/should be deleted when a Warranty is deleted. Secondly, when I *do* delete a Warranty, my Listing''s warranty_id still points to the deleted record''s ID, when it should instead be set to nil. Is there a more appropriate way to express the relationship between a class and a lookup table? -- Posted via http://www.ruby-forum.com/.
Steve > class Listing < ActiveRecord::Base > belongs_to :warranty > and of course my Listing table has a warranty_id column.> > This feels wrong.When you read ''belongs_to'', think ''references'', ''points_to''. It won''t feel wrong anymore. Alain
I believe that (depending on your DBMS) what having an "ON DELETE SET NULL" in the foreign key specification of the Listing table schema should allow your DBMS to take care of this. This is of course not a Rails solution. A raisl solution could use the "on_delete" hook (if i''m not making it up, im still quite new to Rails myself), and do something like: def on_delete self.listings.each do { |listing| listing.warranty_id = null } end There may of course be a way to do this to all the objects at once without using a block but liek I said I am new. Hope these ideas can help you. James Adams -- Posted via http://www.ruby-forum.com/.
Thanks. The latter sounds close to a sensible approach, though the callback I need is before_destroy and after setting the property to nil it needed a save(). I''ll stick with this unless a better answer comes up regarding my discomfort with using belongs_to for a relationship where I absolutely don''t ever want a cascading delete to be implied. IMO there really should be separate associations like "refers_to" and "referenced_by" to express the needs of a lookup table, even if all they essentially do is (1) override :dependent to return false at all times and (2) on deletion of a lookup table entry, nil out the fields in referring tables that pointed to the deleted entry. Here''s the relevant code I went with. It appears to work: in listing.rb: class Listing < ActiveRecord::Base belongs_to :warranty end in warranty.rb: class Warranty < ActiveRecord::Base has_many :listings before_destroy :disassociate_listings private def disassociate_listings self.listings.each { |listing| listing.warranty_id = nil listing.save } end end James Adams wrote:> I believe that (depending on your DBMS) what having an "ON DELETE SET > NULL" in the foreign key specification of the Listing table schema > should allow your DBMS to take care of this. This is of course not a > Rails solution. > > A raisl solution could use the "on_delete" hook (if i''m not making it > up, im still quite new to Rails myself), and do something like: > > def on_delete > self.listings.each do { |listing| > listing.warranty_id = null > } > end > > There may of course be a way to do this to all the objects at once > without using a block but liek I said I am new. > > Hope these ideas can help you. > > James Adams-- Posted via http://www.ruby-forum.com/.
It''s not the name that makes it feel wrong. It''s the secondary behaviors those terms imply that makes it feel wrong. "references" and "points_to" wouldn''t imply that "child" records could be deleted safely like "belongs_to/has_many" does. ;) Alain Ravet wrote:> Steve > > class Listing < ActiveRecord::Base > > belongs_to :warranty > > and of course my Listing table has a warranty_id column. >> >> This feels wrong. > > > When you read ''belongs_to'', think ''references'', ''points_to''. It won''t > feel wrong anymore. > > Alain-- Posted via http://www.ruby-forum.com/.