On 30.07.2009 00:16, spox wrote:
> On Wednesday 29 July 2009 12:34:30 Ch Ba wrote:
>> So I'm trying to figure out how I can allow an end user to decide which
>> modules to mixin to a instance of a class, but I'm not sure if it's
>> possible. An example of what I would like.
>>
>> module Thing
>>   @bar = 5
>> end

This does not work as it defines a member of module Thing with value 5. 
    You would rather need something like this:

module Thing
   attr_writer :bar

   def bar
     @bar ||= 5
   end
end

But this does not solve the initialization problem.  For that you need a 
bit more complex logic (see below).

>> class Foo
>>   def initialize
>>     @bar = 0
>>     @foo = 2
>>   end
>> end
>>
>> class FooBar < Foo
>>   def initialize(*modules)
>>     @bar = 1
>>     modules.each do |module_name|
>>       eval("include #{module_name.to_s.capitalize}")
>>     end
>>   end
>> end
>>
>> test = FooBar.new(:thing)
>>
>> In the previous example, test would be an instance of FooBar, and it's
>> @bar would be 5 (from the module Thing), and it's @foo would be 2, from
>> it's superclass. Is that possible? The previous returns a nomethoderror
>> for "include" in the instance of test. And it might have several other
>> errors since I just typed it up.
> 
> module Thing
>   def bar
>     5
>   end
> end
> 
> class Foo
>   attr_reader :bar
>   attr_reader :foo
>   def initialize
>     @bar = 0
>     @foo = 2
>   end
> end
> 
> class FooBar < Foo
>   def initialize(*modules)
>     super()
>     @bar = 1
>     modules.each do |module_name|
>         klass = Kernel.const_get(module_name)
>         extend klass
>     end
>   end
> end
> 
> test = FooBar.new(:Thing)
> puts test.bar
> puts test.foo
> 
> Not exactly what you are looking for, but close.

I believe what OP wants can be achieved doing something like this 
(untested):

module Thing
   attr_acessor :bar

   def initialize
     # deliberately no super here
     self.bar = 5
   end
end

class FooBar
   def initialize(*modules)
     super()
     @bar = 1

     modules.each do |mod|
       extend mod

       begin
         mod.instance_method(:initialize).bind(self).call()
       rescue NameError
         # ignore
       end
     end
   end
end

test = FooBar.new(Thing)
puts test.bar
puts test.foo

Kind regards

	robert

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