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