Lazy Loading?

I’m having problems with what seems to be lazy loading behavior in Ruby
on Rails. I have two objects in a parent-child relationship such as:

class Order < ActiveRecord::Base
has_many :items, :dependent => true
end
class Item < ActiveRecord::Base
belongs_to :order
end

I put an instance of the Order object into the session using:

session[:order] = Order.new

I then extract the object in the controller and set it equal to the
instance variable @order so that it is accessible in my view.

def myaction
@order = session[:order]
end

Now, my problem is that, in the view, the items array in @order is nil
UNLESS I access the items array in the controller, e.g.,

def myaction
@order = session[:order]
logger.debug(@order.items)
end

This seems to me that Rails is loading the items array in a lazy fashion
(which is great and expected), however, for some reason it only does
this in the controller. That is, if I access the items array in the
view, it doesn’t trigger the loading of the array. Am I doing something
wrong here? Is there a way to control the lazy loading behavior of
Rails? Help!

Jason,

It’s been my experience that if you’re saving models into a session
(as opposed to just the models’ unique id), then you can’t lazy-load
them.

In your application.rb file, try adding model :order

See the Rails wiki article [1] for more info on session handling.

[1] Peak Obsession

Thanks for the response, Ed…

I did have the model :order set in the application.rb file as well as
model :line, however, it still did not work. Lazy-loading of the items
did work in the controller, when the object was retrieved from the
session, just not in the view.

I’ve changed my approach to just store the id of the order in the
session and then load the order in my controller with the extra :include
=> :items parameter, e.g.,

@order = Order.find(:all, conditions => “id = #{session[:order_id]}”,
:include => items)

I found out that this extra parameter will tell Rails to load the items
array when the order object is loaded instead of loading the items in a
lazy fashion. I then use the @order object in my view and it works
fine.

I would, however, still like to understand the details of how Rails does
lazy loading. So if anyone out there knows, please drop me a line.
Thanks!

@order = Order.find(:all, conditions => “id = #{session[:order_id]}”,
:include => items)

Whoa, hold on there cowboy. Coding like that can get you an sql
injection attack. (Unlikely with a session value, but you don’t want
to get in the habit).

@order = Order.find(:all, :conditions => [‘id = ?’,
session[:order_id]], :include => :items)


rick
http://techno-weenie.net