M
m4dc4p
I spent a day figuring out how to solve this problem, and it seems like
there should be a much better solution. I wanted to write a module
that, when included in an object, would create a class variable and
accessor for that object. If another class includes the module, it
should have its own class variable and accessor. The class variable
does *not* live in the module - it is not shared by all objects which
include the module.
A simplified version of what I came up with is below. Module Foo
defines the class variable and accessor. Class Bar and Baz are related
by inheritance. Instance variables a and b are of class Bar and Baz.
Instance variable w is of class Bil, which is not related to either Bar
or Baz.
When a value is added to the "prop" class variable of either a or
b, they both show it. However, when a value is added to the "prop"
class variable in w, it does not show up in either a or b.
I'm convinced there is a better way to do this and what I came up
with is just a hack on a kludge. Any and all help is appreciated!
module Foo
def self.included(mod)
super(mod)
class << mod; self; end.class_eval <<-EOS
@prop = []
def prop
@prop ||= []
end
EOS
def mod.inherited(p)
def p.prop
superclass.prop
end
end
end
end
class Bar
include Foo
end
class Baz < Bar
end
class Bil
include Foo
end
a = Bar.new
b = Bar.new
x = Baz.new
w = Bil.new
a.class.prop << "p1"
puts "a, b, and x share property added to a:
#{a.class.prop.inspect},
#{b.class.prop.inspect},
#{x.class.prop.inspect}"
b.class.prop << "p2"
puts "and property added to b:
#{a.class.prop.inspect},
#{b.class.prop.inspect},
#{x.class.prop.inspect}"
w.class.prop << "p3"
puts "but not a property added to w.
a: #{a.class.prop.inspect},
b: #{b.class.prop.inspect},
x: #{x.class.prop.inspect},
w: #{w.class.prop.inspect}"
#>ruby mod_test.rb
#a, b, and x share property added to a:
# ["p1"],
# ["p1"],
# ["p1"]
#and property added to b:
# ["p1", "p2"],
# ["p1", "p2"],
# ["p1", "p2"]
#but not a property added to w.
# a: ["p1", "p2"],
# b: ["p1", "p2"],
# x: ["p1", "p2"],
# w: ["p3"]
p.s. The implementation here relies on the append_features method of
module, and the inherited method of objects. When an object first
includes the module, the class variable and property are added to the
object via append_features. I found that this this did NOT extend down
the inheritance chain for those objects, though. I was forced to
override the inherrited method on the initial object so I could place
the 'properties' definition in each subclass. This is my least favorite
part of my solution.
there should be a much better solution. I wanted to write a module
that, when included in an object, would create a class variable and
accessor for that object. If another class includes the module, it
should have its own class variable and accessor. The class variable
does *not* live in the module - it is not shared by all objects which
include the module.
A simplified version of what I came up with is below. Module Foo
defines the class variable and accessor. Class Bar and Baz are related
by inheritance. Instance variables a and b are of class Bar and Baz.
Instance variable w is of class Bil, which is not related to either Bar
or Baz.
When a value is added to the "prop" class variable of either a or
b, they both show it. However, when a value is added to the "prop"
class variable in w, it does not show up in either a or b.
I'm convinced there is a better way to do this and what I came up
with is just a hack on a kludge. Any and all help is appreciated!
module Foo
def self.included(mod)
super(mod)
class << mod; self; end.class_eval <<-EOS
@prop = []
def prop
@prop ||= []
end
EOS
def mod.inherited(p)
def p.prop
superclass.prop
end
end
end
end
class Bar
include Foo
end
class Baz < Bar
end
class Bil
include Foo
end
a = Bar.new
b = Bar.new
x = Baz.new
w = Bil.new
a.class.prop << "p1"
puts "a, b, and x share property added to a:
#{a.class.prop.inspect},
#{b.class.prop.inspect},
#{x.class.prop.inspect}"
b.class.prop << "p2"
puts "and property added to b:
#{a.class.prop.inspect},
#{b.class.prop.inspect},
#{x.class.prop.inspect}"
w.class.prop << "p3"
puts "but not a property added to w.
a: #{a.class.prop.inspect},
b: #{b.class.prop.inspect},
x: #{x.class.prop.inspect},
w: #{w.class.prop.inspect}"
#>ruby mod_test.rb
#a, b, and x share property added to a:
# ["p1"],
# ["p1"],
# ["p1"]
#and property added to b:
# ["p1", "p2"],
# ["p1", "p2"],
# ["p1", "p2"]
#but not a property added to w.
# a: ["p1", "p2"],
# b: ["p1", "p2"],
# x: ["p1", "p2"],
# w: ["p3"]
p.s. The implementation here relies on the append_features method of
module, and the inherited method of objects. When an object first
includes the module, the class variable and property are added to the
object via append_features. I found that this this did NOT extend down
the inheritance chain for those objects, though. I was forced to
override the inherrited method on the initial object so I could place
the 'properties' definition in each subclass. This is my least favorite
part of my solution.