adam_0
adam_0

Reputation: 7190

Using modules as namespaces to override built-in classes in Ruby

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!

Upvotes: 1

Views: 1264

Answers (3)

Bo Jeanes
Bo Jeanes

Reputation: 6383

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.

Upvotes: 1

horseyguy
horseyguy

Reputation: 29895

require 'path/to/Date.rb'

class MyClass
    include MyModule::Date
end

Upvotes: 1

Andrew Vit
Andrew Vit

Reputation: 19239

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

Upvotes: 0

Related Questions