Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extend model in plugin with "has_many" using a module

I have a some code in an engine style plugin which includes some models. In my app I want to extend one of these models. I have managed to add both instance and class methods to the model in question by including a module from within an initializer.

However I cannot seem to add associations, callbacks etc. I get a 'method not found' error.

/libs/qwerty/core.rb

module Qwerty
  module Core
    module Extensions

      module User
        # Instance Methods Go Here 

        # Class Methods
        module ClassMethods
          has_many  :hits, :uniq => true # no method found

          before_validation_on_create :generate_code # no method found

          def something # works!
            "something"
          end
        end

        def self.included(base)
          base.extend(ClassMethods)
        end
      end
    end
  end
end

/initializers/qwerty.rb

require 'qwerty/core/user'

User.send :include, Qwerty::Core::Extensions::User
like image 529
Kris Avatar asked Oct 05 '09 11:10

Kris


2 Answers

You should be able to do this. A little more concise IMHO.

module Qwerty::Core::Extensions::User
  def self.included(base)
    base.class_eval do
      has_many  :hits, :uniq => true
      before_validation_on_create :generate_code
    end
  end
end
like image 90
Subimage Avatar answered Oct 20 '22 07:10

Subimage


I think this should work

module Qwerty
  module Core
    module Extensions
      module User
      # Instance Methods Go Here 

        # Class Methods
        module ClassMethods
          def relate
            has_many  :hits, :uniq => true # no method found

            before_validation_on_create :generate_code # no method found
          end

          def something # works!
            "something"
          end
        end

        def self.included(base)
          base.extend(ClassMethods).relate
        end
      end
    end
  end
end

The old code is wrong cause the validation and the association are called upon module loading, and this module knows nothing about ActiveRecord. That's a general aspect of Ruby, code inside class or module bodies is called directly when loaded. You don't want that. To get around that you can use the above solution.

like image 45
khelll Avatar answered Oct 20 '22 08:10

khelll