# Metaprogramming help

**URL:** <https://www.ruby-forum.com/t/metaprogramming-help/121265>\
**Category:** Ruby\
**Created:** [November 26, 2007, 10:20am UTC](https://www.ruby-forum.com/t/metaprogramming-help/121265 "2007-11-26T10:20:14Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![crenner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/278dde/32.png) [@crenner](https://www.ruby-forum.com/u/crenner)\
**Post date:** [November 26, 2007, 10:20am UTC](https://www.ruby-forum.com/t/metaprogramming-help/121265/1 "2007-11-26T10:20:14Z")

</div>

I have created a module as follows which adds an initialize method to  
the class it is included in. The problem is that the initializer method  
could be easily overriden by the includer Class. Is there a way to  
ensure that the initialize method is run even though it may have been  
overriden??

module SomeModule

def self.included(base)  
base.class\_eval do

```
  attr_accessor :fields, :x_position, :y_position

  def initialize(x_position=0, y_position=0)
    @fields=self.class.xfields.clone
    self.y_position=y_position
    self.x_position=x_position
    for field in @fields
          eval "self."+field[:var] + " = field[:value]"
    end
    @fields = @fields.sort_by{|f| f[:order]} if @fields.find{|f|

```

f[:order]}  
end  
end  
end

end

Any help is appreciated.  
Thanks, Chris

---

<div class="post-metadata">

**Author:** ![crenner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/278dde/32.png) [@crenner](https://www.ruby-forum.com/u/crenner)\
**Post date:** [November 26, 2007, 11:42am UTC](https://www.ruby-forum.com/t/metaprogramming-help/121265/2 "2007-11-26T11:42:38Z")

</div>

On Nov 26, 2007 10:20 AM, Chris R. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I have created a module as follows which adds an initialize method to  
> the class it is included in. The problem is that the initializer method  
> could be easily overriden by the includer Class. Is there a way to  
> ensure that the initialize method is run even though it may have been  
> overriden??  
> No there is none and I am not sure it is a good idea, as it is the  
> users responsability to call super.  
> But if it turns out to be a good idea than one could imagine doing  
> something like below, which kind of hides better what you try to hide.  
> I believe that hiding your own init method and assure it is called in  
> new might be a better model of your intent, initialize belongs to the  
> user after all, right?

module M  
class \<\< self  
def included into  
my\_init = nil  
into.module\_eval do  
### More sophistication can be added here to avoid naming  
conflicts  
### in the includee (into)  
define\_method :my\_init do puts 42 end  
my\_init = instance\_method :my\_init  
remove\_method :my\_init  
end

```
  class << into; self end.module_eval do
    alias_method :_orig_new_, :new
    define_method :new do | *args | # more hocus pocus needed for 

```

&blk  
o = _orig\_new_( \*args )  
my\_init.bind( o ).call( \*args )  
o  
end  
end  
end  
end  
end

class C  
include M  
def my\_init; puts 222 end  
end

c= C.new  
c.my\_init

Of course a user can still mess with C#new but your code might be save  
from most common reusage patterns :).

HTH  
Robert

–

[http://ruby-smalltalk.blogspot.com/](http://ruby-smalltalk.blogspot.com/)

* * *

All truth passes through three stages. First, it is ridiculed. Second,  
it is violently opposed. Third, it is accepted as being self-evident.  
Schopenhauer (attr.)

---

<div class="post-metadata">

**Author:** ![crenner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/278dde/32.png) [@crenner](https://www.ruby-forum.com/u/crenner)\
**Post date:** [November 26, 2007, 12:17pm UTC](https://www.ruby-forum.com/t/metaprogramming-help/121265/3 "2007-11-26T12:17:25Z")

</div>

Sorry for quothing myself but you know Murphy’s law ☹

of course it is unnecessary to alias new to _orig\_new_, just replace  
_orig\_new_ with a call to super.

Sorry  
R.

---

<div class="post-metadata">

**Author:** ![crenner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/278dde/32.png) [@crenner](https://www.ruby-forum.com/u/crenner)\
**Post date:** [November 26, 2007, 6:49pm UTC](https://www.ruby-forum.com/t/metaprogramming-help/121265/4 "2007-11-26T18:49:37Z")

</div>

On Nov 26, 2007, at 2:20 AM, Chris R. wrote:

> ```
> base.class_eval do
> @fields = @fields.sort_by{|f| f[:order]} if @fields.find{|f|
> 
> ```
> 
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

i’d be inclined to do something like this:

cfp:~ \> cat a.rb  
module M  
def M.initialize obj  
obj.instance\_eval{  
@a = 42  
}  
end

module ClassMethods  
def new \*a, &b  
obj = super  
ensure  
M.initialize obj  
end  
end

module InstanceMethods  
attr :a  
end

def self.included other  
other.send :extend, ClassMethods  
other.send :include, InstanceMethods  
end  
end

class C  
include M  
end

p C.new.a

cfp:~ \> ruby a.rb  
42

allowing you to extend the includee’s class, instances, and also keep  
your private initialize private rather than dropping it into the  
includee

regards  
a @ [http://codeforpeople.com/](http://codeforpeople.com/)

---

<div class="post-metadata">

**Author:** ![crenner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/278dde/32.png) [@crenner](https://www.ruby-forum.com/u/crenner)\
**Post date:** [November 26, 2007, 9:53pm UTC](https://www.ruby-forum.com/t/metaprogramming-help/121265/5 "2007-11-26T21:53:48Z")

</div>

On Nov 26, 2007 6:49 PM, ara.t.howard [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > ```
> > self.x_position=x_position
> > 
> > ```
> 
> def M.initialize obj  
> end  
> end
> 
> allowing you to extend the includee’s class, instances, and also keep  
> your private initialize private rather than dropping it into the  
> includee  
> Well the simplicity and elegance of your code speak for themselves, I  
> would like to defend myself nevertheless;)  
> my aim was hiding the implementation even more, but as I put it  
> myself, that might not make sense very easily.  
> But I learnt a lot from your approach here…  
> R.

---

<div class="post-metadata">

**Author:** ![crenner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/278dde/32.png) [@crenner](https://www.ruby-forum.com/u/crenner)\
**Post date:** [November 27, 2007, 12:32am UTC](https://www.ruby-forum.com/t/metaprogramming-help/121265/6 "2007-11-27T00:32:02Z")

</div>

On Nov 26, 2007, at 1:53 PM, Robert D. wrote:

> Well the simplicity and elegance of your code speak for themselves, I  
> would like to defend myself nevertheless;)  
> my aim was hiding the implementation even more, but as I put it  
> myself, that might not make sense very easily.  
> But I learnt a lot from your approach here…

lol - my own code looks much more like yours. i go back and forth  
with methodology. this week i am using modules 😉

a @ [http://codeforpeople.com/](http://codeforpeople.com/)

---

<div class="post-metadata">

**Author:** ![crenner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/278dde/32.png) [@crenner](https://www.ruby-forum.com/u/crenner)\
**Post date:** [November 27, 2007, 12:53am UTC](https://www.ruby-forum.com/t/metaprogramming-help/121265/7 "2007-11-27T00:53:05Z")

</div>

On Nov 26, 4:20 am, Chris R. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> f[:order]}  
> end  
> end  
> end
> 
> end

This is more of an aside then an answer to your question. But it is  
important to note that you should not do the above. You are  
“falsifying” inclusion and actually injecting code. The reason I say  
“falsify” is because you end up with a module in the hierarchy that  
contains no code. If you want to inject code, then simply define a  
class method that does it. Don’t use the included callback.

BTW: To ensure a routine always runs on initialization despite  
#initialize, one way:

class X  
class \<\< self  
def new(\*a, &b)  
o = allocate  
o.do\_your\_thing  
o.initialize(\*a,&b)  
o  
end  
end  
end

The other is AOP which is a much larger can of worms.

T.

---

<div class="post-metadata">

**Author:** ![crenner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/278dde/32.png) [@crenner](https://www.ruby-forum.com/u/crenner)\
**Post date:** [November 27, 2007, 11:15am UTC](https://www.ruby-forum.com/t/metaprogramming-help/121265/8 "2007-11-27T11:15:28Z")

</div>

Wow, thanks for all your replies.

> BTW: To ensure a routine always runs on initialization despite  
> #initialize, one way:
> 
> class X  
> class \<\< self  
> def new(\*a, &b)  
> o = allocate  
> o.do\_your\_thing  
> o.initialize(\*a,&b)  
> o  
> end  
> end  
> end
> 
> The other is AOP which is a much larger can of worms.

so whats the simplest way to ensure this method was always run ? :

def initialize(x=0, y=0)  
self.x\_position=x  
self.y\_position=y  
end

Thanks  
Chris

---

<div class="post-metadata">

**Author:** ![crenner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/278dde/32.png) [@crenner](https://www.ruby-forum.com/u/crenner)\
**Post date:** [November 27, 2007, 3:25pm UTC](https://www.ruby-forum.com/t/metaprogramming-help/121265/9 "2007-11-27T15:25:26Z")

</div>

On Nov 27, 5:15 am, Chris R. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > ```
> > o.initialize(*a,&b)
> > 
> > ```
> 
> self.x\_position=x  
> self.y\_position=y  
> end

Why do you want to thwart super here? You should have very clear  
reason for doing so, otherwise leave it.

But to answer your question directly:

class X  
class \<\< self  
def new(\*a, &b)  
o = allocate  
o.pre\_initialize(\*a, &b)  
o.initialize(\*a,&b)  
o  
end  
end

```
def pre_initialize(x=0, y=0)
  self.x_position=x
  self.y_position=y
end

```

end

T.
