|
|
|
|
||||||
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
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 |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
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 |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
Joel VanderWerf wrote:
> class Toad; extend Kozmik extend... different from include, right? -- Phlip |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
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 |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
On Sep 14, 2007, at 5:00 PM, Phlip wrote: > 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 |
|
![]() |
| Outils de la discussion | |
|
|