Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > meta-programming

Reply
Thread Tools

meta-programming

 
 
Rajinder Yadav
Guest
Posts: n/a
 
      12-15-2009
I am just starting to expand my Ruby knowledge into the area of
meta-programming.

I want to be able to create a class dynamically. Lets call it, class
Person, and then I want to add methods to it dynamically.

From a static point I have managed to compile the following example:

class Person
def self.extend_me
class_eval "def greet; puts 'hello'; end"
instance_eval "def name; puts 'Person'; end"
end
end

Person.extend_me

Person.respond_to? :greet
Person.respond_to? :name

puts Person.name
p = Person.new
puts p.greet


How would I declared a, 'class Person' dynamically and then add methods
and attributes to it? Can someone point me to good documentation on this
or show me some simple code example?

--
Kind Regards,
Rajinder Yadav

http://DevMentor.org

Do Good! - Share Freely

 
Reply With Quote
 
 
 
 
Brian Candler
Guest
Posts: n/a
 
      12-15-2009
Rajinder Yadav wrote:
> How would I declared a, 'class Person' dynamically


Option 1: since you're using string eval already, you could just do the
same.

eval "class Person; end"

Option 2:

Person = Class.new # superclass is Object
Person = Class.new(Mammal) # superclass is Mammal

I find this isn't often done in practice though. A program which doesn't
know in advance which classes it has can be a bit too dynamic You
would probably register your classes somewhere to be able to find them.
In a Hash is one option; under a Module is another, so you can use

MyModule.constants

to find them all.

You can make your classes anonymous if you don't bind them to a
constant:

my_klass = Class.new

> and then add methods and attributes to it?


As you've done before, using string eval, is one way.

Another way:

Person.class_eval { define_method(:greet) { puts "Hello" } }

This means that the method is a closure, and can access variables
outside (unlike 'def' which starts a fresh scope), and this can be
useful sometimes.

Another way: put the method(s) of interest in module(s), then include
the relevant ones.

Person.class_eval { include Greeter }

ActiveRecord is a plentiful source of examples.
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
 
Jesús Gabriel y Galán
Guest
Posts: n/a
 
      12-15-2009
On Tue, Dec 15, 2009 at 9:32 AM, Rajinder Yadav <(E-Mail Removed)> wrote=
:
> I am just starting to expand my Ruby knowledge into the area of
> meta-programming.
>
> I want to be able to create a class dynamically. Lets call it, class Pers=

on,
> and then I want to add methods to it dynamically.
>
> From a static point I have managed to compile the following example:
>
> class Person
> =A0 def self.extend_me
> =A0 class_eval "def greet; puts 'hello'; end"
> =A0 instance_eval "def name; puts 'Person'; end"
> =A0 end
> end
>
> Person.extend_me
>
> Person.respond_to? :greet
> Person.respond_to? :name
>
> puts Person.name
> p =3D Person.new
> puts p.greet
>
>
> How would I declared a, 'class Person' dynamically and then add methods a=

nd
> attributes to it? Can someone point me to good documentation on this or s=

how
> me some simple code example?


If you want to define the class dynamically, take a look at Class.new.
This creates an anonymous class that you can assign to a constant
directly or with const_set.
To define methods I would use define_method. Adding attributes is done
adding methods that set and get the attributes:

irb(main):042:0> C =3D Class.new do
irb(main):043:1* def self.add_method(name, &blk)
irb(main):044:2> define_method(name, &blk)
irb(main):045:2> end
irb(main):046:1> end
=3D> C

irb(main):051:0> C.add_method(:name) {@name}
=3D> #<Proc:0xb7cb9de8@(irb):51>
irb(main):052:0> C.add_method(:name=3D) {|value| @name =3D value}
=3D> #<Proc:0xb7cb3bf0@(irb):52>
irb(main):053:0> c =3D C.new
=3D> #<C:0xb7cb16d4>
irb(main):054:0> c.name=3D3
=3D> 3
irb(main):055:0> c.name
=3D> 3

Hope this helps,

Jesus.

 
Reply With Quote
 
Rajinder Yadav
Guest
Posts: n/a
 
      12-15-2009
Jesús Gabriel y Galán wrote:
> On Tue, Dec 15, 2009 at 9:32 AM, Rajinder Yadav <(E-Mail Removed)> wrote:
>> I am just starting to expand my Ruby knowledge into the area of
>> meta-programming.
>>
>> I want to be able to create a class dynamically. Lets call it, class Person,
>> and then I want to add methods to it dynamically.
>>
>> From a static point I have managed to compile the following example:
>>
>> class Person
>> def self.extend_me
>> class_eval "def greet; puts 'hello'; end"
>> instance_eval "def name; puts 'Person'; end"
>> end
>> end
>>
>> Person.extend_me
>>
>> Person.respond_to? :greet
>> Person.respond_to? :name
>>
>> puts Person.name
>> p = Person.new
>> puts p.greet
>>
>>
>> How would I declared a, 'class Person' dynamically and then add methods and
>> attributes to it? Can someone point me to good documentation on this or show
>> me some simple code example?

>
> If you want to define the class dynamically, take a look at Class.new.
> This creates an anonymous class that you can assign to a constant
> directly or with const_set.
> To define methods I would use define_method. Adding attributes is done
> adding methods that set and get the attributes:
>
> irb(main):042:0> C = Class.new do
> irb(main):043:1* def self.add_method(name, &blk)
> irb(main):044:2> define_method(name, &blk)
> irb(main):045:2> end
> irb(main):046:1> end
> => C
>
> irb(main):051:0> C.add_method(:name) {@name}
> => #<Proc:0xb7cb9de8@(irb):51>
> irb(main):052:0> C.add_method(:name=) {|value| @name = value}
> => #<Proc:0xb7cb3bf0@(irb):52>
> irb(main):053:0> c = C.new
> => #<C:0xb7cb16d4>
> irb(main):054:0> c.name=3
> => 3
> irb(main):055:0> c.name
> => 3
>
> Hope this helps,
>
> Jesus.
>
>


Hi Jesus, yes it does help and you answered the next question I was
about to ask about adding variables after reading Brian's reply.

--
Kind Regards,
Rajinder Yadav

http://DevMentor.org

Do Good! - Share Freely

 
Reply With Quote
 
Rajinder Yadav
Guest
Posts: n/a
 
      12-15-2009
Brian Candler wrote:
> Rajinder Yadav wrote:
>> How would I declared a, 'class Person' dynamically

>
> Option 1: since you're using string eval already, you could just do the
> same.
>
> eval "class Person; end"
>
> Option 2:
>
> Person = Class.new # superclass is Object
> Person = Class.new(Mammal) # superclass is Mammal
>
> I find this isn't often done in practice though. A program which doesn't
> know in advance which classes it has can be a bit too dynamic You
> would probably register your classes somewhere to be able to find them.
> In a Hash is one option; under a Module is another, so you can use
>
> MyModule.constants
>
> to find them all.
>
> You can make your classes anonymous if you don't bind them to a
> constant:
>
> my_klass = Class.new
>
>> and then add methods and attributes to it?

>
> As you've done before, using string eval, is one way.
>
> Another way:
>
> Person.class_eval { define_method(:greet) { puts "Hello" } }
>
> This means that the method is a closure, and can access variables
> outside (unlike 'def' which starts a fresh scope), and this can be
> useful sometimes.
>
> Another way: put the method(s) of interest in module(s), then include
> the relevant ones.
>
> Person.class_eval { include Greeter }
>
> ActiveRecord is a plentiful source of examples.


Hi Brian,

thanks for the excellent examples and explanation =), I can't stop
smiling about how beautiful and elegantly simple Ruby make things.

--
Kind Regards,
Rajinder Yadav

http://DevMentor.org

Do Good! - Share Freely

 
Reply With Quote
 
Brian Candler
Guest
Posts: n/a
 
      12-15-2009
Jesús Gabriel y Galán wrote:
> irb(main):051:0> C.add_method(:name) {@name}
> => #<Proc:0xb7cb9de8@(irb):51>
> irb(main):052:0> C.add_method(:name=) {|value| @name = value}
> => #<Proc:0xb7cb3bf0@(irb):52>
> irb(main):053:0> c = C.new
> => #<C:0xb7cb16d4>
> irb(main):054:0> c.name=3
> => 3
> irb(main):055:0> c.name
> => 3


Of course, since 'name' is static here, you could just include a module.

It gets more fun when the names of the accessors themselves are dynamic.
At this point it really does make more sense to use string eval, rather
than the alternative (instance_variable_get and instance_variable_set).

Have a look at define_method_attribute= in the following:
http://github.com/rails/rails/blob/m...thods/write.rb

Also see define_read_method in attribute_methods/read.rb, and
method_missing in base.rb (this defines finder methods dynamically)
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Rajinder Yadav
Guest
Posts: n/a
 
      12-15-2009
Brian Candler wrote:
> Jesús Gabriel y Galán wrote:
>> irb(main):051:0> C.add_method(:name) {@name}
>> => #<Proc:0xb7cb9de8@(irb):51>
>> irb(main):052:0> C.add_method(:name=) {|value| @name = value}
>> => #<Proc:0xb7cb3bf0@(irb):52>
>> irb(main):053:0> c = C.new
>> => #<C:0xb7cb16d4>
>> irb(main):054:0> c.name=3
>> => 3
>> irb(main):055:0> c.name
>> => 3

>
> Of course, since 'name' is static here, you could just include a module.
>
> It gets more fun when the names of the accessors themselves are dynamic.
> At this point it really does make more sense to use string eval, rather
> than the alternative (instance_variable_get and instance_variable_set).
>
> Have a look at define_method_attribute= in the following:
> http://github.com/rails/rails/blob/m...thods/write.rb


Thanks for pointing out the path to ActiveRecord, I haven't gotten use
to browsing source code, this is really helpful!

>
> Also see define_read_method in attribute_methods/read.rb, and
> method_missing in base.rb (this defines finder methods dynamically)


cool I will do that =)


--
Kind Regards,
Rajinder Yadav

http://DevMentor.org

Do Good! - Share Freely

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off




Advertisments