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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With