Belongs_to and lookup tables

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. :wink:

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