在Rails 4.2中,我有一个可排序的关注点,它有一个不变的“完整”。app/models/concerns/orderable.rb
module Orderable
extend ActiveSupport::Concern
COMPLETE = "Complete"
end在Rails控制台中,我能够运行Orderable.constants,它返回[:COMPLETE]。但是,如果我将可排序的关注点更改为 module中描述的“低巡洋洋”样式,如下所示:
concern :Orderable do
COMPLETE = "Complete"
end然后在Rails控制台中运行Orderable.constants返回[]。Rails文档说,“定义一个关注点的低端捷径.是等价的。”为什么这一项更改会影响对模块常量的访问?我需要重新定义他们吗?
发布于 2018-05-04 11:03:31
实际上,这似乎是在如何实现“宏”方面的一个缺陷:
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对象转换为提供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我会避免使用“低巡洋舰”语法,直到这是固定的。
https://stackoverflow.com/questions/50165220
复制相似问题