Hi Sean,

On Sat, 26 Nov 2005 16:08:19 -0000, Sean O'Halpin <sean.ohalpin / gmail.com>  
wrote:

> On 11/26/05, Ross Bamford <rosco / roscopeco.remove.co.uk> wrote:
>
> I hope can answer some of your questions:
>
>>
>> 1) Is this the right way to define a method with a dynamic name?
>>
>>                eval <<-EOC
>>                  def #{method_name}
>>                    'You called #{method_name}'
>>                  end
>>                EOC
>>
>> it seems to(?) work, but I wonder if theres a better way?
>
> You can also use define_method, but it has limitations:
>
>> [...]
>
> define_method method_name do
>     puts "You called #{method_name}"
> end
>

Ahh, I should have known to check Module :) I'm still getting used to  
methods coming from all angles.

>
> You can't define methods that take blocks (as you can't pass a block
> argument to a block) which means that you need to use your original  
> method
> (eval + string) if you want to dynamically create a method that takes
> a block argument.
>

Interesting, I didn't know that (about block args to blocks). I guess if I  
wanted to pass a block in that way, I'd have to get a Proc for the  
closure? I've seen code like:

	some_method(proc { |s| s.do_something })

which seems a bit nasty to me.

> Also note the differences in scope between using "def ... end" and a
> define_method + a closure.
>

Okay, I'm with you there.

>>
>> 2) I'm struggling with boolean attributes, and question marks.
>> attr_accessor (etc) won't allow me to pass those names in (I guess  
>> because
>> they're illegal instance var names). I tried:
>>
>>        attr_accessor :is_green
>>        alias is_green? is_green
>>
>> which works, but again it strikes me theres probably a better way that
>> I've missed.
>
> I can't think of a standard way to do this that is quicker but you could
> do this:
>
> class Module
>   def predicate(*names)
>     names.each do |name|
>       attr_accessor name
>       alias_method "#{name}?", name
>     end
>   end
> end
>
> class A
>   predicate :is_green
> end
>
> a = A.new
> a.is_green = true
> p a.is_green?
> -- OUTPUT --
> true
>

Nice one. Gotta get used to this 'effectively adding keywords' thing too.  
I've gotten around the fact that class definitions can call methods, now I  
need to get used to it being _my_ methods :)

> Just to add a comment to David's explanation.
>
> class A
>   @foo = "A's foo"
> end
> p A.instance_eval { @foo }
>
> A.instance_eval { @foo = "A's foo again" }
>
> class A
>   puts @foo
> end
> -- OUTPUT --
> A's foo
> A's foo again
>
> The thing to get your head around is that a class is an object in its  
> own right
> (i.e. it is an instance of class Class).
>

This is where I am going around in circles. It's an instance of Class, but  
it also has a class, Class. So, Class.class == Class. Is that right ?

> When you open a class (with say "class A"), all the subsequent statements
> are executed in the context of that class instance object.
>

Yes, I kind of got that, but I wasn't thinking about it properly. I've  
been playing around with bindings and instance_eval a bit, and the 'self =  
current object' idea I have to say makes a lot of sense. I see now though,  
that theres more depth here than I first thought when it comes to the  
class definition.

> Regarding @@class_variables - they work a bit like globals within a
> class hierarchy. For example:
>
> class Model
>   @@models = []
>
>   def models
>     @@models
>   end
> end
>
> class Element < Model
>   @@models = ['Hello from Element']
> end
>
> class Schema < Model
>   @@models = ['Hello from Schema']
> end
>
> e = Element.new
> p e.models
> __END__
> ["Hello from Schema"]
>
> In other words, they do not belong to a class as such but a class  
> hierarchy

Hmm, I think I need to go back to the book on class variables. I can't  
quite see how they fit in, especially with respect to singleton class and  
stuff. Thanks for your explanation, though - it's just me :(

I'll probably be asking again after I confuse myself some more ;)

Cheers for your reply.

-- 
Ross Bamford - rosco / roscopeco.remove.co.uk