0

I want to extend core Array class with simple method:

class Array
  def to_hash
    result = Hash.new
    self.each { |a| result[a] = '' }
    result
  end
end

I put array.rb into lib/core_ext and tried to require it in application.rb by

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

But still get undefined method 'to_hash' for ["var1", "var2", "var3"]:Array if tried to use it in model method. Of course I rebooted the server after code changes.

freemanoid
  • 14,592
  • 6
  • 54
  • 77

1 Answers1

2

Once way you can do this is by adding the following to one of the files in config/initializers

require 'core_ext/array`

All your autoload_paths config value does is make the paths available for when the classes/files are requested. In my app I might have some file structure as follows

- lib/
  |
  |- deefour.rb
  |- deefour/
     |
     |- core_ext.rb

In my deefour.rb I have

require 'deefour/core_ext'

and inside config/initializers I have a deefour.rb file containing simply

require 'deefour'

The only way the autoload config value you set will cause Rails to look auto load lib/deefour/core_ext.rb is if you had some call to a class Deefour::CoreExt that existed in that file. This is why my require 'deefour' line in the initializer knows to autoload the lib/deefour.rb file.

The explicit require 'deefour/core_ext' in lib/deefour.rb serves the same purpose, since it too does not follow the standard class-name-to-directory mapping Ruby/Rails will expect.

deefour
  • 34,974
  • 7
  • 97
  • 90
  • Is it correct way to create a special file with require in initializers? – freemanoid Nov 27 '12 at 21:55
  • Yes, it's correct when you're trying to load a file from `lib/` that doesn't follow the typical class-name-to-directory mapping Ruby/Rails will expect – deefour Nov 27 '12 at 21:58
  • Can you show correct variant according standard class-name-to-directory convention? – freemanoid Nov 27 '12 at 22:18
  • You can't really do it with monkey patches. If I called some class method `Deefour::User::Manager.create!`, Ruby/Rails would find it's way to `lib/deefour/user/manager.rb` for the `Manager` class nested inside the `Deefour::User` namespace. You can't really do this with a monkey patch on the ruby core; thus the `require` lines. – deefour Nov 27 '12 at 22:26