What Is '$:.Unshift File.Dirname(_File_)' Doing

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 :

  1. adding -I options on the ruby command line
  2. modifying the $LOAD_PATH variable within the sources
  3. 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



Leave a reply



Submit