From: Rajinder Yadav on
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

From: Brian Candler on
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/.

From: Jesús Gabriel y Galán on
On Tue, Dec 15, 2009 at 9:32 AM, Rajinder Yadav <devguy.ca(a)gmail.com> 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.

From: Rajinder Yadav on
Jes�s Gabriel y Gal�n wrote:
> On Tue, Dec 15, 2009 at 9:32 AM, Rajinder Yadav <devguy.ca(a)gmail.com> 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

From: Rajinder Yadav on
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