I'm working with an external framework (redmine) which has one Project
model that has_many EnabledModules
.
Projects can have EnabledModules "attached" or "removed" via the module names, like this:
class Project < ActiveRecord::Base
...
has_many :enabled_modules, :dependent => :delete_all
...
def enabled_module_names=(module_names)
enabled_modules.clear
module_names = [] unless module_names && module_names.is_a?(Array)
module_names.each do |name|
enabled_modules << EnabledModule.new(:name => name.to_s)
end
end
end
I'd like to detect when new modules are attached/removed via callbacks on EnabledModule
, and not modify the "original source code" if possible.
I can detect "attachments" like this:
class EnabledModule < ActiveRecord::Base
belongs_to :project
after_create :module_created
def module_created
logger.log("Module attached to project #{self.project_id}")
end
end
I thought that a before_destroy
would work for detecting removals, but it will not.
This happens because the enabled_modules.clear
call on Project.enabled_module_names=
, doesn't invoke 'destroy' on the modules. It just sets their project_id
to nil. So I figured I should use a after_update
or before_update
.
If I use after_update
, how can I get the 'previous' project_id
?
If I use before_update
, how can I differentiate between modules that are 'just updated' and modules whose project_id is going to be reset to nil?
Should I use a totally different approach here?
EDIT: I just found out that I could get the old values with '_was' (i.e. self.project_was
). However, collection.clear
doesn't seem to trigger update callbacks. Any other solutions?
EDIT 2: Changed title