Mariano Kamp
12/20/2006 11:27:00 AM
On Dec 19, 2006, at 10:36 PM, Luke Kanies wrote:
> Something like thie following should work:
>
> require 'test/unit'
> include Test::Unit::Assertions
>
> class Base
> class << self
> def enhance(*attributes)
> attr_accessor *attributes
>
> define_method(:initialize) do |*ary|
> attributes.each do |a|
> send(a.to_s + "=", ary.shift)
> end
> end
> end
> end
> end
> class Derived < Base; end
>
> class Testing < Test::Unit::TestCase
> def test_initialize
> Derived.enhance(:a, :b, :c)
> d = Derived.new("a", "b", "c")
>
> assert_equal "a", d.a
> assert_equal "b", d.b
> assert_equal "c", d.c
> end
> end
>
> I didn't really do what you want, because I'm not actually using
> class_eval here at all, but the assertions pass, anyway, which I
> assume is the real goal.
>
> Note that I'm using attr_accessor here instead of attr_reader,
> because it's much easier to set the attributes this way. You could
> just about as easily use instance_variable_set or whatever the
> method is, but I prefer this for my own code.
>
> Note also that if you call enhance() multiple times on the same
> class, you'll recreate the initialize() method each time, which is
> probaby a bad thing; as long as this is just for testing, you
> should be fine, but I'd be wary of putting this into production
> anywhere.
>
> One of the things I love about ruby is I can usually use a block
> instead of a string with the eval methods, but what I love even
> more is being able to skip the eval methods entirely.
Hi Luke,
thanks. That should work for my example.
Well, generally speaking I love the idea that you can transform
one concept into another and if this works nicely it most of the time
looks elegant to me. So I was hoping that I just didn't get how to do
that with code in strings as opposed to blocks.
So it seems, that there are things that you can do with one of the
concepts but not with the other.
I am currently trying to figure out what the hard rules are on
when to use a String and when to use a block.
I like the String approach as it is pretty close to how you would
write the method by hand, but I hate about it that it is just heap of
characters. But the latter might be just me as my thoughts are often
still in the Java world, where you like to do things explicitly and
give the compiler/editor a chance to help you.
Coming back to the example it seems that the two approaches do not
provide the same functionality. When using the String approach the
parameters to the initialize method are explicit. On consequence is
that if I would call Derived.new ("a", "b") I would get an error
saying that I just provided two of three parameters. This doesn't
happen with the block approach. Of course I could always explicitly
code to check for the ary length, but this is kind of redundant.
Cheers,
Mariano