Phlip1
(Phlip)
14 September 2007 21:00
1
Rubyists:
Here's a test case illustrates the problem. Then we'll have a candidate fix
and some questions.
class Kozmik
def self.acts_as_frog(species)
@@frog_list << species
end
@@frog_list = []
cattr_accessor :frog_list
end
class Toad < Kozmik
acts_as_frog :bufo
acts_as_frog :kermit
end
class BullFrog < Kozmik
acts_as_frog :tree
acts_as_frog :riparian
end
def test_fun_with_metaclasses
assert_equal [:tree, :riparian], BullFrog.frog_list
assert_equal [:bufo, :kermit], Toad.frog_list
end
Suppose we need an 'acts_as_' system to generate some methods for our target
classes. And suppose one method is a list of all the arguments passed to
each acts_as_() in each specific class.
The above test fails because @@ occupies the entire inheritance chain. So
both frog_list() class-methods return [:tree, :riparian, :bufo, :kermit].
The fix seems to be to reach into the meta-class for each derived class:
class Kozmik
def self.acts_as_frog(species)
@frog_list ||= []
@frog_list << species
self.class.send :attr_accessor, :frog_list
end
end
Is that as clean and lean as it could be? Is there some way to do this with
even fewer lines?
Next question: Couldn't class Kozmik be a module instead?
···
--
Phlip
http://www.oreilly.com/catalog/9780596510657/
^ assert_xpath
Phlip wrote:
...
class Kozmik
def self.acts_as_frog(species)
@frog_list ||=
@frog_list << species
self.class.send :attr_accessor, :frog_list
end
end
Is that as clean and lean as it could be? Is there some way to do this with
even fewer lines?
Next question: Couldn't class Kozmik be a module instead?
Sure...
module Kozmik
def acts_as_frog(species)
@frog_list ||=
@frog_list << species
self.class.send :attr_accessor, :frog_list
end
end
class Toad; extend Kozmik
...
end
Or is that cheating somehow?
···
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
Ari_Brown
(Ari Brown)
14 September 2007 21:45
3
Rubyists:
Here is one answering
class Kozmik
def self.acts_as_frog(species)
@frog_list ||=
@frog_list << species
self.class.send :attr_accessor, :frog_list
end
end
Is that as clean and lean as it could be? Is there some way to do this with
even fewer lines?
I am not really sure if this works, but couldn't you do:
class Kozmik
def self.inherited
module_eval do
@frog_list =
end
end
def self.acts_as_frog(species)
@frog_list << species
end
end
Also, does module_eval only work in a class method? Why can't I do def something; module_eval do puts 5 end; end ?
Ari
-------------------------------------------|
Nietzsche is my copilot
···
On Sep 14, 2007, at 5:00 PM, Phlip wrote:
Phlip1
(Phlip)
14 September 2007 21:27
4
Joel VanderWerf wrote:
class Toad; extend Kozmik
extend... different from include, right?
···
--
Phlip
Phlip wrote:
Joel VanderWerf wrote:
class Toad; extend Kozmik
extend... different from include, right?
If you need it to be #include , you can always call #extend from within #append_features as in ruby-talk:35979.
···
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407