How to Monkey Patch a Model in a Core from a Plugin
Added by Ben Wheeler over 10 years ago
I'm wondering how to monkey patch the watcher model from my plugin.
Running v2.5.2 of Redmine:
RAILS_ENV=development ruby script/rails server webrick -e development
My model looks like this:
class WatcherWeight < ActiveRecord::Base belongs_to :watcher end
I want my model's objects to delete when a watcher is deleted, so my patch looks like:
class Watcher < ActiveRecord::Base has_one :watcher_weight, dependent: :destroy end
And in my plugin's init.rb I have this:
ActionDispatch::Callbacks.to_prepare do #patches Rails.logger.debug 'WATCHLIST: hello world' require_dependency 'watcher' require_dependency 'plugins/watchlist/lib/watcher_patch' end
The problem is that my code only runs when my controller handles the response, not all the time (e.g. I need it to run on DELETE "/issues/{issue_id}/watchers/{watcher_id}" request.
Please let me know the best way to do this. This is my first time writing ruby at all let alone a rails/redmine plugin...
Replies (3)
RE: How to Monkey Patch a Model in a Core from a Plugin
-
Added by Martin Denizet (redmine.org team member) over 10 years ago
Hello Ben,
Your patch should look like:
module MyPlugin
module Patches
module WatcherPatch
def self.included(base) # :nodoc:
base.send(:include, InstanceMethods)
base.class_eval do
unloadable # Send unloadable so it will not be unloaded in development
has_one :watcher_weight, dependent: :destroy
end
end
end
end
Watcher .send(:include, MyPlugin::Patches::WatcherPatch)
Let me know if it works,
Cheers,
RE: How to Monkey Patch a Model in a Core from a Plugin
-
Added by Ben Wheeler over 10 years ago
Hi Martin,
Awesome! I cribbed off of the redmine_helpdesk plugin and figured out the above, but I was missing the "unloadable" keyword! That was the ticket.
My code now looks like this:
module Watchlist module WatcherPatch def self.included(base) # :nodoc: base.send(:include, InstanceMethods) base.class_eval do unloadable has_one(:watcher_weight, :dependent => :destroy) after_create :addWatcherWeight end end module InstanceMethods def addWatcherWeight WatcherWeight.create(:watcher_id => id, :weight => 0) end end end # module WatcherPatch end # module Watchlist # Add module to Watcher class Watcher.send(:include, Watchlist::WatcherPatch)
The only problem I'm having now is my watcher_weight record still does not get automatically deleted when the parent watcher record is destroyed. I thought this line should take care of that:
has_one(:watcher_weight, :dependent => :destroy)
What am I missing?
RE: How to Monkey Patch a Model in a Core from a Plugin
-
Added by Ben Wheeler over 10 years ago
I figured out that the watchable plugin calls delete_all rather than destroy, which doesn't honor :dependent => :destroy.