I have extended the ActiveRecord::Base
class in the following way:
lib
, let's call it now foo
has_many_bidirectional
to have bidirectional has_many relationships in ActiveRecord::Base
classesin 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
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.