Blankman
Blankman

Reputation: 267020

How to create a lazy loaded property in Ruby for a Model?

I want to create a lazy-loaded property that returns a collection on a Model, how do I do this?

I don't want to create an association for this.

So I want it to return a collection, if the collection hasn't been initialized yet then hit the database, return the rows, then initialize it.

If it get's run once, then no need to run it again since the next page request will start things over.

Upvotes: 11

Views: 8118

Answers (2)

David Sulc
David Sulc

Reputation: 25994

Add an instance attribute (e.g. @my_attribute)

And then define

def my_attribute
  @my_attribute ||= initialize_my_attribute
end

(Note: initialize_my_attribute is a function/method you've implemented that will load the value you want.)

How this works: the attribute starts out with a nil value (we haven't assigned anything to it). The object instance can't access it directly, because we haven't defined an attribute accessor on it. Instead we have a method that has the exact same name as the attribute, so that when you call my_object.my_attribute it looks exactly as if you're accessing the attribute when you're actually calling the object instance's method.

What happens in the method? The ||= short hand is equivalent to

@my_attribute = (@my_attribute || initialize_my_attribute)

So if @my_attribute already has value, that value is returned. Otherwise, @my_attribute gets a value assigned (and then returned). In other words: the value will be loaded in @my_attribute the first time it is accessed (and only the first time).

And voila! Lazy loading.

Upvotes: 23

Charma
Charma

Reputation: 1107

Associated properties are lazy-loaded by default. Check your logs so see that queries to the database are only done if the property is accessed.

I ran into this issue too. And after I implemented my self-made lazy-loading functions I realised that they were meaningless. By adding lazy-loaders like described above, you add a lazy-loader to the internal lazy-loader which makes things slower in terms of performance without adding any value.

Upvotes: 0

Related Questions