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?

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?

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!