ActiveRecord STI not restricting type in queries

I have the following models:

class Address < ActiveRecord::Base
validates_format_of :zip, :with => /\A[0-9]{5}\z/, :allow_blank =>
false
validates_presence_of :address1
validates_presence_of :state
belongs_to :user
end

the inherited records are in a subdirectory

class Addresses::ShipFromAddress < Address
belongs_to :transaction
end

class Addresses::ShipToAddress < Address
belongs_to :transaction
end

class Transaction < ActiveRecord::Base
has_one :ship_to_address, :class_name => “Address”, :dependent =>
:destroy
has_one :ship_from_address, :class_name => “Address”, :dependent =>
:destroy
end

I can access transaction.ship_to_address and
transaction.ship_from_address but the query that’s generated for both
is:
SELECT addresses.* FROM addresses WHERE addresses.transaction_id
= 5 LIMIT 1

There’s no expected type constraint.

However, if I do:
Addresses::ShipToAddress.find_by_transaction_id(5) the query is correct
as:
SELECT addresses.* FROM addresses WHERE addresses.type IN
(‘Addresses::ShipToAddress’) AND addresses.transaction_id = 5 LIMIT
1

I have the workaround but it bugs me that the
transaction.ship_to_address doesn’t work correctly. The one thing that
may be wonky is that I’m putting “non-typed” ActiveRecord superclass
entries into addresses but that shouldn’t be an issue?

On Oct 17, 3:20pm, “Dave G.” [email protected] wrote:

as:
SELECT addresses.* FROM addresses WHERE addresses.type IN
(‘Addresses::ShipToAddress’) AND addresses.transaction_id = 5 LIMIT
1

I have the workaround but it bugs me that the
transaction.ship_to_address doesn’t work correctly. The one thing that
may be wonky is that I’m putting “non-typed” ActiveRecord superclass
entries into addresses but that shouldn’t be an issue?

You’ve told active record that ship_to_address is just a regular
address (since you’ve got class_name => ‘Address’), so active record
believes you. If ship_to_address should only ever by a
Addresses::ShipToAddress then you need to let active record know.

Fred

That doesn’t work. I was under the impression that if the ActiveRecord
class name wasn’t obvious that it needed to be specified. In fact, if I
take that out, I get errors about Addresses::ShipToAddress not being a
defined constant when trying transaction.ship_to_address.

Maybe I need so specify the :class to be Adddresses::ShipToAddress? But
that doesn’t make a whole lot of sense to me because that, specifically,
is derivable from “has_one :ship_to_address” and I don’t understand
what the syntax would be anyway.

Ok, that DOES work. I don’t know what I was doing but I thought I tried
that several times.

My coworker looked at it and had me try it again and voila, the line is:

has_one :ship_to_address, :class_name => ‘Addresses::ShipToAddress’,
:dependent => :destroy

Thank you!