Metaprogramming help

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

On Nov 26, 2007 10:20 AM, Chris R. [email protected] 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/


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

Sorry for quothing myself but you know Murphy’s law :frowning:

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

Sorry
R.

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

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/

On Nov 26, 2007 6:49 PM, ara.t.howard [email protected] 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.

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 :wink:

a @ http://codeforpeople.com/

On Nov 26, 4:20 am, Chris R. [email protected] 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.

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

On Nov 27, 5:15 am, Chris R. [email protected] 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.