Rails 'forgets' class 在初始化器和查询之间
Rails 'forgets' class between initializer and queries
我在 Rails 上遇到了一个特殊问题。
我们已经设置了一个 Hook
class 来处理我们应用程序内部的一个小 pub/sub 机制,它是这样的
class Hook
@subscriptions = {}
class << self
def subscribe(message, &block)
@subscriptions[message] ||= []
@subscriptions[message] << block
end
def publish(message)
@subscriptions[message].each(&:call)
end
end
end
(有点充实,但你明白了)。
问题是:
在初始化器中我们有 Hook.subscribe(:change) { ... }
但是当模型调用 Hook.publish(:change)
时,没有任何反应。快速检查表明,在模型再次调用 Hook
之前,defined? Hook
returns nil
.
模型中的代码为
after_commit do
# byebug
Hook.publish(:change)
end
甚至更奇怪:在初始化程序中我设置了一个全局变量来保存常量 $hook = Hook
,该常量确实在模型中的 $hook
变量中,但与 Hook 不匹配它会自动加载。
# inside a debugger in the model
> defined? Hook
=> nil
> $hook
=> Hook
> Hook # will trigger autoloading
=> Hook
> defined? Hook
=> "constant"
> Hook == $hook
=> false
> Hook.instance_variable_get(:@subscriptions)
=> {}
> $hook.instance_variable_get(:@subscriptions)
=> { change: [<Proc:...>] }
> Hook.object_id == $hook.object_id
=> false
如果我通过调试器将它设置回常量 Hook = $hook
,一切都会再次正常运行 — 常量在请求中使用适当的变量维护,甚至。
我已经无计可施了。有人知道会发生什么吗?
我终于找到了一个修复程序,即使我不完全理解它(我仍然不太清楚 Rails 如何处理自动加载我猜 - 我需要更深入地调查当我有时间)。
Hook
class 在一个模块 (OurApp::Hook
) 中,为了清楚起见,我在我分享的示例中省略了它(显然是我的错误)。
我注意到 OurApp.constants
丢失了一些除 Hook
之外的常量。
我进入 lib/our_app.rb
并对其进行了修改:
module OurApp
autoload :Hook, 'lib/our_app/hook.rb'
# ...
end
这似乎可以解决问题,没有更多问题了。
谢谢大家!
我在 Rails 上遇到了一个特殊问题。
我们已经设置了一个 Hook
class 来处理我们应用程序内部的一个小 pub/sub 机制,它是这样的
class Hook
@subscriptions = {}
class << self
def subscribe(message, &block)
@subscriptions[message] ||= []
@subscriptions[message] << block
end
def publish(message)
@subscriptions[message].each(&:call)
end
end
end
(有点充实,但你明白了)。
问题是:
在初始化器中我们有 Hook.subscribe(:change) { ... }
但是当模型调用 Hook.publish(:change)
时,没有任何反应。快速检查表明,在模型再次调用 Hook
之前,defined? Hook
returns nil
.
模型中的代码为
after_commit do
# byebug
Hook.publish(:change)
end
甚至更奇怪:在初始化程序中我设置了一个全局变量来保存常量 $hook = Hook
,该常量确实在模型中的 $hook
变量中,但与 Hook 不匹配它会自动加载。
# inside a debugger in the model
> defined? Hook
=> nil
> $hook
=> Hook
> Hook # will trigger autoloading
=> Hook
> defined? Hook
=> "constant"
> Hook == $hook
=> false
> Hook.instance_variable_get(:@subscriptions)
=> {}
> $hook.instance_variable_get(:@subscriptions)
=> { change: [<Proc:...>] }
> Hook.object_id == $hook.object_id
=> false
如果我通过调试器将它设置回常量 Hook = $hook
,一切都会再次正常运行 — 常量在请求中使用适当的变量维护,甚至。
我已经无计可施了。有人知道会发生什么吗?
我终于找到了一个修复程序,即使我不完全理解它(我仍然不太清楚 Rails 如何处理自动加载我猜 - 我需要更深入地调查当我有时间)。
Hook
class 在一个模块 (OurApp::Hook
) 中,为了清楚起见,我在我分享的示例中省略了它(显然是我的错误)。
我注意到 OurApp.constants
丢失了一些除 Hook
之外的常量。
我进入 lib/our_app.rb
并对其进行了修改:
module OurApp
autoload :Hook, 'lib/our_app/hook.rb'
# ...
end
这似乎可以解决问题,没有更多问题了。
谢谢大家!