What is '$:.unshift File.dirname(__FILE__)' doing?
It's adding the current file's directory to the load path. $:
represents the load path (which is an array) and unshift
prepends to the beginning of the array.
The reason it's there (and at the top) is so that all those requires needn't worry about the path.
ruby $:.unshift File.dirname(__FILE__)
$:
is just a shortcut for $LOAD_PATH
. __FILE__
is the relative path to the script. This adds the current script directory to the load path.
What exactly does $:.unshift(File.expand_path(../../lib, __FILE__)) do?
$:
holds Load path for scripts and binary modules by load or require. . And Array#unshift
will prepend the new path to $:
. File#expand_path
Converts a pathname to an absolute pathname. __FILE__
is already answered here What does __FILE__ mean in Ruby?
.
unshift + file.join in ruby
The above code adds the path "vendor/addressable-2.1.0/lib/addressable/uri" to the global variable used for looking up external files. The path will be relative to the directory that houses the file this code is placed in. So were {dir} is the directory config.ru is placed, it will add {dir}/vendor/addressable-2.1.0/lib/addressable/uri
to the lookup path for includes.
Ruby: File Path using $:.unshift(File.join('DIR1', 'DIR2'))
$: is Ruby shorthand to the load path array, i.e. an array full of the paths that Ruby uses to look up external files when asked to require one (try running it in IRB).
In Ruby, .unshift is a method that takes the given path (in this case, whatever File.join(APP_ROOT, 'lib')
resolves to), and prepends it to the beginning of the load path array.
This way Ruby will know to check the APP_ROOT/lib path the next time you do a require 'myfile'
line elsewhere in the app.
Confusing behavior of File.dirname
File.dirname
should return an absolute path if given an absolute path, and a relative path if given a relative path:
File.dirname('/home/jon/test.rb') # => '/home/jon'
File.dirname('test.rb') # => '.'
__FILE__
returns the name of the current script, which is therefore a relative path from the current directory. That means you should always use expand_path
if you want to get the absolute path with File.dirname(__FILE__)
.
NB Ruby 2.0.0 introduces the __dir__
constant
require File.dirname(__FILE__) -- how to safely undo filesystem dependency?
I actually use this scheme in production code.
Requiring files relative to the current source location has several advantages :
- the source tree can be moved around as a whole and remains usable since we require sources relatively to each other.
- since we use full paths, we avoid accidental collisions (loading a source with the same name in another library, or reloading the same source twice)
- the code can be used without having to modify ruby's search path
Should you prefer to use a modified ruby search path, you can do it in multiple ways :
- adding -I options on the ruby command line
- modifying the $LOAD_PATH variable within the sources
- playing with the environment variable RUBYLIB
Solution 1 implies controlling how ruby is invoked. You'll need a script to start the program, such as:
@echo off
REM my_script.cmd
set srcdir=%~dp0\..\path\to\source
ruby -I %srcdir% %srcdir%\my_script.rb
Or:
#!/bin/sh
srcdir=$(cd $(dirname $0)/../path/to/source && pwd)
exec ruby -I $srcdir $srcdir/my_script.rb
Solution 2 is workable but does not avoid collisions. You'll typically do something like :
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
Solution 3 is unadvisable, the less dependencies you'll have toward environment variables, the better you will be.
Related Topics
How to Call an Older Version of a Gem from the Commandline
How to Display a PDF in Ror (Ruby)
How to List All Objects Created from a Class in Ruby
Install Any Version of Ruby with Rvm on Mavericks
How to Cache a Calculated Column in Rails
Error While Trying to Load the Gem 'Devise. Activesupport: Duration Can't Be Coerced into Integer
Heroku Rails 4 Could Not Connect to Server: Connection Refused
How to Parse JSON Request Body in Sinatra Just Once and Expose It to All Routes
Failed to Build Gem Native Extension' on Windows 7 (The System Cannot Find the Path Specified)
How to Measure the Size of a Ruby Object
Iterating Between Two Datetimes, with a One Hour Step
Uninitialized Constant Rake::Dsl in Ruby Gem
How to Switch to an Older Version of Rails
How to Validate Members of an Array Field
How to Install an Older Version of Jekyll
Why Are My Bigdecimal Objects Initialized with Unexpected Rounding Errors