English 中文(简体)
Redmine Plugins - Detecting enabling and disabling of modules
原标题:

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

最佳回答

I ended up reimplementing the enabled_module_names= method of projects, including a file in vendor/plugins/my_plugin/lib/my_plugin/patches/project_patch.rb and alias.

module MyPlugin
  module Patches
    module ProjectPatch
      def self.included(base)
        base.send(:include, InstanceMethods)
        base.extend(ClassMethods)
        base.class_eval do
          unloadable # Send unloadable so it will not be unloaded in development

          # This replaces the existing version of enabled_module_names with a new one
          # It is needed because we need the "destroy" callbacks to be fired,
          # and only on the erased modules (not all of them - the default 
          # implementation starts by wiping them out in v0.8 ish)
          alias_method :enabled_module_names=, :sympa_enabled_module_names=
        end
      end

      module ClassMethods
      end

      module InstanceMethods

        # Redefine enabled_module_names so it invokes 
        # mod.destroy on disconnected modules
        def sympa_enabled_module_names=(module_names)

          module_names = [] unless module_names and module_names.is_a?(Array)
          module_names = module_names.collect(&:to_s)
          # remove disabled modules
          enabled_modules.each {|mod| mod.destroy unless module_names.include?(mod.name)}

          # detect the modules that are new, and create those only
          module_names.reject {|name| module_enabled?(name)}.each {|name| enabled_modules << EnabledModule.new(:name => name) }
        end
      end
    end
  end
end

I had to include some code on my vendor/plugins/my_plugin/init.rb file, too:

require  redmine 

require  dispatcher 

# you can add additional lines here for patching users, memberships, etc...
Dispatcher.to_prepare :redmine_sympa do
  require_dependency  project 
  require_dependency  enabled_module 

  Project.send(:include, RedmineSympa::Patches::ProjectPatch)
  EnabledModule.send(:include, RedmineSympa::Patches::EnabledModulePatch)

end

Redmine::Plugin.register :redmine_sympa do
# ... usual redmine plugin init stuff
end

After this, I was able to detect deletions on enabled modules (via before_delete) on my patcher.

问题回答

It looks like revision 2473 onwards of Redmine should solve your problem. See the diffs here: http://www.redmine.org/projects/redmine/repository/diff/trunk/app/models/project.rb?rev=2473&rev_to=2319

Basically the code has been modified such that removed modules are destroyed rather than deleted, the difference being that model callbacks are not fired for deletes.

There s another related fix in revision 3036 that seems important (see http://www.redmine.org/issues/4200) so you might want to pick up at least that version.

Regarding:

If I use after_update, how can I get the previous project_id

Maybe try project_id_was, it s provided by ActiveRecord::Dirty





相关问题
rails collection_select vs. select

collection_select and select Rails helpers: Which one should I use? I can t see a difference in both ways. Both helpers take a collection and generates options tags inside a select tag. Is there a ...

SSL slowness in EC2

We ve deployed our rails app to EC2. In our setup, we have two proxies on small instances behind round-robin DNS. These run nginx load balancers for a dynamically growing and shrinking farm of web ...

Auth-code with A-Za-z0-9 to use in an URL parameter

As part of a web application I need an auth-code to pass as a URL parameter. I am currently using (in Rails) : Digest::SHA1.hexdigest((object_id + rand(255)).to_s) Which provides long strings like : ...

RubyCAS-Client question: Rails

I ve installed RubyCAS-Client version 2.1.0 as a plugin within a rails app. It s working, but I d like to remove the ?ticket= in the url. Is this possible?

activerecord has_many :through find with one sql call

I have a these 3 models: class User < ActiveRecord::Base has_many :permissions, :dependent => :destroy has_many :roles, :through => :permissions end class Permission < ActiveRecord::...

Ordering a hash to xml: Rails

I m building an xml document from a hash. The xml attributes need to be in order. How can this be accomplished? hash.to_xml

Text Editor for Ruby-on-Rails

guys which text editor is good for Rubyonrails? i m using Windows and i was using E-Texteditor but its not free n its expired now can anyone plese tell me any free texteditor? n which one is best an ...

How to get SQL queries for each user where env is production

I’m developing an application dedicated to generate statistical reports, I would like that user after saving their stat report they save sql queries too. To do that I wrote the following module: ...

热门标签