From: nobu.nakada@... Date: 2000-02-20T20:57:54+09:00 Subject: [ruby-list:20876] active attribute --Multipart_Sun_Feb_20_20:57:15_2000-1 Content-Type: text/plain; charset=ISO-2022-JP なかだです。 あぅ。さっきのは subject 間違ってます(;_;)。こっちが active attribute、あっちは aliasing module のはずでした。 で、リサイクル第2段。実は active attribute って何を指してるか よく分かってなかったりしますが、こういうもんでしょうか。 --Multipart_Sun_Feb_20_20:57:15_2000-1 Content-Type: text/plain; subtype="ruby"; charset=US-ASCII Content-Disposition: attachment; filename="activeattr.rb" Content-Transfer-Encoding: 7bit class Module class ActiveAttr < Module Separator = '.'.freeze ThreadKey = nesting[0].to_s.intern def self.new(obj, name, &defs) String === name or name = name.id2name opref, owner = Thread.current[ThreadKey] prefix = opref.to_s + name + Separator actor = super() adaptor = Class.new(Adaptor) begin Thread.current[ThreadKey] = [prefix, adaptor] actor.adapt(adaptor, prefix, &defs) adaptor.bind(owner || obj, name, (opref ? '@owner' : 'self')) ensure Thread.current[ThreadKey] = ([opref, owner] if opref) end actor end def adapt(adaptor, prefix, &defs) module_eval(&defs) im = instance_methods - Module.instance_methods im.each do |m| alias_method(prefix + m, m) remove_method(m) end adaptor.prefix(prefix, im) end class Adaptor def self.prefix(pref, meths) meths.each do |m| module_eval "def #{m}(*args) @owner.__send__(#{(pref + m).intern}, *args) end" end self end def self.bind(owner, name, msg) adaptor = self owner.module_eval %{ @#{name} = adaptor def #{name} @#{name} ||= self.type.instance_eval {@#{name}}.new(#{msg}) end } end def initialize(owner) @owner = owner end end end def active_attr(name, &defs) include(ActiveAttr.new(self, name, &defs)) end end if __FILE__ == $0 class A attr_reader :v def initialize @v = [] end active_attr :x do def []=(*args) v = args.pop @v[*args] = v end def [](*args) @v[*args] end def q @v end active_attr :y do attr_accessor :v end end active_attr :y do # distinguished to x.y, so y.v causes exception end end a = A.new # shuffle test data s = (0...10).to_a while i = s.size.nonzero? a.v << s[i = rand(i)] s[i, 1] = nil end require 'ok' ok = Check['active attribute'] ok[a.x.q == a.v] ok[a.x.y.v == a.v] ok[begin a.y.v; nil; rescue NameError; $! end] end --Multipart_Sun_Feb_20_20:57:15_2000-1 Content-Type: text/plain; charset=ISO-2022-JP -- そうだ 強気に ちょっと インチキに☆彡 中田 "Bugるくらいがちょうどいいかも;-)" 伸悦 --Multipart_Sun_Feb_20_20:57:15_2000-1--