Store defaults after first request
Reported by Justin Ossevoort | June 23rd, 2009 @ 09:47 AM
Currently the default
behaves like a "if no value
is set, return the (result of) default
". So requesting
the same attribute,that has no value, multiple times will call the
default
block multiple times. I know this can be
easily worked around by assigning as part of the default body's
block, but I think it should logically be the default (or otherwise
better documented).
Consider:
class Foo < Doodle
@@serial = 0
has :uid do
default{ @@serial += 1 }
end
end
x = Foo.new
puts x.uid # -> 1
puts x.uid # -> 2
Not exactly what one expects.
Comments and changes to this ticket
-
Justin Ossevoort July 7th, 2009 @ 01:14 PM
Oh, and here is the way to currently work around this:
class Foo < Doodle @@serial = 0 has :uid do default{ @uid = @@serial += 1 } end end x = Foo.new puts x.uid # -> 1 puts x.uid # -> 1
-
Sean O'Halpin October 11th, 2009 @ 02:29 AM
- State changed from new to resolved
Apologies for the long delay in replying.
For your use case, I would use #init rather than #default. Something like this:
require 'doodle' class Foo < Doodle counter = 0 has :uid do init { counter += 1 } end end bar = Foo.new bar.uid # => 1 bar.uid # => 1 Foo.new.uid # => 2
As you have experienced, the default block is called every time, so it's best not to generate side effects (like updating and using a class variable).
-
Justin Ossevoort October 12th, 2009 @ 08:43 AM
- Tag set to feature
I see I didn't really state my intentions clearly. What I was looking for was something along the lines of lazy initialization. And neither nor really do that.
The trick I currently use is:
class Foo < Doodle has :foo do
default{ @foo = .... }
end endBut I think it's rather ugly and I can see something like this breaking in some future Doodle release. Also it's probably not what was intended for.
Probably a more elegant way would be:
class Foo < Doodle has :foo, :lazy do
init{ ... }
end end(or)
class Bar < Doodle has :bar dolazy_init { ... }
end end -
Justin Ossevoort October 21st, 2009 @ 01:45 PM
My examples were pretty screwed up, here is a cleaned up version with example:
require 'doodle' $counter = 0 class Foo < Doodle has init_attr do init{ $counter += 1 } end has default_attr do default{ $counter += 1 } end has lazy_attr, :lazy do init{ $counter += 1 } end end f = Foo.new f.init_attr # => 1 f.lazy_attr # => 2 f.default_attr # => 3 f.init_attr # => 1 f.lazy_attr # => 2 f.default_attr # => 4
Or as a alternative to
init
anddefault
:require 'doodle' class Foo < Doodle has some_attr do lazy_init{ 'bar' } end end
Please Sign in or create a free account to add a new ticket.
With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile ยป
This site is for tracking issues for the doodle rubygem.
doodle is a Ruby gem for creating extended attribute accessors with defaults, conversions and validations.
See http://doodle.rubyforge.org/ for more details.