# Dynamically mixins?

**URL:** <https://www.ruby-forum.com/t/dynamically-mixins/172910>\
**Category:** Ruby\
**Created:** [July 29, 2009, 9:34pm UTC](https://www.ruby-forum.com/t/dynamically-mixins/172910 "2009-07-29T21:34:23Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![navouri](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/f475e1/32.png) [@navouri](https://www.ruby-forum.com/u/navouri)\
**Post date:** [July 29, 2009, 9:34pm UTC](https://www.ruby-forum.com/t/dynamically-mixins/172910/1 "2009-07-29T21:34:23Z")

</div>

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

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.

---

<div class="post-metadata">

**Author:** ![navouri](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/f475e1/32.png) [@navouri](https://www.ruby-forum.com/u/navouri)\
**Post date:** [July 30, 2009, 12:17am UTC](https://www.ruby-forum.com/t/dynamically-mixins/172910/2 "2009-07-30T00:17:10Z")

</div>

On Wednesday 29 July 2009 12:34:30 Ch Ba wrote:

> ```
> @bar = 0
> 
> ```
> 
> 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.

---

<div class="post-metadata">

**Author:** ![navouri](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/f475e1/32.png) [@navouri](https://www.ruby-forum.com/u/navouri)\
**Post date:** [July 30, 2009, 11:50am UTC](https://www.ruby-forum.com/t/dynamically-mixins/172910/3 "2009-07-30T11:50:50Z")

</div>

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).

> > ```
> > modules.each do |module_name|
> > 
> > ```
> > 
> > for “include” in the instance of test. And it might have several other  
> > attr\_reader :foo  
> > modules.each do |module\_name|  
> > 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

---

<div class="post-metadata">

**Author:** ![navouri](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/f475e1/32.png) [@navouri](https://www.ruby-forum.com/u/navouri)\
**Post date:** [July 30, 2009, 5:32pm UTC](https://www.ruby-forum.com/t/dynamically-mixins/172910/4 "2009-07-30T17:32:09Z")

</div>

On 30.07.2009 16:21, Brian C. wrote:

> def self.extended(obj)  
> obj.instance\_eval do  
> @bar = 5  
> end  
> end  
> end

That’s a nice idea to use #extended!

> ```
> @bar = 1
> 
> ```
> 
> Thing, then you can use Object.const\_get as others have pointed out. Or  
> build a hash:
> 
> ALLOWED\_MODULES = {  
> :thing =\> Thing,  
> }
> 
> …  
> extend ALLOWED\_MODULES[mod]

May I suggest to use #fetch in that case - the error might be a bit more  
telling.

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![navouri](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/f475e1/32.png) [@navouri](https://www.ruby-forum.com/u/navouri)\
**Post date:** [July 30, 2009, 4:21pm UTC](https://www.ruby-forum.com/t/dynamically-mixins/172910/5 "2009-07-30T16:21:41Z")

</div>

Ch Ba wrote:

> The previous returns a nomethoderror  
> for “include” in the instance of test.

Use “extend” rather than “include” if you want to add a module to a  
single object, rather than to a class.

I think this does what you want:

module Thing  
def self.extended(obj)  
obj.instance\_eval do  
@bar = 5  
end  
end  
end

class Foo  
def initialize  
@bar = 0  
@foo = 2  
end  
end

class FooBar \< Foo  
def initialize(\*modules)  
super()  
@bar = 1  
modules.each do |mod|  
extend mod  
end  
end  
end

test = FooBar.new(Thing)  
p test

If you want to pass a symbol like :thing instead of the actual module  
Thing, then you can use Object.const\_get as others have pointed out. Or  
build a hash:

ALLOWED\_MODULES = {  
:thing =\> Thing,  
}

…  
extend ALLOWED\_MODULES[mod]

---

<div class="post-metadata">

**Author:** ![navouri](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/f475e1/32.png) [@navouri](https://www.ruby-forum.com/u/navouri)\
**Post date:** [July 30, 2009, 8:44pm UTC](https://www.ruby-forum.com/t/dynamically-mixins/172910/6 "2009-07-30T20:44:36Z")

</div>

Robert K. wrote:

> > ALLOWED\_MODULES = {  
> > :thing =\> Thing,  
> > }
> > 
> > …  
> > extend ALLOWED\_MODULES[mod]
> 
> May I suggest to use #fetch in that case - the error might be a bit more  
> telling.

Yes, that’s a good idea. I’m in the habit of writing things like

extend(ALLOWED\_MODULES[mod] || (raise “Unknown module  
#{mod.inspect}”))

but I thought that might clutter the sample code in this case. I always  
forget about Hash#fetch.

Another way is:

ALLOWED\_MODULES = Hash.new { raise “Oi!” }  
ALLOWED\_MODULES.merge!({  
… etc  
})
