Topic: Plugin help

I've written a plugin which patches ActiveRecord, much like acts_as_paranoid, but I would like the patch to be applied to all models that inherit from ActiveRecord.  The only examples of plugins which patch ActiveRecord that I can find, simply rely on the user entering "acts_as_paranoid" or some similar method name in each model.  I'd like this plugin to automatically be applied to every ActiveRecord model.

Below is a snippet of the module which gets included in ActiveRecord when the plugin loads:

module Viget
  module Permissions
    module AdminMassAssignment
      def self.included(base)
        base.extend ClassMethods
      end

      module ClassMethods
        def admin_mass_assignment
          unless mass_assignment?
            alias_method :original_update_attributes, :update_attributes
            class << self
              alias_method :original_new, :new
            end
          end
          include InstanceMethods
        end


Does anyone have an idea of a way that I can get this plugin to be automatically applied to each model?

Edit: I read the other recent thread about mixins and the solution proposed there did not work.  My include logic looks like:
ActiveRecord::Base.send :include, Viget::Permissions::AdminMassAssignment
and yet the models don't seem to know I've patched them without explicitly stating "admin_mass_assignment" in each of them.

Last edited by Weexpectedthis (2007-08-01 08:51:54)

Kyle Peyton - Web Developer
Santa Clara, CA - Startontop

Re: Plugin help

The reason the code will only work if you put admin_mass_assignment is because you've contained the code within that method. You don't neccessarily have to though:

module ClassMethods
  unless mass_assignment?
  alias_method :original_update_attributes, :update_attributes
  class << self
    alias_method :original_new, :new
  end
end

That should make the changes without you having to call admin_mass_assignment.

Alex

Re: Plugin help

I modified the mixin and commented out the method definition lines:

module Viget
  module Permissions
    module AdminMassAssignment
      def self.included(base)
        base.extend ClassMethods
      end

      module ClassMethods
#        def admin_mass_assignment
          unless mass_assignment?
            alias_method :original_update_attributes, :update_attributes
            class << self
              alias_method :original_new, :new
            end
          end
          include InstanceMethods
#        end


No difference in behavior, still none of my tests pass.

Kyle Peyton - Web Developer
Santa Clara, CA - Startontop

Re: Plugin help

But if you uncomment those lines, then put admin_mass_assignment in the model, the tests pass?

Alex

Re: Plugin help

Yes sir.

Kyle Peyton - Web Developer
Santa Clara, CA - Startontop

Re: Plugin help

That's funny... there must be a reason I suppose, but I can't think of what it might be. But I suppose a work around may be to add the line:

ActiveRecord::Base.send(:admin_mass_assignment)

under the line to include the module.

Alex

Re: Plugin help

I agree that is seems funny and I'm wondering if it has anything to do with the fact that I'm patching :new, :create, and :update_attributes on ActiveRecord.

I tried adding the line:

ActiveRecord::Base.send :admin_mass_assignment

after my include line, but it only fixed one of 3 broken tests.

Then I tried:

Account.send :admin_mass_assignment

instead and all tests passed.

I'm baffled by this issue.

Kyle Peyton - Web Developer
Santa Clara, CA - Startontop

Re: Plugin help

Hmmm... the only other suggestion I have would be to put:

class ActiveRecord::Base
  def self.inherited(c)
    c.admin_mass_assignment
  end
end

in your init.rb, which would run admin_mass_assignment on all classes inheriting from ActiveRecord::Base.

Alex

Re: Plugin help

Thanks for that last suggestion, it seemed to work.

Kyle Peyton - Web Developer
Santa Clara, CA - Startontop