Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

Store defaults after first request

#9

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.

Reported by Justin Ossevoort · June 23rd, 2009 @ 09:47 AM

State: resolved
Milestone: none
Assigned to: Sean O'Halpin Sean O'Halpin

Activity

  1. Justin Ossevoort
    Justin Ossevoort

    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
    

    July 7th, 2009 @ 01:14 PM

  2. Sean O'Halpin
    Sean O'Halpin
    • 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).

    October 11th, 2009 @ 02:29 AM

  3. Justin Ossevoort
    Justin Ossevoort
    • 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 end

    But 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 do
    lazy_init { ... }
    
    
    
    
    end end

    October 12th, 2009 @ 08:43 AM

  4. Justin Ossevoort
    Justin Ossevoort

    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 and default:

        require 'doodle'
    
        class Foo < Doodle
            has some_attr do
                lazy_init{ 'bar' }
            end
        end
    

    October 21st, 2009 @ 01:45 PM

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.