Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mansakondo/ded3d7db56ef99efb5776a4e406cc572 to your computer and use it in GitHub Desktop.
Save mansakondo/ded3d7db56ef99efb5776a4e406cc572 to your computer and use it in GitHub Desktop.
load_path.unshift File.expand_path(path, __FILE__)

$:.unshift File.expand_path(path, __FILE__)

I saw this line of code somewhere and i felt kind of confuse about it and intimidate. That's why, i'll try to explain what i've found so far (if there is any errors, feel free to point them out).

What is this $: ?

This alien thing $: is a shortcut referencing the $LOAD_PATH. What is the $LOAD_PATH ? The $LOAD_PATH is a global variable as you can tell from $ at the beginning. A global variable is a variable which is accessible from everywhere in a given context. For example take a look at the function below :

$global = 1

def sum(a, b)
$global += a + b    #Same as $global = $global + a + b
end

p increment(2,3) # 6

Here, the context is the file you're in. The variable $global is callable from anywhere in the code because of the $. Reciprocally, a global variable like $LOAD_PATH is accessible from anywhere in your command line environnement and that can be helpful to shorten some actions that can be laborious is you're working on a big project.This why we're using the $LOAD_PATH here.

The $LOAD_PATH variable contains an array of path which mostly point to lib/ sub-directories :

>> $LOAD_PATH
=> ["/home/Mansa/.rbenv/rbenv.d/exec/gem-rehash",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/did_you_mean-1.3.0/lib",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/coderay-1.1.2/lib",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/method_source-0.9.2/lib",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/yard-0.9.19/lib",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/pry-doc-1.0.0/lib",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/pry-rails-0.3.9/lib",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/site_ruby/2.6.0",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/site_ruby/2.6.0/x86_64-linux",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/site_ruby",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/vendor_ruby/2.6.0",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/vendor_ruby/2.6.0/x86_64-linux",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/vendor_ruby",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/2.6.0",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/2.6.0/x86_64-linux"]

>> $:
=> ["/home/Mansa/.rbenv/rbenv.d/exec/gem-rehash",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/did_you_mean-1.3.0/lib",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/coderay-1.1.2/lib",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/method_source-0.9.2/lib",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/yard-0.9.19/lib",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/pry-doc-1.0.0/lib",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/pry-rails-0.3.9/lib",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/site_ruby/2.6.0",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/site_ruby/2.6.0/x86_64-linux",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/site_ruby",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/vendor_ruby/2.6.0",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/vendor_ruby/2.6.0/x86_64-linux",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/vendor_ruby",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/2.6.0",
"/home/Mansa/.rbenv/versions/2.6.3/lib/ruby/2.6.0/x86_64-linux"]

>> $: == $LOAD_PATH
=> true

We can see that the $: notation is obviously a shortened version of $LOAD_PATH

What is $:.unshift ?

Now we see that things are starting to fall into place but still, there is quite a bit cover to get the full picture.

We saw earlier that the $LOAD_PATH was an array containing several path. It means that $:.unshift is calling to a Array#unshift(which is the Ruby notation refering to an instance method from a Ruby classes) method on the $: array :

# $:.unshift ... >> $LOAD_PATH.unshift >> Array#unshift

The Array#unshift method is adding a elements pass in argument to the beginning of an array :

>> [1,2,3].unshift(0)
=> [0,1,2,3]

Read the Official Ruby Doc for more info.

What is File.expand_path(path, __FILE__) ?

The File#expand_path method is used to convert a relative path to an absolute path. Relative path are relative, which means that there defined in the context they we're in.

$ pwd         #show the current directory
~/code/Rails 

$ ls          #show all the public access file in a directory
my_app  my_app2

$ cd myapp/   #change the directory

With the cd command we've used the relative path to the myapp/ directory instead of absolute path which is ~/code/Rails/my_app

What the File#expand_path method allow us to reconstruct the path from the root directory. The first argument specify the relative path to a file or directory. The second argument set the starting point from where we want to start reconstructing the path.

>> __FILE__
=> my_app/Gemfile

>> File.expand_path("../my_app2/Gemfile", __FILE__)
=> ~/code/Rails/my_app2/Gemfile

Here the second argument is set to __FILE__ which is a variable returning the current file or directory we're in. You can replace __FILE__ by any file or directory you want.

Not so complicated huh ? If you want a sharp explaination about how the File#expand_path method work, i suggest you take a look at the first awswer of this Stackoverflow post

What is $:.unshift File.expand_path(path, __FILE__) ?

Now with all pieces together we can start reconstructing the puzzle.

As we know now, $:.unshift represents an array method call. We can deduce from that File.expand_path(path, __FILE__) is the argument we're passin in(Note: In Ruby, parenthesis are optional if there is only one argument). It means that through the $:.unshift method call we've plan to add File.expand_path(path, __FILE__) to the $: array. By doing so, we're adding the path generate by File.expand_path(path, __FILE__) in the $LOAD_PATH array which allows our command line environnment to have access to the specified path from anywhere. And why it is that helpful ? Because it allow us to call require "directory" instead of require "../../../path/to/directory to require a specified directory in our Ruby project.

Viewing like this it may not be seem that helpful, but in real life substantial projects, this can time/energy saver. Because things like this require "../../../../../directory aren't particulary fun to do in my opinion :). Moreover, when you have a tons of files/directories to require,, it can be tremendously laborious.

Conclusion

That's all :)

Let's review what we've seen so far :

a - We saw that the $: notation was a shorcut for $LOAD_PATH and that $LOAD_PATH is global variable containing an array of path. b - We saw that $:.unshift was an Array method which serve to add elements to the beginning of an array. c - We saw that File.expand_path(path, __FILE__) serve to reconstruct an absolute path from a relative path. d - We saw that $:.unshift File.expand_path(path, __FILE__) serve to add an absolute path generate by with File.expand_path(path, __FILE__) to the beginning of the $: array, which allow us to require file and directories without specifing the absolute path for it.

I hope that you get a clearer understanding now or a least that you're not as confused as the first time you saw this code :)

Peace ☥

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment