tags:

views:

91

answers:

3

I have a Date class which I would like to use to overwrite Ruby's Date class. However, whenever I do a require 'Date' in my other files, it includes Ruby's Date class and not my own.

I thought that putting it in a module would work well, so I did so within the Date.rb file:

module myModule
  class Date
  #...
  end
end

However I still can't figure out how to make my other classes include THIS Date class and not the built-in class. How can I achieve this?

All help is appreciated and thanks in advance!

A: 

First, you need to require the correct file. Often the right thing happens when you do require 'date' and it's resolved to a file based on your $LOAD_PATH. You can be more specific by putting your date.rb in a directory so you can require 'my_module/date' or just use a relative path like ./date

You can then specify the module hierarchy when referring to this class:

::MyModule::Date

Or you can include it wherever you prefer to call this Date over the standard one without specifying:

class Event
  include MyModule
  def initialize
    @date = Date.today # refers to MyModule::Date
  end
end
Andrew Vit
`>require ::MyModule::Date` gets me `NameError: uninitialized constant MyModule::Date`
adam_0
require is a filename string, not module name.
Andrew Vit
Right. So how do I require the correct file? And is there a way to make this so that I don't have to specify ::MyModule::Date, similar to Java's `import`?
adam_0
Updated my answer for your questions.
Andrew Vit
This isn't working for me -- perhaps because my module is in a file that's not of the same name as the module? (`module MyModule` contains `class Date` and is in `Date.rb`)
adam_0
Also, would it help if I put `Event` inside `MyModule` as well?
adam_0
If you're on a case-sensitive filesystem, I guess there might be a difference between `require 'date'` and `require 'Date'`. This just refers to a filename, so it either has to be in your `$LOAD_PATH` or you have to specify the path to it. As for putting your Event class inside your module, sure, why not: then your Date class will be available there and you won't need to include it.
Andrew Vit
Unfortunately, this didn't solve my problem -- I thought my filesystem was case-sensitive, but apparently not. Also, I want a fix that works on any filesystem, so this is just a hack that works on one filesystem or another.
adam_0
+1  A: 
require 'path/to/Date.rb'

class MyClass
    include MyModule::Date
end
banister
I should specify that `Date.rb` is the same directory as the class that I want to include it in.
adam_0
then do `require "./Date.rb"`
bjeanes
@bjeanes: I tried this: `irb(main):003:0> require "./Date.rb"=> false` How can I figure out why the include didn't work?
adam_0
`require` returning false does not necessarily mean that it did not work. In any case, try doing `require File.join(File.dirname(__FILE__), "Date.rb")` to be sure. Really, the simplest solution is to just call the file something else, like `my_custom_date.rb`. The class/module name does NOT have to match the file name.
bjeanes
A: 

Adam,

Your best bet is to simply follow some conventions:

  1. Always name your filenames lower case (date.rb not Date.rb)
  2. Put your files in a specific directory inside your library (lib is a good candidate)
  3. Don't name your files the same thing as built in Ruby classes (call it my_date.rb or something) or if your class/module is name-spaced inside a module, put it in a folder of the module name (lib/my_module/date.rb).

This removes any ambiguity in which file you are trying to load. If you absolutely must keep it named date.rb, then load it with the full path by doing something like: File.join(File.dirname(__FILE__), "date.rb").

For debugging purposes you can look at the following special variables to see what's being loaded instead of your file:

  • $: will show the load path (i.e. every directory it looks in to find files to require. You will note that the current directory (.) is last. This is why your file isn't loaded -- it looks in the system path first. You can always move your current directory to the front of the load path as a solution by doing $:.unshift(File.dirname(__FILE__)), but I'd try one of the above approaches before resorting to this
  • $" shows every file that has been required into your current environment so far.
bjeanes