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?
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 A.s
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
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 R. 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
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 A.s 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 A.s