What does $:<< “.” do to Ruby's require

2019-04-06 06:33发布

I don't understand the meaning of $:<< "." in Ruby.

I upgraded Ruby to 1.9.1, but a program was not working. My classmate told me that I am supposed to add $:<< "."

What does $:<< "." do?

标签: ruby require
3条回答
干净又极端
2楼-- · 2019-04-06 06:39
  1. $: is the variable that holds an array of paths that make up your Ruby's load path
  2. << appends an item to the end of the array
  3. . refers to the current directory

    1   2  3
    |   |  |
    V   V  V
    $: << "."
    

So you are adding the current directory to Ruby's load path

References:

  1. Can be found in the Execution Environment Variables section of of this page from The Pragmatic Programmers Guide

    An array of strings, where each string specifies a directory to be searched for Ruby scripts and binary extensions used by the load and require methods. The initial value is the value of the arguments passed via the -I command-line option, followed by an installation-defined standard library location, followed by the current directory (“.”)[Obviously this link is for an older version of Ruby as this is still in there]. This variable may be set from within a program to alter the default search path; typically, programs use $: << dir to append dir to the path.

  2. Can be found in the docs for array at ruby-doc.org.

    Append—Pushes the given object on to the end of this array. This expression returns the array itself, so several appends may be chained together.

查看更多
Viruses.
3楼-- · 2019-04-06 06:57

Since version 1.9, Ruby doesn't look for required files in the current working directory AKA .. The $LOAD_PATH or $: global variable is an array of paths where Ruby looks for files you require.

By adding $:<< "." to your files, you are actually telling Ruby to include your current directory in the search paths. That overrides new Ruby behavior.

查看更多
【Aperson】
4楼-- · 2019-04-06 06:57

In your example you add working directory (".") to ruby load path ($:).

Working directory (".") was removed from load path (global variable $: or $-I or $LOAD_PATH) in Ruby 1.9 because it was considered a security risk:

  • Your working directory may be any folder, and your script will require files from this folder if these files have appropriate names. For example you have 2 files in Project1 folder main.rb and init.rb:

==Project1/main1.rb:
$: << "." require 'init'
==Project1/init.rb:
puts 'init 1'

And you have alike project:

==Project2/main2.rb:
$: << "." require 'init'
==Project2/init.rb:
puts 'init 2'

If you run Project1 from Project2 folder, then main1.rb will require Project2/init.rb, not Project1/init.rb:

~/Projects/Project2$ ruby ../Project1/main1.rb
init 2 # may be unexpected an dangerous
~/Projects/Project2$ ruby main2.rb
init 2

  • You can change your working directory in your code, e.g. using Dir.chdir:

    ruby-1.9.2-p290 :002 > puts File.expand_path('.')
    => /home/alex/Projects
    ruby-1.9.2-p290 :003 > Dir.chdir('..') 
    ruby-1.9.2-p290 :004 > puts File.expand_path('.')
    => /home/alex
    

I recommend you to use the following techniques instead of $: << '.':

  • require_relative (Ruby 1.9 only)

  • Add folder of the file to the working directory (common approach because it is compatible with Ruby 1.8): $: << File.expand_path('..', __FILE__) etc.. __FILE__ is a reference to the current file name. File.expand_path converts a pathname to an absolute pathname.

查看更多
登录 后发表回答