10

I'm new to rails and making some sort of noob mistake: I frequently need to count the number of lines in a file, so I'm trying to monkey patch class File like this:

class File
  def self.line_count( filename ) 
    %x{wc -l #{filename}}.split.first.to_i  
  end
end

I saved this to /lib/file_util.rb. I thought that this was supposed to be auto-required, so that I could just use it, but that doesn't work:

$ rails console
>> File.line_count('Gemfile')
NoMethodError: undefined method `line_count' for File:Class
...

So I try to require it manually, no joy:

>> require '<myproj>/lib/file_util.rb' # same result with require 'file_util.rb'
=>nil

But it works if I require it within IRB:

$ irb
>> require '<myproj>/lib/file_util.rb'
=> true
>> File.line_count('Gemfile')
=> 22

I also tried to to add the require to config/application.rb:

...
Bundler.require(:default, Rails.env) if defined?(Bundler)

require 'file_util.rb'

module <myproj>
...

and I get:

$ rails console
<myproj>/config/application.rb:9:in `require': no such file to load -- file_util.rb (LoadError)

What am I doing wrong?

Mori
  • 27,279
  • 10
  • 68
  • 73

2 Answers2

11

Ok, I seem to have mostly figured it out. Rails doesn't automatically require everything under /lib. It only auto loads when you try to use a new class name that matches a file name in lib. So if I define line_count in class FileUtil instead of File it automatically finds and loads 'file_util.rb'. But patching File and naming the patch file 'file.rb' doesn't work, since the File class is already defined, so Rails doesn't go looking for a definition.

My other problem was that I was trying to do the require too soon in the startup sequence, before Rails had a chance to enhance require to look in its directories. When I added "require 'file_util'" to config/environments/development.rb it works fine.

But this doesn't explain why I can't manually require the file from within rails console.

Mori
  • 27,279
  • 10
  • 68
  • 73
  • 1
    Yeah the naming of the file to autoload worked for me. Didn't know it was wired that way now. – squarism Feb 27 '11 at 04:50
  • 1
    I ran into that problem too. This is what I do to automatically force all files in lib to be required: http://stackoverflow.com/questions/4235782/rails-3-library-not-loading-until-require/6797707#6797707 – Tyler Rick Jul 23 '11 at 01:42
7

Monkeypatching classes can be done more easily by adding a file in config/initializers. All of those files are automatically loaded by Rails at startup.

You can call your initializer file anything you want. Try config/initializers/file.rb.

chadoh
  • 4,343
  • 6
  • 39
  • 64