Is require File.expand_path(..., __FILE__) the best practice?
In Ruby 1.9.2 + require_relative
is probably the more correct way to do it.
require
was changed to not include your '.'
directory for security reasons. require_relative
was added to provide a local-file solution for modules relative to your calling script's path.
You can search here on StackOverflow, particularly in "What is require_relative in Ruby?", and the internets and find usage tricks and the why-for messages explaining how it came about.
File.expand_path(../../Gemfile, __FILE__) How does this work? Where is the file?
File.expand_path('../../Gemfile', __FILE__)
is a somewhat ugly Ruby idiom for getting the absolute path to a file when you know the path relative to the current file. Another way of writing it is this:
File.expand_path('../Gemfile', File.dirname(__FILE__))
both are ugly, but the first variant is shorter. The first variant is, however, also very non-intuitive until you get the hang of it. Why the extra ..
? (but the second variant may give a clue as to why it is needed).
This is how it works: File.expand_path
returns the absolute path of the first argument, relative to the second argument (which defaults to the current working directory). __FILE__
is the path to the file the code is in. Since the second argument in this case is a path to a file, and File.expand_path
assumes a directory, we have to stick an extra ..
in the path to get the path right. This is how it works:
File.expand_path
is basically implemented like this (in the following code path
will have the value of ../../Gemfile
and relative_to
will have the value of /path/to/file.rb
):
def File.expand_path(path, relative_to=Dir.getwd)
# first the two arguments are concatenated, with the second argument first
absolute_path = File.join(relative_to, path)
while absolute_path.include?('..')
# remove the first occurrence of /<something>/..
absolute_path = absolute_path.sub(%r{/[^/]+/\.\.}, '')
end
absolute_path
end
(there's a little bit more to it, it expands ~
to the home directory and so on -- there are probably also some other issues with the code above)
Stepping through a call to the code above absolute_path
will first get the value /path/to/file.rb/../../Gemfile
, then for each round in the loop the first ..
will be removed, along with the path component before it. First /file.rb/..
is removed, then on the next round /to/..
is removed, and we get /path/Gemfile
.
To make a long story short, File.expand_path('../../Gemfile', __FILE__)
is a trick to get the absolute path of a file when you know the path relative to the current file. The extra ..
in the relative path is to eliminate the name of the file in __FILE__
.
In Ruby 2.0 there is a Kernel
function called __dir__
that is implemented as File.dirname(File.realpath(__FILE__))
.
Requiring files in Ruby
require_relative 'lib/checkers/board'
require_relative 'lib/checkers/checker'
This is how I have always done it. This is located in my main app file, which is always in the root directory. I'm unsure how it will behave from other files, although I believe it will be relative to the calling file.
Also, settings.root
will return the root directory of your app, no need for File.dirname(__FILE__)
anywhere.
This works in Ruby 1.9 without any special techniques via the comments above.
If you are using 1.8, you can do this
require './lib/checkers/board'
require './lib/checkers/checker'
Other techniques for 1.8 are listed in this question.
Best way to require all files from a directory in ruby?
How about:
Dir["/path/to/directory/*.rb"].each {|file| require file }
What does __FILE__ mean in Ruby?
It is a reference to the current file name. In the file foo.rb
, __FILE__
would be interpreted as "foo.rb"
.
Edit: Ruby 1.9.2 and 1.9.3 appear to behave a little differently from what Luke Bayes said in his comment. With these files:
# test.rb
puts __FILE__
require './dir2/test.rb'
# dir2/test.rb
puts __FILE__
Running ruby test.rb
will output
test.rb
/full/path/to/dir2/test.rb
understanding __FILE__
Since you are using a relative path in '../../views'
, you need a reference point to expand the path. The second argument, which happens to be __FILE__
in this case, overrides the default reference point, which is the current working directory.
Ruby Doc File.expand_path
What is the difference between require_relative and require in Ruby?
Just look at the docs:
require_relative
complements the builtin methodrequire
by allowing you to load a file that is relative to the file containing therequire_relative
statement.For example, if you have unit test classes in the "test" directory, and data for them under the test "test/data" directory, then you might use a line like this in a test case:
require_relative "data/customer_data_1"
Related Topics
How to Step Out of a Loop with Ruby Pry
Upgrading from Rails 3 to Rails 3.1
Find Out If an Ip Is Within a Range of Ips
Generate Unique Random String with Letters and Numbers in Lower Case
How to Change Hash Keys from 'Symbol's to 'String'S
Jekyll on Windows: Pygments Not Working
Does Dependency Injection Exist in Rails
Deploying Sinatra App (With Config.Ru) on Heroku Cedar Stack
Why Does This Nokogiri Xpath Have a Null Return
Rubocop Line Length: How to Ignore Lines with Comments
Installing Ruby 1.9.1 on Ubuntu
How to Redefine a Ruby Constant Without Warning
Why Is Safe Navigation Better Than Using Try in Rails
How to Password-Protect My /Sidekiq Route (I.E. Require Authentication for the Sidekiq::Web Tool)