我在Rails 4.2中有一个可订购的问题,有一个常数" Complete"。 app/models/concerns/orderable.rb
:
module Orderable
extend ActiveSupport::Concern
COMPLETE = "Complete"
end
在Rails控制台中,我可以运行Orderable.constants
,返回[:COMPLETE]
。但是,如果我将可订购的问题更改为" low-cruft" Rails concerning module中描述的样式如此:
concern :Orderable do
COMPLETE = "Complete"
end
然后在Rails控制台中运行Orderable.constants
返回[]
。 Rails的文档说明,用来定义问题的"低空缺口捷径是等价的。"为什么这种单一变化会导致失去对模块常量的访问?我需要以某种方式重新定义它们吗?
答案 0 :(得分: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
此代码monkeypat the ruby Module对象以提供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”语法。