为什么 Rails low-cruft 问题会导致模块丢失其常量?
Why does the Rails low-cruft concern cause the module to lose its constants?
我在 Rails 4.2 中有一个常量 "Complete" 的可订购问题。 app/models/concerns/orderable.rb
:
module Orderable
extend ActiveSupport::Concern
COMPLETE = "Complete"
end
在 Rails 控制台中,我可以 运行 Orderable.constants
,returns [:COMPLETE]
。但是,如果我将可订购关注点更改为 Rails concerning module 中描述的 "low-cruft" 样式,如下所示:
concern :Orderable do
COMPLETE = "Complete"
end
然后 运行在 Rails 控制台 returns []
中宁 Orderable.constants
。 Rails 文档说 "low-cruft short cut to define a concern ... is equivalent." 为什么这个单一的更改会导致失去对模块常量的访问权限?我需要以某种方式重新定义它们吗?
这似乎实际上是关注点 "macro" 的实施方式存在缺陷:
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
在修复此问题之前,我会避免使用 "low-cruft" 语法。
我在 Rails 4.2 中有一个常量 "Complete" 的可订购问题。 app/models/concerns/orderable.rb
:
module Orderable
extend ActiveSupport::Concern
COMPLETE = "Complete"
end
在 Rails 控制台中,我可以 运行 Orderable.constants
,returns [:COMPLETE]
。但是,如果我将可订购关注点更改为 Rails concerning module 中描述的 "low-cruft" 样式,如下所示:
concern :Orderable do
COMPLETE = "Complete"
end
然后 运行在 Rails 控制台 returns []
中宁 Orderable.constants
。 Rails 文档说 "low-cruft short cut to define a concern ... is equivalent." 为什么这个单一的更改会导致失去对模块常量的访问权限?我需要以某种方式重新定义它们吗?
这似乎实际上是关注点 "macro" 的实施方式存在缺陷:
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
在修复此问题之前,我会避免使用 "low-cruft" 语法。