views:

192

answers:

2

I've got a Moose class with a lazy_build attribute. The value of that attribute is a function of another (non-lazy) attribute.

Suppose somebody instantiates the class with a value of 42 for the required attribute. Then they request the lazy attribute, which is calculated as a function of 42. Then, they have the nerve to change the first attribute!

The lazy one has already been built, so the builder will not get called again, and the lazy attribute is now out-of-date.

I have a solution now where I maintain a "dirty" flag on the required attribute, and an accessor on the lazy one checks the dirty flag and rebuilds it if needed.

However, this seems like a lot of work. Is there a way to handle this within Moose, e.g. using traits?

+6  A: 

My typical solution:

has 'attr1' => (
    ...
    trigger => \&clear_attr2, 
);

i.e. when attr1 is updated, attr2 is cleared and will be rebuilt when it is next accessed. clear_attr2 comes for free when you use lazy_build. As long as you use the accessor methods, you don't need a 'dirty' flag.

This is a common pattern - some kind of trait to handle 'derived' attributes would be nice.

rjh
Perfect. I really like this solution. I was heading in the same direction by doing an `after` modifier on `set_attr1`, but the trigger is even easier. Thanks
friedo
+1  A: 

You might want to check out the answers from when I asked the same question: Expiring cached results of calculations when attribute values change

clscott