Why does irb -r make __FILE__ an absolute path? - ruby

foo.rb is a one-liner that puts __FILE__
irb -r ./foo.rb
gives me the absolute path to foo.rb. This is not the behavior if I run ruby foo.rb. Why is it happening in irb?
irb 0.9.6(09/06/30),
ruby 1.9.3p327

The reason this happens in IRB is the same reason this would happen if you had written a program named bar.rb with the following contents.
require './foo'
You will find that using IRB with the require as you do is no different than calling bar.rb which has the require.
From the documentation:
__FILE__ -- The name of the file currently being executed, including
path relative to the directory where the application was started up
(or the current directory, if it has been changed).
So this is including the path relative to the directory where the application was started up. Who knows where irb or bar are? When it is not clear, then the path is given as well.

Related

Terminal issue - ruby: no such file or directory

Total newb here. I'm trying to get a simple ruby program to run in the terminal on my MacBook Pro. I used Atom text editor to write the following:
class Sample
def hello
puts "Hello, World!"
end
end
s = Sample.new
s.hello
I saved the file as my_program.rb to a folder on my desktop. I go to the terminal to run the program. I type
ruby my_program.rb
and it returns
ruby: No such file or directory -- my_program.rb (LoadError)
I can use the irb and run a single line of ruby using
ruby -e 'puts "hello world"'
But can't get it to find the .rb file.
I appreciate any help y'all can offer! Thanks!
ruby ~/Desktop/my_program.rb
Ruby might be clever, but is has no mind-reading builtin. You need to tell it, where your file is. This is, of course, not Ruby-specific, but applies to all commands - they can't guess, where in your file system you have stored a file.
An alternative would be to place ~/Desktop in your PATH and use
ruby -S my_program.rb
Ruby will then execute the first program with this name which it finds in $PATH. Whether it is wise to place the Desktop directory into the PATH is a different issue....

how to distribute a ruby script via homebrew

How can I deploy a simple ruby script via homebrew?
Here's what I tried
Wrote formula in a GitHub repo named homebrew-foo
# file https://github.com/foo/homebrew-foo/blob/master/foo.rb
class Foo < Formula
desc "A command line tool"
url "https://github.com/foo/foo/archive/master.zip"
version "5.0.1"
def install
bin.install "foo"
lib.install Dir["lib/*"]
end
end
The other repository contains the ruby script. These are the files
./foo
./lib/libfile1.rb
here's what the script does
#!/usr/bin/env ruby
require './lib/libfile1.rb'
puts "came here"
The problem is that the require fails.
$ brew install foo/foo/foo
$ foo
results in this error
/Users/user1/.rbenv/versions/2.4.1/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in
require': cannot load such file -- ./lib/libfile1.rb (LoadError)
from
/Users/user1/.rbenv/versions/2.4.1/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in
require' from /usr/local/bin/foo
$ which foo
/usr/local/bin/foo
I suspect it's because the .rb file is not there at /usr/local/bin/foo/lib/libfile1.rb
Any ideas whats the proper way to do this?
There are two issues with your script:
The first one is you try to require some file relatively to the current directory; i.e. the one from which the script is run, not the one it’s located in. That issue can be fixed by using Ruby’s require_relative:
#!/usr/bin/env ruby
require_relative './lib/libfile1.rb'
puts "came here"
The second issue is the script assumes the lib/ directory is located in its directory; which it’s not because your formula installs the script under <prefix>/bin/ and the library files under <prefix>/lib/. Homebrew has a helper for that use-case called Pathname#write_exec_script. It lets you install everything you need under one single directory, then create an executable under bin/ that calls your script.
Your formula now looks like this:
class Foo < Formula
desc "A command line tool"
url "https://github.com/foo/foo/archive/master.zip"
version "5.0.1"
def install
libexec.install Dir["*"]
bin.write_exec_script (libexec/"foo")
end
end
It installs everything under libexec/ (lib/ is usually reserved for lib files), then add an executable under bin/ that calls your libexec/foo script.
I found the answer to my own question, actually it's a technique used by someone on the net, basically do something like this
#!/usr/bin/env ruby
DBMGR_HOME = File.expand_path('../..', __FILE__)
$LOAD_PATH.unshift(File.join(DBMGR_HOME, 'lib'))
require 'dbmgr'
And the recipe can be like this:
https://github.com/callahanrts/homebrew-dbmgr/blob/master/dbmgr.rb

Ruby: How to load a file into interactive ruby console (IRB)?

I am using IRB (interactive ruby console) to learn how to program with Ruby. How do I load a file into the console if I write my programs in a text editor first?
If you only need to load one file into IRB you can invoke it with irb -r ./your_file.rb if it is in the same directory.
This automatically requires the file and allows you to work with it immediately.
Using ruby 1.9.3 on Ubuntu 14.04, I am able to load files from the current directory into irb with the following command line:
irb -I . -r foo.rb
where foo.rb is the file I want to load from my current directory. The -I option is necessary to add the current directory (.) to ruby's load path, as explained in the ruby man page. This makes it possible to require files from the current directory, which is what the -r option to irb accomplishes.
The key piece that wasn't obvious for me when I had this problem is the -I option. Once you do that, you can call require 'foo.rb' from within irb for any files in the current directory. And of course, you can specify any directory you want, not just . with the -I option. To include multiple directories on the load path, separate them with a colon (:), e.g.:
irb -I foo/:bar/:baz/
This command will add the directories foo, bar, and baz to ruby's load path.
The final alternative is to use the relative or absolute path to the file when using require or -r to load a file:
irb -r ./foo.rb
or from within irb:
> require './foo.rb'
Type in irb
And then
require './ruby_file.rb'
This is assuming that ruby_file.rb is in the same directory. Adjust accordingly.
Two ways:
to load source without running the program -- this gives access to all variables and functions:
source("filename.rb")
to run program and then drop into interactive mode -- this only gives access to functions, not variables:
require("filename.rb")
It depends on your ruby. Ruby 1.8 includes your current path, while ruby 1.9 does not. Evaluate $: to determine if your path is included or not. So in ruby 1.9 you must use the entire path, which is always a safe bet.
Then you can use require or load to include the file.
require does not require you to add the suffix of the file when trying to find it and will only include the file once. require should be used instead of load most of the time.
Check out Adding a directory to $LOAD_PATH (Ruby) if you are going to be using ruby 1.8
Type the ruby codes in the text editor
Save it with the extension .rb (for example: demo.rb).
In linux, open your terminal then change directory to the current location of that file (cd command is used to change directory).
After that,type irb and your filename(don't forget to include your extension(.rb)).
In that image,I loaded a simple ruby file which only prints "ruby".
Another way to load the path into irb is just type require then drag and drop the file into the terminal.🙂
-tested using Linux Mint.
For those, who want to load .rb file from the different directory. Just add a string representer of the directory to $: variable.
> $: << "/directory/to/the/required/rb/file"
> require "file"

ruby require relative files

I'm using ruby v1.9.1 in combination with vim and I execute my scripts with:
:!ruby "%"
my scripts are running fine if I add:
$:.unshift File.dirname(__FILE__)
to add the path of this file to the LOAD_PATH of ruby. If I omit this line my require statements to local scripts aren't working anymore.
Is there a way to pass the path of the file to rubys LOAD_PATH? Something like (completly fictional):
:!ruby "%" --add-to-load-path
I did some research before and stubled upon require_relative, but this has the same effect as require and is not working.
You can use the -I option of the ruby executable and write something like the following:
:!ruby -I%:p:h. %
See ruby --help for further information and file modifiers.
Edited: see comments.

How to specify rubygems path in environment-less Ruby script?

I've written a data collection script for Cacti in Ruby and it runs fine from the command line but Cacti runs the script via "env -i" which strips the environment so Ruby can't find the rubygems library ("in `require': no such file to load -- rubygems (LoadError)"). How might I work around this?
#!/bin/sh
#export LOAD_PATH=whatever
#export RUBYLIB=whatever
#export RUBYOPT=whatever
#export RUBYPATH=whatever
#export RUBYSHELL=whatever
#export PATH=$PATH:whatever
exec ruby -x. $0 "$#"
#!/usr/bin/ruby
require 'rubygems'
require 'open4' # or whatever
# rest of ruby script here
This is a shell script that runs ruby with -x, which will cause the interpreter to skip lines until it finds #!.*ruby. This will give you a chance to restore the environment. The . after -x is a noop, you can take out the ., or replace it with a directory. Ruby will cd there before running the script.
I'm actually guessing that this is not really what you want, since this could have been done without any trickery by just making two scripts, one for the shell, one for Ruby. Perhaps the list of environment variables Ruby cares about will help...
I don't think $LOAD_PATH used for gems (at least, not exclusively). You might want to look at a couple environment variables that haven't been mentioned here yet:
ENV['GEM_HOME']
ENV['GEM_PATH']
You can see your current paths for gems with:
require 'rubygems'
puts Gem.path
A partial answer might be here: comp.lang.ruby post
Can you modify any of the following in your Ruby script: $:, $-I or $LOAD_PATH? These all just point to the same array which specifies where Ruby looks for classes and other ephemera...
>> $LOAD_PATH
=> ["/usr/local/lib/ruby/site_ruby/1.8", "/usr/local/lib/ruby/site_ruby/1.8/i686-darwin9.5.0", "/usr/local/lib/ruby/site_ruby", "/usr/local/lib/ruby/1.8", "/usr/local/lib/ruby/1.8/i686-darwin9.5.0", "."]

Resources