On 7/7/06, Phil Tomson <rubyfan / gmail.com> wrote:
> On 7/6/06, Phil Tomson <rubyfan / gmail.com> wrote:
> > On 7/6/06, William Morgan <wmorgan-ruby-talk / masanjin.net> wrote:
> > > Hi all,
> > >
> > > Quick question: is there a better way to write Foo.contains below?
> > > Forcing the lexical scoping like this feels wrong.
> > >
> > > class Foo
> > >  def self.contains *o
> > >    @contents ||= []
> > >    @contents += o
> > >    contents = @contents
> > >    define_method(:contents) { contents }
> > >  end
> > > end
> > >
> > > class Bar < Foo
> > >  contains :goat, :boat
> > >  contains :stoat
> > > end
> > >
> > > p Bar.new.contents # => [:goat, :boat, :stoat]
> > >
> >
> > How about:
> >
> >  class Foo
> >   class << self
> >     def contains *o
> >       @contents ||= []
> >       @contents += o
> >     end
> >     attr_accessor :contents
> >   end
> >   def contents
> >     @contents ||= self.class.contents
> >   end
>
> Actually, after thinking about it a bit more, I'd probably go with:
>
>      def contents
>        self.class.contents
>      end
>
> >  end
>
>
> Phil

A tiny refinement (in the golfing mood):

class Foo
  class << self
    def contains(*args)
      (@contents ||= []).push(*args)
    end
  end
  def contents
    self.class.contains
  end
end

class Bar < Foo
  contains :goat, :boat
  contains :stoat
end

p Bar.contains
p Bar.new.contents

__END__
[:goat, :boat, :stoat]
[:goat, :boat, :stoat]

Regards,
Sean