【发布时间】:2012-06-01 10:16:49
【问题描述】:
我正在尝试扩展 gem (https://github.com/peteonrails/vote_fu) 为我的应用程序提供的 ActiveRecord 模型 (Vote)。 (即,app/models 中没有 vote.rb)
我的第一个方法是创建一个名为 lib/extend_vote.rb 的文件,其中包含代码:
Vote.class_eval do
after_create :create_activity_stream_event
has_one :activity_stream_event
def create_activity_stream_event
# something..
end
end
这在创建第一个投票时有效,但是当我尝试创建每个后续投票时,我收到错误 TypeError (can't dup NilClass)。
我认为这个错误是由于Vote 类在每次请求后自动重新加载,但lib/extend_vote.rb 中的代码仅在服务器启动时加载一次,这会导致has_one :activity_stream_event 关联行为奇怪。 (另外,如果我在development.rb 中设置config.cache_classes = true,问题就会消失)
为了解决这个问题,我尝试通过将to_prepare 块添加到我的development.rb 来使投票扩展在每个请求上重新加载:
config.to_prepare do
load 'extend_vote.rb'
end
这解决了(can't dup NilClass) 问题,但现在每当我创建一个新投票时,create_activity_stream_event 回调就会被调用一次。即,第一次投票调用它一次,第二次调用它两次,等等。所以看起来to_prepare 块正在积极地重新加载扩展并添加重复的回调。
向这个Vote 模型添加方法和回调的最佳方式是什么?
【问题讨论】:
-
如果你只使用
class Vote而不是Vote.class_eval是否有效?您还可以做的一件事是在 gem 本身中编辑代码,然后使用修改后的版本。 -
class Vote的行为与Vote.class_eval相同——两者都不起作用。我想我可以修改 gem,但我真的不想大声笑。真是一团糟! -
您认为为什么会重新加载 Vote 类?在 resposity 中,该类位于 lib 目录中,因此与您相同...
标签: ruby-on-rails model gem metaprogramming