On Mon, Apr 11, 2011 at 11:20 AM, Lars Olsson <lasso / lassoweb.se> wrote:
> Hi list!
>
> I have a metaprogramming question that is driving me mad. I though I
> understood how to do it, but obviously I didn't. This is what I want
> to do:
>
> I want to create a class method that takes a bunch of options and
> returns a singleton class with those options set,
>
> class Opportunities
> =A0def self.using(options)
> =A0 =A0# Store options in singleton class variable @options and then
> return singleton class
> =A0end
> =A0def self.options
> =A0 =A0return @options
> =A0end
> end
>
> So that I can use:
>
> foo =3D Opportunities.using({:one =3D> 1, :two: =3D> 2, :three =3D> 3})
> bar =3D Opportunities.using({:four =3D> 4, :five: =3D> 5, :six =3D> 6})
>
> and then
>
> foo.options =3D> {:one =3D> 1, :two: =3D> 2, :three =3D> 3}
> bar.options =3D> {:four =3D> 4, :five: =3D> 5, :six =3D> 6}
>
> Please note that I don't want instances of the Opportunities class, I
> want two separate classes that shares the same behavior except for
> that they return different values for the Opportunities.options call.
>
> This really should be possible with ruby, right?

Right.  You can use a closure like this:

class Opportunities
  def self.using(opts)
    opts.freeze
    cl =3D Class.new self # so we can define instance methods
    class<<cl;self;end.send(:define_method, :options) {opts}
    cl
  end

  # inherited by all
  def xyz
  end
end


irb(main):019:0> foo =3D Opportunities.using(:one =3D> 1, :two =3D> 2, :thr=
ee =3D> 3)
=3D> #<Class:0x10958c78>
irb(main):020:0> bar =3D Opportunities.using(:four =3D> 4, :five =3D> 5, :s=
ix =3D> 6)
=3D> #<Class:0x1095f7f8>
irb(main):021:0> foo.options
=3D> {:one=3D>1, :two=3D>2, :three=3D>3}
irb(main):022:0> bar.options
=3D> {:four=3D>4, :five=3D>5, :six=3D>6}
irb(main):023:0> f =3D foo.new
=3D> #<#<Class:0x10958c78>:0x109672dc>
irb(main):024:0> f.class.options
=3D> {:one=3D>1, :two=3D>2, :three=3D>3}
irb(main):025:0> f.class.ancestors
=3D> [#<Class:0x10958c78>, Opportunities, Object, Kernel, BasicObject]

Or you can use a member

class Opportunities
  def self.using(opts)
    cl =3D Class.new self

    class<<cl
      attr_reader :options
    end

    cl.instance_variable_set '@options', opts.freeze

    cl
  end
end

or this way

class Opportunities
  class <<self
    attr_reader :options
  end

  def self.using(opts)
    cl =3D Class.new self
    cl.instance_variable_set '@options', opts.freeze
    cl
  end
end

or this way

class Opportunities
  class <<self
    attr_reader :options
  end

  def self.using(opts)
    Class.new(self).tap do |cl|
      cl.instance_variable_set '@options', opts.freeze
    end
  end
end


Choose to your liking. :-)

Cheers

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/