Getting note only the class instances but also instances of subclasses on a has_many associations

Hello,
I have a model like this:

Model

class ContainerCharge < ShipmentCharge
belongs_to :container
end

class Container < ActiveRecord::Base
has_many :container_charges
end

class HandlingContainerCharge < ContainerCharge
end
class ShippingContainerCharge < ContainerCharge
end

Controller

#Please assume here that this container has many Handling and Shipping
charges
container.container_charges # <- doesn’t return the handling and
shipping charges, only instances of the the super class
ContainerCharge

I would like the association to return all the container charges which
should be the right thing to do…
Anyone knows how to do this?

Regards,
Gam.

On Jun 15, 12:44 pm, gamov [email protected] wrote:

I would like the association to return all the container charges which
should be the right thing to do…
Anyone knows how to do this?

Does this only happen if cache_classes is set to false ?

Fred

Hi Fred,
nope, with cache_classes = true it behaves the same way…

On Jun 15, 7:57 pm, Frederick C. [email protected]

On Tue, Jun 15, 2010 at 7:57 AM, Frederick C.
[email protected] wrote:

Fred
Fred,

I don’t think that’s the issue here. It seems to me that the problem
is the two-level STI

ShippingCharge
ContainerCharge
HandlingContainerCharge
ShippingContainerCharge

So, since ContainerCharge is an STI subclass, the association

has_many :container_charges

is going to add a where clause restricting the results to those where
the type is “ContainerCharge”.

I haven’t tested it but perhaps

has_many :container_charges,
:class_name => ‘ShippingCharge’,
:conditions => {:type => %w(ContainerCharge
HandlingContainerCharge ShippingContainerCharge)}


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Github: rubyredrick (Rick DeNatale) · GitHub
Twitter: @RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

On Jun 15, 1:11 pm, Rick DeNatale [email protected] wrote:

has_many :container_charges

is going to add a where clause restricting the results to those where
the type is “ContainerCharge”.

STI is a bit funny in development mode - if the class isn’t loaded,
rails doesn’t know that it exists and so doesn’t know to include that
particular type in the where condition on type. I’ve got STI mixed
with associations in a few places and (as long as it knows that the
subclasses exist) a has_many like that does pull in subclasses. I
normally end up using require_dependency on the subclasses at the
bottom of the file defining the parent class

Fred

Hi Rick,
Of course I should have looked at the SQL query… and indeed, you are
perfectly right, Rails adds a WHERE clause on type… and it has to to
filter out the classes that are NOT involved:
SELECT count(*) AS count_all FROM “charges” WHERE
(“charges”.container_id = 1) AND ( (“charges”.“type” =
‘ContainerCharge’ ) )

Your idea is almost there, but Rails insists with the last AND clause
on the type… any idea on how to get ride of it?:
SELECT count(*) AS count_all FROM “charges” WHERE
(“charges”.container_id = 1 AND (“charges”.“type” IN
(‘ContainerCharge’,‘HandlingContainerCharge’,‘ShippingContainerCharge’)))
AND ( (“charges”.“type” = ‘ContainerCharge’ ) )

Thanks guys for your time. REALLY appreciated!
Regards,
Gam.

PS: I just realized that I didn’t specify that I’m using a STI… but
you figured it out…

On Jun 15, 5:43 pm, gamov [email protected] wrote:

Hi Rick,
Of course I should have looked at the SQL query… and indeed, you are
perfectly right, Rails adds a WHERE clause on type… and it has to to
filter out the classes that are NOT involved:
SELECT count(*) AS count_all FROM “charges” WHERE
(“charges”.container_id = 1) AND ( (“charges”.“type” =
‘ContainerCharge’ ) )

It should just be a case of ensuring all the subclasses of
container_charge are loaded

Fred

I have added:
has_many :container_charges,
:class_name => ‘Charge’,
:conditions => {:type => %w(ContainerCharge
HandlingContainerCharge ShippingContainerCharge)}

With this, Rails remove the problematic ##AND ( (“charges”.“type” = >
‘ContainerCharge’ ) ) ##. This seems like a big workaround not so
pretty but it works in the console. Now the field_for method doesn’t
see the charges in a form_for and I don’t know why… I’m almost
there!

On Jun 16, 12:47 am, Frederick C. [email protected]

I ran into problem when I wanted to mass assign via the association.
The class of the new object will be of the topclass.
The solution is here:

and in your form, use :type_helper

Now the field_for method doesn’t
see the charges in a form_for and I don’t know why… I’m almost
there!

Silly me, forgot the: accepts_nested_attributes_for :container_charges

Well, it’s hacky but it works. I’ll report here if I run into other
troubles because of this trick.

Regards,
Gam.