Metaprogramming and module question

  • Thread starter Pedro Del Gallego
  • Start date
P

Pedro Del Gallego

Hi

Yesterday , i'd made an example for fun, after read [1]. that let me
introduce pre o post behavior to an method with this easy sintax

class Foo
pre:)my_method) { #some_code}
end

but i ve a proble when i try to move the pre and post method to a
module. Can anyone explainme why the pre methods is undefined in the
class ?

thanks in advance.

[1] : http://split-s.blogspot.com/2006/02/design-by-contract-for-ruby.html

My code :
----------------------------------------------------------------------------------------------------------------
Pre and Post method implemented in Song class

class Song
attr_accessor :title
def play
puts "#{@title}"
end
end

class Song
def self.pre (name_method, &condition)
old_method = instance_method(name_method)

define_method(name_method) { |*args|
condition.call
old_method.bind(self).call(*args)
}
end

def self.post (name_method, &condition)
old_method = instance_method(name_method)

define_method(name_method) { |*args|
condition.call
}
end
end

class Song
pre :)play ) { puts "Playing ..." }
end

song = Song.new
song.title= "Hola song"
song.play

----------------------------------------------------------------------------------------------------------------
Als module implementation : not work undefined method `pre' for
Song:Class (NoMethodError)

class Song
attr_accessor :title
def play
puts "#{@title}"
end
end

module MetaTest

def self.included(mod)
puts "and now MetaTest has been used by #{mod.inspect}..."
end

def self.pre (name_method, &condition)
old_method = instance_method(name_method)

define_method(name_method) { |*args|
condition.call
old_method.bind(self).call(*args)
}
end

def self.post (name_method, &condition)
old_method = instance_method(name_method)

define_method(name_method) { |*args|
condition.call
}
end
end

class Song
include MetaTest
end

class Song
pre :)play ) { puts "Playing ..." }
end


song = Song.new
song.title= "Hola caracola"
song.play
 
P

Phrogz

but i ve a proble when i try to move the pre and post method to a
module. Can anyone explainme why the pre methods is undefined in the
class ?
[snip]

Including a Module into a Class only links in the 'instance' methods
of that module as instance methods of the class. Module methods (def
self.foo) are not inherited as 'class' methods.

See http://phrogz.net/RubyLibs/RubyMethodLookupFlow.png for a visual
explanation.

The easiest thing to do is make those methods instance methods of the
module, and extend your Song class with them:

module Foo
def bar; puts "#bar called on #{self}"; end
end

class Cat
include Foo
end

class Dog
extend Foo
end

Cat.bar rescue puts "No Cat.bar method!"
Cat.new.bar rescue puts "No Cat#bar method!"
Dog.bar rescue puts "No Dog.bar method!"
Dog.new.bar rescue puts "No Dog#bar method!"

#=> No Cat.bar method!
#=> #bar called on #<Cat:0x28347b0>
#=> #bar called on Dog
#=> No Dog#bar method!
 
R

Rick DeNatale

but i ve a proble when i try to move the pre and post method to a
module. Can anyone explainme why the pre methods is undefined in the
class ?
[snip]

Including a Module into a Class only links in the 'instance' methods
of that module as instance methods of the class. Module methods (def
self.foo) are not inherited as 'class' methods.

See http://phrogz.net/RubyLibs/RubyMethodLookupFlow.png for a visual
explanation.

The easiest thing to do is make those methods instance methods of the
module, and extend your Song class with them

And a good way to do this automatically and make including the
MetaTest module do what the OP expects is something like:

module MetaTest

def self.included(mod)
puts "and now MetaTest has been used by #{mod.inspect}..."
mod.extend(ClassMethods)
end

module ClassMethods

def pre (name_method, &condition)
old_method = instance_method(name_method)

define_method(name_method) { |*args|
condition.call
old_method.bind(self).call(*args)
}
end

def post (name_method, &condition)
old_method = instance_method(name_method)

define_method(name_method) { |*args|
condition.call
}
end
end
end
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top