2

I want to extend the functionality of Array, add a method that checks if a key exists in array and that the array is not empty, where to write the class and how to make sure it's loaded?

Chen Kinnrot
  • 20,609
  • 17
  • 79
  • 141

2 Answers2

3

You can either put it into lib/ and make sure that it is autoloaded as outlined in the answer by shioyama; or you could just put it into an initializer. I like the initializer approach a bit better, since it is easier (you get autoloading for free).

I usually create a core_ext subdirectory of the initializers directory and put my core class extensions in there. I always try to put the name of the class that is being extended and a description of what I add into the filename, so in you case I would create a file RAILS_ROOT/config/initializers/core_ext/array_my_function containing:

module MyFunctionForArray
  def my_function(arg1, arg2)
    # ...
  end
end

Array.send :include, MyFunctionForArray

I always try to not reopen the class and extend it directly but to put my extensions into a module and then including this module into the class to extend.

severin
  • 10,148
  • 1
  • 39
  • 40
  • I also do it in initializers but I used to reopen the class. Is there any advantage for this approach of including modules instead of reopening the class? – rubyprince Oct 05 '12 at 10:34
  • 1
    In my opinion you do not pollute the original class as much when you include a module containing all your extensions (you add ONE new element into the original class' ancestor chain vs. adding X new method(s) to the class directly). And it helps you when you need to figure out where a method is defined: `[1,2,3].method(:my_function)` for example tells you that the method *my_function* comes from the module and not the class itself, therefore making it easier for you to find it... – severin Oct 05 '12 at 14:28
  • +1 you're right, for the specific case the OP asked about (extending the functionality of Array) this is the more straightforward approach. I was thinking in more general terms. – Chris Salzberg Oct 05 '12 at 21:11
2

Standard way to do it is to put the code in lib/ and make sure it's autoloaded by rails by adding a line to config/application.rb:

config.autoload_paths += Dir["#{config.root}/lib/**/"]

Then in your code, just make sure you require it wherever you use it. If you want to apply it everywhere, create an initializer in config/initializers with a line:

require 'my_array'

Where my_array.rb is the name of the file in lib where you have the file. That will make it available in your models, controllers, views, etc.

See also: Best way to load module/class from lib folder in Rails 3?

Also, beware of one pitfall of autoloading a directory structure in ruby (not just rails), explained in this answer: Best way to load module/class from lib folder in Rails 3?

Community
  • 1
  • 1
Chris Salzberg
  • 27,099
  • 4
  • 75
  • 82