开发者

Extending ActiveRecord - what is the difference between send, extend?

开发者 https://www.devze.com 2023-03-22 09:41 出处:网络
I\'m working on an ApplicationModel for a Rails app that has over 200 modules. The app is so large that when we rails s it literally take开发者_如何学运维s 40 seconds to load our app. So in developmen

I'm working on an ApplicationModel for a Rails app that has over 200 modules. The app is so large that when we rails s it literally take开发者_如何学运维s 40 seconds to load our app. So in development we have a ton modules we often change and to see the changes we have to reload the app.

So I created an ApplicationModel and moved all the initializers into that model so changes are reloaded in development and we do not have to restart the server again saving lots of time everyday.

I made ApplicationModel inherit from ActiveRecord::Base and made it an abstract class. All other models inherit from this model. So now we can put our initializers that extend ActiveRecord into this model.

Since I'm working on a project that other people started I don't know the difference between these two ways of extending ActiveRecord and would like to know the differences between them.

ActiveRecord::Base.send(:include, someModule)
ActiveRecord::Base.extend(ClassMethods)


First, I think you're overcomplicating this a bit. If you want to reload your application's models in the console, the best choice is to just run reload!, not a complicated custom solution.

Second, the difference between these two choices:

ActiveRecord::Base.send   :include, M
ActiveRecord::Base.extend M

is that include adds the module to the class, just as if you'd copy-pasted the instance methods in the module right into the class's definition.

By contrast, extend will add the module to the metaclass, just as if you'd copy-pasted the instance methods in the module into a class << self block in the class.

Here's an illustrative example:

module InstanceMethods
  def foo; "foo"; end
end

class ActiveRecord::Base
  include InstanceMethods
end

ActiveRecord::Base.instance_methods.include? :foo
=> true

But:

module ClassMethods
  def bar; "bar"; end
end

class ActiveRecord::Base
  extend ClassMethods
end

ActiveRecord::Base.instance_methods.include? :bar
=> false   # hmm, it's not an instance method...

ActiveRecord::Base.singleton_class.instance_methods.include? :bar
=> true    # ... it's a class method, aka an
           # instance method on the metaclass


What you're seeing is probably:

ActiveRecord::Base.send( :include, InstanceMethods )
ActiveRecord::Base.extend( ClassMethods )

When you include a module, it's methods become instance methods in your class, when you extend a module, the module methods get inserted into the instance variable where you "extended" them. In this case, you're extending the ActiveRecord::Base "class" instance (the Class object that represents ActiveRecord::Base objects), which means these methods will become "class" methods.

You can get a full explanation about this here: "Including and extending modules in Ruby".

0

精彩评论

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