重新打开 gem 提供的 ActiveRecord 模型 [英] Re-open an ActiveRecord model that's provided by a gem
问题描述
我正在尝试扩展一个 ActiveRecord 模型 (Vote
),它是一个 gem (https://github.com/peteonrails/vote_fu) 提供给我的应用程序.(即,app/models
中没有 vote.rb
)
I'm trying to extend an ActiveRecord model (Vote
) that a gem (https://github.com/peteonrails/vote_fu) provides to my application. (I.e., there is no vote.rb
in app/models
)
我的第一个方法是创建一个名为 lib/extend_vote.rb
的文件,其中包含代码:
My first approach was to create a file called lib/extend_vote.rb
that contains the code:
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)
.
This works when the first vote is created, but when I try to create each subsequent vote I get the error TypeError (can't dup NilClass)
.
我认为这个错误是由于 Vote
类在每次请求后自动重新加载,但 lib/extend_vote.rb
中的代码只加载一次当服务器启动时,这会导致 has_one :activity_stream_event
关联行为异常.(此外,如果我在 development.rb
中设置 config.cache_classes = true
,问题就会消失)
I think this error is caused by the fact that the Vote
class is reloaded automatically after every request, but the code in lib/extend_vote.rb
is loaded only once when the server starts and this causes the has_one :activity_stream_event
association to behave weirdly. (Also, the problem goes away if I set config.cache_classes = true
in development.rb
)
为了解决这个问题,我试图通过在我的 development.rb
中添加一个 to_prepare
块来重新加载每个请求的投票扩展:
To solve this problem, I tried to make the vote extensions reload on every request by adding a to_prepare
block to my development.rb
:
config.to_prepare do
load 'extend_vote.rb'
end
这解决了 (can't dup NilClass)
问题,但是现在每当我创建一个新投票时,create_activity_stream_event
回调都会被额外调用一次.即,第一次投票调用它一次,第二次调用它两次,等等.所以看起来 to_prepare
块太积极地重新加载扩展并添加重复的回调.
This solves the (can't dup NilClass)
problem, but now whenever I create a new vote, the create_activity_stream_event
callback gets called an additional time. I.e., the first vote calls it once, the second calls it twice, etc, etc. So it seems like the to_prepare
block is reloading the extension TOO aggressively and adding duplicate callbacks.
向这个 Vote
模型添加方法和回调的最佳方法是什么?
What's the best way to add methods and callbacks to this Vote
model?
推荐答案
[更新:应该是防止模块被多次包含在同一个类中的正确解决方案]
[UPDATE: should be the right solution to prevent the module being include several times in the same class]
我相信你可以使用 ActiveSupport::Concern 来防止模块被包括多次调用的回调结果.请参阅下面的示例:
I believe you can use ActiveSupport::Concern to prevent the module being include several times which result by callback called several time. See the example below :
module VotePatch
extend ActiveSupport::Concern
included do
after_create :create_activity_stream_event
has_one :activity_stream_event
end
module InstanceMethods
def create_activity_stream_event
#your code here
end
end
end
Vote.send(:include, VotePatch)
这篇关于重新打开 gem 提供的 ActiveRecord 模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!