Are ruby command line switches -rubygems & -r incompatible? - ruby

I recently converted a ruby library to a gem, which seemed to break the command line usability
Worked fine as a library
$ ruby -r foobar -e 'p FooBar.question' # => "answer"
And as a gem, irb knows how to require a gem from command-line switches
$ irb -rubygems -r foobar
irb(main):001:0> FooBar.question # => "answer"
But the same fails for ruby itself:
$ ruby -rubygems -r foobar -e 'p FooBar.question'
ruby: no such file to load -- foobar (LoadError)
must I now do this, which seems ugly:
ruby -rubygems -e 'require "foobar"; p FooBar.question' # => "answer"
Or is there a way to make the 2 switches work?
Note: I know the gem could add a bin/program for every useful method but I don't like to pollute the command line namespace unnecessarily

-rubygems is actually the same as -r ubygems.
It doesn't mess with your search path, as far as I understand, but I think it doesn't add anything to your -r search path either. I was able to do something like this:
ruby -rubygems -r /usr/lib/ruby/gems/myhelpfulclass-0.0.1/lib/MyHelpfulClass -e "puts MyHelpfulClass"
MyHelpfulClass.rb exists in the lib directory specified above.
That kind of sucks, but it at least demonstrates that you can have multiple -r equire directives.
As a slightly less ugly workaround, you can add additional items to the ruby library search path (colon delimited in *nix, semicolon delimited in windows).
export RUBYLIB=/usr/lib/ruby/gems/1.8/gems/myhelpfulclass-0.0.1/lib
ruby -rubygems -r MyHelpfulClass -e "puts MyHelpfulClass"
If you don't want to mess with the environment variable, you can add something to the load path yourself:
ruby -I /usr/lib/ruby/gems/1.8/gems/myhelpfulclass-0.0.1/lib \
-rubygems -r MyHelpfulClass -e "puts MyHelpfulClass"

Note: this problem exists for ruby 1.8, but is resolved in ruby 1.9.
On 1.8, if you specify both libs via -r, ruby will try to load each library without paying attention to changes in the $LOAD_PATH. But rubygems does change $LOAD_PATH so the gems can be found.
The reason it works with irb is that irb does pay attention to $LOAD_PATH changes.
Unfortunately, the best workaround I've found is to use the more verbose form:
ruby -rubygems -e 'require "foobar"; p FooBar.question'
The pain doesn't increase linearly with the number of libs though, if you use an iterator:
ruby -rubygems -e '%w(rake rspec).each{|r| require r }'

Related

In a Ruby gem, is it possible to have executables written in other languages?

I have a gem which has an executable in bin/. A wildcard is used in the gemspec:
s.executables = Dir["bin/*"].map &File.method(:basename)
If I have a ruby file at bin/my_file which had chmod a+x run, then it's found in the PATH in bash:
#!/usr/bin/env ruby
puts "working ruby script"
However I have another executable written in coffeescript at bin/my_file.coffee:
#!/usr/bin/env coffee
console.dir "printing from coffee file"
When I run my_file.coffee in shell, it tries to read this script with ruby instead of coffeescript.
How can I run this executable with coffeescript as intended?
As it stands, I'm using a workaround which is to wrap my coffee code as a string in my ruby app and then passing it to coffee -e and capturing the output.
Also, looking at this RubyGems issue shows the official explanation:
RubyGems is not meant to support arbitrary executables.
OK. So is there an alternative besides wrapping code in heredoc?
Is there a good reason this restriction is in place?
I guess it's simply in the specification of RubyGems:
https://github.com/zzak/rubygems/commit/709c5aae7ffd9958cc2ea89dc2caf6b7e02c56b7
+ # Executables included may only be ruby scripts, not scripts for other
+ # languages or compiled binaries.
+ #

"require" command not found when require 'nokogiri'

Homebrew, ruby 2.0.0p648, nokogiri 1.6.7.2 are installed. When require 'nokogiri' there appears an error:
-bash: require: command not found
What's wrong?
Try running the script from the console/terminal shell like this:
ruby script_name.rb
You can also try adding this shebang line to the top of your .rb file:
#!/usr/bin/env ruby
This will auto-identify the script as Ruby when you try to run it directly in some shells. Also see:
Why is it better to use “#!/usr/bin/env NAME” instead of “#!/path/to/NAME” as my shebang?
what is the use of “#!/usr/local/bin/ruby -w” at the start of a ruby program
You're running your command in bash -- this is a Ruby command.
You can't run a Ruby command directly in bash. If you want to use Ruby at command line, open the Ruby shell irb.
$ irb
and then you'll see the prompt
2.3.0 :001 >
The first number indicates the Ruby version you are using. In my case it is Ruby 2.3.0. The second number is the command number.
Then you may type
require 'nokogiri'
and it surely work, if you have this gem installed.

How to run Ruby code from terminal?

I need to run a few lines of Ruby code from terminal, but I can't find the needed parameter for it.
Can you explain how to do this?
If Ruby is installed, then
ruby yourfile.rb
where yourfile.rb is the file containing the ruby code.
Or
irb
to start the interactive Ruby environment, where you can type lines of code and see the results immediately.
You can run ruby commands in one line with the -e flag:
ruby -e "puts 'hi'"
Check the man page for more information.

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", "."]

Include files in a command line with Ruby

When running ruby scripts as such
ruby some-script.rb
How would I include a file (e.g. configuration file) in it dynamically?
As you have found, the -r option is your friend. It also works with IRB:
irb -ropen-uri
Will do the same as require 'open-uri'
FWIW, the most common thing I need to include via the command line is rubygems. And since newer versions of ruby come with gems built in I don't want to edit the file, but include it for testing. Luckily the folks who created gems added a little alias sugar.
You can do the following:
ruby -rubygems myscript.rb
Instead of the ugly:
ruby -rrubygems myscript.rb
OK, so it is one character, but thought it was extra polish to make me happier.
Actually, I found it. It's the -r command line entry.
-r <library_name>
This causes Ruby to load the library using require.
It is useful when used in conjunction with -n or -p.
You can use:
require 'some_ruby_file'
in some-script.rb. It will load some_ruby_file.rb.
Before you call require "somefile.rb" you must navigate to the folder that the file is located or you must provide the full path. In example: require "~/Documents/Somefolder/somefile.rb"

Resources