重新打开由宝石提供的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
)
我的第一个方法是创建一个名为 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 ..
结束
结束
这在创建第一张投票时有效,但当我尝试创建每个后续投票我得到错误 TypeError(不能重复NilClass)
。
我认为这个错误是这是由于在每个请求后自动重载 Vote
类,但是 lib / extend_vote.rb
仅在服务器启动时加载一次,这会导致 has_one:activity_stream_event
关联表现异常。 (此外,如果我在 development.rb
中设置 config.cache_classes = true
),问题就消失了。
为了解决这个问题,我试图通过向我的<$ c添加一个 to_prepare
块来重新加载投票扩展$ c> development.rb :
config.to_prepare do
load'extend_vote。 rb'
end
解决了(can not dup NilClass)
问题,但现在无论何时创建新投票,都会调用 create_activity_stream_event
回调函数。也就是说,第一次投票调用它一次,第二次调用它两次,等等等等。所以看起来像 to_prepare
块正在积极地重新加载扩展TOO并添加重复的回调。
为这个投票
模型添加方法和回调的最佳方式是什么?
我相信您可以使用 ActiveSupport :: Concern 来阻止模块的存在包括由几次回调导致的几次。
请参阅下面的示例:
module VotePatch
扩展ActiveSupport :: Concern
包含
after_create:create_activity_stream_event
has_one:activity_stream_event
end
模块InstanceMethods
def create_activity_stream_event
#您的代码在这里
结束
结束
结束
Vote.send(:include,VotePatch)
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
)
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
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)
.
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
)
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
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.
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]
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)
这篇关于重新打开由宝石提供的ActiveRecord模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!