Eager loading ActiveRecord objects

I have a complex graph of ActiveRecord entities that I want to load with
one big honkin’ join query to avoid ripple loading. It’s for a report.
However :include doesn’t get me all the way there because I want to load
parents of parents (or children of children). I don’t mind doing the
SQL by hand but I’m not quite sure what to do to get the result set into
my model objects. I don’t want to bypass my model objects because they
have important calculation methods I need.

I’d like to run a raw SQL query and then somehow plug the results into
model objects. Sooo, what’s the best way to go about this?

Thanks!

Steve

Stephen M. wrote:

However :include doesn’t get me all the way there because I want to load
parents of parents (or children of children). I don’t mind doing the
SQL by hand but I’m not quite sure what to do to get the result set into
my model objects. I don’t want to bypass my model objects because they
have important calculation methods I need.

You can load children of children with :include, eg
Foo.find :all, :include =>[:{children=>[:children_of_children]}]

Frederick C. wrote:

You can load children of children with :include, eg
Foo.find :all, :include =>[:{children=>[:children_of_children]}]

Awesome, thanks! I’m not sure if I understand the syntax. Are the
curly braces necessary?

Steve

Stephen M. wrote:

Frederick C. wrote:

You can load children of children with :include, eg
Foo.find :all, :include =>[:{children=>[:children_of_children]}]

Awesome, thanks! I’m not sure if I understand the syntax. Are the
curly braces necessary?

Steve

Slight typo: should be
Foo.find :all, :include =>[{:children=>[:children_of_children]}]

IIRC you do need the braces generally, although you can probably omit
for the example above. You do need them for stuff like
Foo.find :all, :include =>[{:children=>[:children_of_children]},
:other_attribute]

Thanks again. Sounds like I’ve got an ActiveRecord guru here.

Related question: Can I join and include the same table? I want to
filter based on a condition in the joined table, but I also want to
eagerly load that table. Ideally I’d like to do that with just one join
in the generated SQL. Can I refer to included tables (via :include) in
my :conditions clause?

Steve

Stephen M. wrote:

Thanks again. Sounds like I’ve got an ActiveRecord guru here.
You’re just to lucky to stumble onto one of the things I have worked
out.

Related question: Can I join and include the same table? I want to
filter based on a condition in the joined table, but I also want to
eagerly load that table. Ideally I’d like to do that with just one join
in the generated SQL. Can I refer to included tables (via :include) in
my :conditions clause?

Steve

I’ve never tried :join and :include of the same table (which I suspect
would be counter productive), however I have used the :included tables
in the :conditions parameter without any problems. The only thing you
need to be careful about is that you have to disambiguate all the column
names (eg foos.bar = ‘baz’ instead of bar = ‘baz’)

Fred

Frederick C. wrote:

I’ve never tried :join and :include of the same table (which I suspect
would be counter productive), however I have used the :included tables
in the :conditions parameter without any problems. The only thing you
need to be careful about is that you have to disambiguate all the column
names (eg foos.bar = ‘baz’ instead of bar = ‘baz’)

OK will do. Thanks again!

Steve

Frederick C. wrote:

Stephen M. wrote:

Frederick C. wrote:

You can load children of children with :include, eg
Foo.find :all, :include =>[:{children=>[:children_of_children]}]

Awesome, thanks! I’m not sure if I understand the syntax. Are the
curly braces necessary?

Steve

Slight typo: should be
Foo.find :all, :include =>[{:children=>[:children_of_children]}]

IIRC you do need the braces generally, although you can probably omit
for the example above. You do need them for stuff like
Foo.find :all, :include =>[{:children=>[:children_of_children]},
:other_attribute]

I’m getting a syntax error here - no doubt something stupid:

@guidance_group=GuidanceGroup.find(@params[:guidance_group_id],
:include=>[{:pupils=>[:setlinks], :pupil_sets, :guidance_group, \
:academic_year]})

RadRails is pointing to the comma after :pupil_sets

Can anyone see the problem?

Cheers,

Robert J.

I think you have an extra ] after :setlinks and an extra [ at the start.
Try
this out.

@guidance_group=GuidanceGroup.find(@params[:guidance_group_id],
:include=>{:pupils=>[:setlinks, :pupil_sets, :guidance_group,
:academic_year]})

Frederick C. wrote:

Stephen M. wrote:

Frederick C. wrote:

You can load children of children with :include, eg
Foo.find :all, :include =>[:{children=>[:children_of_children]}]

Awesome, thanks! I’m not sure if I understand the syntax. Are the
curly braces necessary?

Steve

Slight typo: should be
Foo.find :all, :include =>[{:children=>[:children_of_children]}]

IIRC you do need the braces generally, although you can probably omit
for the example above. You do need them for stuff like
Foo.find :all, :include =>[{:children=>[:children_of_children]},
:other_attribute]

Awesome +1 ! I was just about to post a question about exactly this
issue, and here is the answer. Some days I just love the Internet :slight_smile:

Robert J.

@guidance_group=GuidanceGroup.find(@params[:guidance_group_id],
:include=>[{:pupils=>[:setlinks], :pupil_sets, :guidance_group, \
:academic_year]})

RadRails is pointing to the comma after :pupil_sets

It’s telling you that because it thinks you’re in a hash: it’s expecting
a =>.
You’re best placed to know what you actually mean, but i suspect you
actually want
:include => [{:pupils=>[:setlinks]}, :pupils_sets, :guidance_group,
:academic_year]
(assuming :setlinks is an attribute of each pupil and everything else is
an attribute of GuidanceGroup)

Using include on the same table works just fine. For one of my
applications
I have a table projects, which references itself because projects can
have
subprojects which can have more subprojects, etc…

class Project < ActiveRecord::Base

Project.find :all, :include => :child_projects

Sorry, accidently hit send before I was done…

class Project < ActiveRecord::Base
belongs_to :parent_project, :class_name => ‘Project’, :foreign_key =>
‘parent_project_id’
has_many :child_project, :class_name => ‘Project’, :foreign_key =>
‘parent_project_id’
end

Project.find :all, :include => :child_projects

This works just fine and I am able to load any project, with all child
projects in one sql query.

Frederick C. wrote:

@guidance_group=GuidanceGroup.find(@params[:guidance_group_id],
:include=>[{:pupils=>[:setlinks], :pupil_sets, :guidance_group, \
:academic_year]})

RadRails is pointing to the comma after :pupil_sets

It’s telling you that because it thinks you’re in a hash: it’s expecting
a =>.
You’re best placed to know what you actually mean, but i suspect you
actually want
:include => [{:pupils=>[:setlinks]}, :pupils_sets, :guidance_group,
:academic_year]
(assuming :setlinks is an attribute of each pupil and everything else is
an attribute of GuidanceGroup)

Cheers - that works. The reference to guidance_group as a child of
guidance_group is as mysterious to me as to everyone else. Just a slip
of the fingers :slight_smile:

BTW, the reason I want to eager load absolutely everything is that the
report I am creating is going to be hived off to a BackgrounDrb worker.
I want to get all the ActiveRecord work done in the background, so that
the rendering is done as quickly as possible once the worker has done
its job.

Robert J.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs