提问人:aaronkelton 提问时间:5/4/2018 更新时间:5/4/2018 访问量:92
为什么 Rails 低 cruft 问题会导致模块失去其常量?
Why does the Rails low-cruft concern cause the module to lose its constants?
问:
我在 Rails 4.2 中有一个 Orderable 问题,常量为 “Complete”。:app/models/concerns/orderable.rb
module Orderable
extend ActiveSupport::Concern
COMPLETE = "Complete"
end
在 Rails 控制台中,我能够运行 ,它返回 .但是,如果我将 Orderable 关注点更改为 Rails 相关模块中描述的“低粗制滥造”样式,如下所示:Orderable.constants
[:COMPLETE]
concern :Orderable do
COMPLETE = "Complete"
end
然后在 Rails 控制台中运行返回 .Rails 文档说,“定义关注点的低粗制滥造的捷径......是等价的。为什么这个单一的更改会产生失去对模块常量的访问的影响?我需要以某种方式重新定义它们吗?Orderable.constants
[]
答:
1赞
max
5/4/2018
#1
实际上,这似乎是关注“宏观”实现方式的一个缺陷:
require 'active_support/concern'
class Module
# A low-cruft shortcut to define a concern.
#
# concern :EventTracking do
# ...
# end
#
# is equivalent to
#
# module EventTracking
# extend ActiveSupport::Concern
#
# ...
# end
def concern(topic, &module_definition)
const_set topic, Module.new {
extend ::ActiveSupport::Concern
module_eval(&module_definition)
}
end
end
include Concerning
end
此代码对 ruby Module 对象进行 monkeypatch 以提供方法。concern
这里的关键是,在定义的新模块的上下文中,它没有正确评估块。module_eval(&module_definition)
运行时实际发生的情况:
concern :Orderable do
COMPLETE = "Complete"
end
::COMPLETE
# => "Complete"
是你在主对象中声明常量。哎呀!COMPLETE
为了正常工作,它应该看起来像这样:
def concern(topic, &module_definition)
const_set topic, Module.new do |m|
extend ::ActiveSupport::Concern
m.module_eval(&module_definition)
end
end
在解决这个问题之前,我会避免使用“low-cruft”语法。
评论