我的第一堂课有不变。我想让它以某种方式工作作为动态价值。
class Post < ActiveRecord::Base
TEST = ["#{self.name}", "test1"]
end
class FakePost < Post
end
在rails console
我试图通过FakePost
访问TEST常量,但仍然显示self
为&#34; Post&#34;宾语。有没有办法实现这个目标?
当前
IRB(主):004:0&GT; FakePost ::测试
=&GT; [&#34;发布&#34;,&#34; test1&#34;]
但是当我通过Post而不是vi FakePost访问Constant时,我想返回这个结果。
预期:
IRB(主):004:0&GT; FakePost ::测试
=&GT; [&#34; FakePost&#34;,&#34; test1&#34;]
答案 0 :(得分:3)
问题是代码TEST = ["#{self.name}", "test1"]
仅在实例化Post
类时被解释一次。之后,它将被修复为["Post", "test1"]
。
在我的脑海中,我无法想到一种使用常量使其工作的方法,但是如果你用类方法替换它就可以正常工作:
class Post
def self.TEST
[self.name, "test1"]
end
end
class FakePost < Post
end
Post.TEST
#=> ["Post", "test1"]
FakePost.TEST
#=> ["FakePost", "test1"]
这样做的原因是类方法中的代码在运行时被解释(即当你调用方法时),而不是在解释类时。两种情况的时间表如下:
使用TEST
常量:
self.name
已解释并返回'Post'
,因为self
目前是Post
类。Post::TEST
不可撤销地设置为["Post", "test1"]
FakePost
类已实例化并从Post
继承,包括TEST
已经实例化的["Post", "test1"]
常量FakePost::TEST == Post::TEST == ["Post", "test1"] #=> true
使用TEST
类方法:
TEST
(但尚未解释)。FakePost
类已实例化,并从TEST
继承Post
类方法。尚未解释。Post.TEST
或FakePost.TEST
时,最终会解释该方法。 self
现在可以是Post
或FakePost
,具体取决于称为TEST
方法的类。答案 1 :(得分:1)
不能修改常量,因此当您在后继中引用它时,它将返回已分配的值。使用类方法。
class Post < ActiveRecord::Base
def self.test
["#{self.name}", "test1"]
end
end
class FakePost < Post
end
答案 2 :(得分:0)
正如其他人所指出的那样,TEST
在解析["Post", "test1"]
时被设置为等于Post
;它与简单TEST = ["Post", "test1"]
的行没有什么不同。
要从常量(TEST
)获得所需的结果,一种可能性是将TEST
设置为等于proc,然后使用self
作为参数调用该proc。这可以通过以下方式完成。
class News
TEST = ->(slf) { ["#{slf}", "test1"] }
end
class FakeNews < News
end
News.instance_eval { self::TEST[self] }
#=> ["News", "test1"]
FakeNews.instance_eval { self::TEST[self] }
#=> ["FakeNews", "test1"]
需要 BasicObject#instance_eval才能使self
等于instance_eval
的接收者。 Proc#[]与Proc#call相同(以及Proc.yield
,Proc#===
和折旧的Proc#()
[书面TEST.(self)
])。随便挑选!