开发者

proper way of extending ActiveRecord::Base

I have extended the ActiveRecord::Base class in the following way:

  • I made a directory under the lib, let's call it now foo
  • wrote the module which provides the extra method has_many_bidirectional to have bidirectional has_many relationships in ActiveRecord::Base classes
  • in the lib/foo/active_record.rb:

    module Foo
      module ActiveRecord
        autoload :Associations, 'active_record/associations'
        autoload :Base, 'active_record/base'
      end
    end
    
  • in the lib/foo/active_record/base.rb:

    module Foo
      module ActiveRecord
        module Base
          def self.included(base)
            base.class_eval do
              include Associations
            end
        开发者_开发百科  end
        end
      end
    end
    
  • and of course the real code in lib/foo/active_record/associations.rb:

    module Foo
      module ActiveRecord
        module Associations
    
          def self.included(base)
            base.extend(ClassMethods)
          end
    
          module ClassMethods
            def has_many_bidirectional(...)
              # ...
            end
          end
        end
      end
    end
    
  • extended the ActiveRecord::Base class in the config/environment.rb with the following code at the end of the configuration file:

    ActiveRecord::Base.class_eval do
      include Foo::ActiveRecord::Base
    end
    
  • with this way Rails was properly included my module, and I could use it without any problem

  • until I wanted to observe an extended class, because in the config/environment.rb the config.active_record.observers part is before the extending part, and the observable class does not know anything about the new method at that point.

The following error produced:

/Library/Ruby/Gems/1.8/gems/activerecord-2.3.10/lib/active_record/base.rb:1998:in `method_missing': undefined method `has_many_bidirectional' for #<Class:0x1032f2fc0> (NoMethodError)
        from .../app/models/user.rb:27

My question is, which is the correct way to extend the ActiveRecord::Base class? (I don't want to use callback methods in my User class.)

Do I really have to create a gem instead of a module under the lib directory to have this functionality?

Thanks!


As I digged it out, the best way is to create a plugin with the generator:

./script/generate plugin has_many_bidirectional

And with this way Rails will include it before the observer part. A good tutorial can be found here.

All of my previous code can be easily adopted to this way.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜