From: Tamara Temple Date: 2013-06-02T07:28:22+09:00 Subject: Re: Is it a bug(about constant reference on dynamic class). jin chizhong wrote: > When I use a dynamic class, It can not reference constants. > See follow code and remark. > And is there any way to work around it? > > #!/usr/bin/env ruby > > class T > def hello > puts self.class.constants.join " " # right, AAA > puts AAA # right, 1 > end > end > > T::AAA = 1 > > t = T.new > t.hello > > > c = Class.new do > def hello > puts self.class.constants.join " " # right, AAA > puts AAA # error: uninitialized constant AAA (NameError) > end > end > > c::AAA = 123 > inst = c.new > inst.hello > > -- > Posted via http://www.ruby-forum.com/. > ENOTABUG :) (for in-depth, read "Metaprogramming Ruby") When you do t = T.new, you are getting something different than when you do inst = c.new: irb(main):039:0> class T;def hello;puts self.class.constants.join " ";puts T_0; end; end => nil irb(main):040:0> t=T.new => # irb(main):041:0> t.hello NameError: uninitialized constant T::T_0 from (irb):39:in `hello' from (irb):41 from /home/tamara/.rvm/rubies/ruby-1.9.3-p392/bin/irb:13:in `
' irb(main):042:0> T::T_0 = "This is now set" => "This is now set" irb(main):043:0> t.hello T_0 This is now set => nil and now using the Class object: irb(main):002:0> c = Class.new{def hello;p self.class.constants; p self.class.const_get("C_0");end} => # irb(main):003:0> c0 = c.new => #<#:0x89ed3e4> irb(main):004:0> c0.hello [] NameError: uninitialized constant #::C_0 from (irb):2:in `const_get' from (irb):2:in `hello' from (irb):4 from /home/tamara/.rvm/rubies/ruby-1.9.3-p392/bin/irb:13:in `
' irb(main):005:0> c0.class.const_set("C_0","this is now set") => "this is now set" irb(main):006:0> c0.hello [:C_0] "this is now set" => "this is now set" irb(main):007:0> c0.class.const_set("C_1","this is another class constant") => "this is another class constant" irb(main):008:0> c0.hello [:C_0, :C_1] "this is now set" => "this is now set" irb(main):009:0> c0.class.const_get("C_1") => "this is another class constant" irb(main):010:0> The main thing to note is the extra level of indirection in the second case: irb(main):040:0> t=T.new => # Notice in this case the named type T, vs here: irb(main):003:0> c0 = c.new => #<#:0x89ed3e4> the indirection, thus the main difference in ruby's syntactic ability to deal with things. Doing this: T::T_0 = 'sommat' is under the hood doing the same thing above: irb(main):025:0> class T;def hello;p self.class.constants; p T_0;end;end => nil irb(main):026:0> T.new.hello [] NameError: uninitialized constant T::T_0 from (irb):25:in `hello' from (irb):26 from /home/tamara/.rvm/rubies/ruby-1.9.3-p392/bin/irb:13:in `
' irb(main):027:0> T.const_set("T_0","set via const_set") => "set via const_set" irb(main):028:0> T.new.hello [:T_0] "set via const_set" => "set via const_set" irb(main):029:0> T::T_0 = "set via T::" (irb):29: warning: already initialized constant T_0 => "set via T::" irb(main):030:0> T.new.hello [:T_0] "set via T::" => "set via T::"