The correct way to extend ActiveRecord :: Base

I extended the ActiveRecord::Base class as follows:

  • I created a directory under lib , now call him foo
  • wrote a module that provides an additional has_many_bidirectional method to have bidirectional has_many relations in ActiveRecord::Base classes
  • in lib/foo/active_record.rb :

     module Foo module ActiveRecord autoload :Associations, 'active_record/associations' autoload :Base, 'active_record/base' end end 
  • in 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 valid 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 config/environment.rb following code at the end of the configuration file:

     ActiveRecord::Base.class_eval do include Foo::ActiveRecord::Base end 
  • that way Rails was correctly included in my module and I could use it without problems

  • until I wanted to observe the extended class, because in config/environment.rb part of config.active_record.observers is before the expanding part, and the observed class does not know anything about the new method with this item.

The following error appeared:

 /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, is this the right way to extend the ActiveRecord::Base class? (I do not want to use callback methods in the User class.)

Do I really need to create a pearl instead of a module in the lib directory in order to have this functionality?

Thanks!

+4
source share
1 answer

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

 ./script/generate plugin has_many_bidirectional 

And so Rails will include it in front of the observer part. A good tutorial can be found here .

All my previous code can be easily adopted in this way.

+2
source

Source: https://habr.com/ru/post/1332917/


All Articles