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 nowfoo
- wrote the module which provides the extra method
has_many_bidirectional
to have bidirectional has_many relationships inActiveRecord::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 theconfig/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
theconfig.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.
精彩评论