How to write a batch script to install ruby gem - ruby

I'm writing a batch script as a setup for a ruby program I'm writing. It needs to be able to
a. Make sure Ruby is installed on the user's computer (and if not point them to the ruby download page)
b. make sure the ruby "yaml" gem is installed, which is a prerequisite for it. I've tried
gem install yaml
in the batch script to no avail. How can I write a batch script that will do these two things?

As far as I know, there is no yaml gem. Although it must be required in code that uses it, it is distributed as part of a Ruby installation. Try this:
ruby -ryaml -e"puts 'YAML found'"
It should work; and if you change the -r token to some nonexistent gem, you'll see an exception raised.

Instead of writing your own script, you could use bundler and create a gemfile. This way people can install all the gems on any operating system.
Example:
require 'rubygems'
require 'bundler/setup'
require 'nokogiri'
require 'rest-client'
#require all your gems like normal
def parse(site)
Nokogiri::HTML(RestClient.get(site))
end
And for the gem file:
source: "https://rubygems.org"
gem 'nokogiri', '~> 1.6.7.2' #<= you can specify which version
gem 'rest-client' #<= you don't have to specify a version though
After you've got everything set up, cd to the directory that has the gemfile and run bundle install this will install all the gems

Related

Require files from gem in Ruby script without bundle exec

I have a script that needs to require specific files out of gems defined in the project Gemfile.
#!/usr/bin/env ruby
require 'some_gem/helpers/some_helper'
... rest of script
When I run the script, I get an error about not being able to load some_helper.rb. If I run with bundle exec command... then everything works.
I understand that bundle exec exposes the Gems to the $LOAD_PATH which lets require work. Is there a way to move that capability into the script so users don't have to type bundle exec?
Do I just need to add require "bundler/setup" to the script before I require the gem files?
http://bundler.io/v1.12/#getting-started
:)
#!/usr/bin/env ruby
require 'rubygems' # because reasons.. most probably it is not needed unless you are using really old ruby where it is not loaded by default
# also at the moment rubygems and bundler are being merged :)
require 'bundler/setup' # for things installed with bundler
require 'some_gem/helpers/some_helper'
You can also check e.g. http://mislav.net/2013/01/understanding-binstubs/

How to include Ruby Gems on Github

So, I've created a GitHub to manage my latest Ruby project, and I want for it to utilize a couple of gems. On my PC, all I have to go is type
gem install "gemName"
and it loads it to my computer, and then all I have to do in my Ruby script is have
require "rubygems"
require "gemName"
How can I do this with GitHub? What I tried to do is create a subfolder from the main repository (called "RubyGems") and then in my main ruby script
require "/RubyGems/colorize"
require "/Rubygems/psych"
With the two gems (colorize and psych) in the "RubyGems" folder.
Is this the proper way to do this? Will this even work? What is the right way to do this? (Sorry, I'm kinda new to GitHub.)
A couple of things, unless you're using a really old version of Ruby (like 1.9) you don't need to require 'rubygems' because is already required by default, next I highly recommend you to get familiar with bundler.
Bundler is used for "bundling" the required gems you use, to so do you have to install the gem (gem install bundler) and then you create a Gemfile, like this:
source 'https://rubygems.org'
ruby '2.2.0'
gem 'colorize', git: 'https://github.com/fazibear/colorize.git'
gem 'psych'
Execute bundle install after, that will create Gemfile.lock file, make sure you push both files to your repository.
With that you would be able to bundle exec ./your-script.rb, assuming your script is something like this:
require 'psych'
require 'colorize'
# Here I do stuff with psych and colorize

ruby adds no path to gems

I use:
rvm 1.25.19 (stable)
ruby 1.9.3p545
I install gem rake command
gem install rake
I understand that $LOAD_PATH should contain the paths:
~/.rvm/rubies/ruby1.9/gems/rake/lib
~/.rvm/rubies/ruby1.9/gems/rake/bin
I execute command:
ruby -e 'puts $LOAD_PATH'
output:
/home/slip/.rvm/rubies/ruby-1.9.3-p545/lib/ruby/site_ruby/1.9.1
/home/slip/.rvm/rubies/ruby-1.9.3-p545/lib/ruby/site_ruby/1.9.1/x86_64-linux
/home/slip/.rvm/rubies/ruby-1.9.3-p545/lib/ruby/site_ruby
/home/slip/.rvm/rubies/ruby-1.9.3-p545/lib/ruby/vendor_ruby/1.9.1
/home/slip/.rvm/rubies/ruby-1.9.3-p545/lib/ruby/vendor_ruby/1.9.1/x86_64-linux
/home/slip/.rvm/rubies/ruby-1.9.3-p545/lib/ruby/vendor_ruby
/home/slip/.rvm/rubies/ruby-1.9.3-p545/lib/ruby/1.9.1
/home/slip/.rvm/rubies/ruby-1.9.3-p545/lib/ruby/1.9.1/x86_64-linux
why path to gem 'rake' don't add?
Installing a gem in Ruby doesn’t automatically add that gem’s files to the load path. When you require a file, first the existing load path is searched and if no matching file is found then Rubygems searches the installed gems for the file. If such a gem is found, then it is activated, which is when the gem’s lib directory is added to the load path.
Here’s an example using the Haml gem:
puts "Before:"
puts $LOAD_PATH
puts
require 'haml'
puts "After:"
puts $LOAD_PATH
This produces:
Before:
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby/1.9.1
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby/1.9.1/x86_64-darwin10.8.0
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby/1.9.1
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby/1.9.1/x86_64-darwin10.8.0
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/x86_64-darwin10.8.0
After:
/Users/matt/.rvm/gems/ruby-1.9.3-p448/gems/tilt-1.4.1/lib
/Users/matt/.rvm/gems/ruby-1.9.3-p448/gems/haml-4.0.5/lib
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby/1.9.1
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby/1.9.1/x86_64-darwin10.8.0
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby/1.9.1
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby/1.9.1/x86_64-darwin10.8.0
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/x86_64-darwin10.8.0
See how the lib directories for Tilt (which is a dependency of Haml) and Haml have been added to the start of the load path.
In the case of some gems, such as Rake, this is complicated by the fact they are part of the standard library and so are already on the load path. If you changed the example above to use require 'rake' then you wouldn’t see any change in the load path. In this situation you can specify you want to use the gem version with the gem method. This activates the gem in question, placing its lib directory at the start of the load path so when you later call require you will load the correct version.
For example, this script
require 'rake'
puts Rake::VERSION
produces 0.9.2.2 with Ruby 1.9.3, as that is the version of Rake included in the standard library. However this script:
gem 'rake'
require 'rake'
puts Rake::VERSION
produces 10.1.1, since that is the current highest version of the Rake gem installed on my system. You can also specify a particular gem version by providing a second argument to gem (this is the same syntax as used in Gemfiles). Note that the gem method doesn’t require any files, you have to do that as a separate step.

How to install, require, and use a gem in ruby

I'm trying to use rake in my ruby script...(Ruby 1.8.6, JRuby 1.6.5)
Downloaded rake using gem install --remote rake, looks ok on install...
Fetching: rake-0.9.2.2.gem (100%)
Successfully installed rake-0.9.2.2
1 gem installed
I've got a simple ruby script which works fine, but when I import rake to using any of the following requires, it starts complaining....
require 'rake'
LoadError: no such file to load -- rake
or
require '/lib/rake'
LoadError: no such file to load -- lib/rake
After some searching, I found that adding require 'rubygems' just before rakefixes the issue....
require 'rubygems'
require 'rake'
Even though it's working, I've got some questions...
The gem spec on rake shows the require_path as lib, so why
doesn't require '/lib/rake' work? Am I misunderstanding the significance of require_path?
Why is it necessary to place require 'rubygems' before require
'rake'
Yes, you are misunderstanding the significance. The require_paths in the specification is an array of subdirectories of that gem's installation directory that should be searched for files belonging to the gem.
To find out where rake really is, try this:
$ gem which rake
You'll see that it is actually installed somewhere completely unrelated to /lib; on my system, it's under /var/lib/gems. Ruby gems, in general, live in their own directory structure; the only file in the standard Ruby include path ($:) is rubygems itself, which you used to have to explicitly require in order to make any actual gems visible. (Since Ruby 1.9, that has not been necessary.)
Gems are more complex than just libraries to load; you can have multiple versions of the same gem installed, and specify which one you want at a time, and do other things that wouldn't work if the gems were just dumped into the standard Ruby include path.
The require_path in the gemspec tells ruby where the files of this gem are located within the gem. It makes you able to type require 'rake', and ruby then knows it needs to look for /lib/rake within the gem installation folder.
In Ruby 1.8, rubygems (the mechanism responsible for making gems available to your app) is not loaded by default, and the default ruby isn't aware of any gem on your system. You need to load rubygems before being able to require any other gem. This is not the case anymore with Ruby 1.9.

Bundler: how to use without rails?

I have a project using cucumber outside of rails. How can I load the gems with the versions specified in my gemfile?
Digging through the Bundler website:
Create Gemfile (run bundle init to create skeleton Gemfile)
bundle install
In your app:
# Only needed for ruby 1.8.x
require 'rubygems'
# The part that activates bundler in your app
require 'bundler/setup'
# require your gems as usual
require 'some_gem'
# ...or require all the gems in one statement
Bundler.require
Could be worth checking out:
Bundler.io - Using Bundler in Your Appplication
Bundler.io - Bundler.setup and Bundler.require
Are bundle exec and require 'bundler/setup' equivalent?
I just learned about a way to make Bundler automatically require dependencies from a Gemfile. Add this code at the beginning of a Ruby program that has a Gemfile:
require 'rubygems'
require 'bundler/setup'
Bundler.require
With Bundler.require there's no need to explicitly require the gems/libraries enumerated in the Gemfile.
This solution is from http://technotales.wordpress.com/2010/08/22/bundler-without-rails/
To be honest I'm not sure if the require rubygems part is needed either.
Here's the simplest and most straightforward approach:
bundler init will create the Gemfile for you
Specify gems in the Gemfile.
Add the following to your main Ruby file
require 'bundler/setup'
Bundler.require
Run bundler install to install the gems.
More information can (now) be found at http://bundler.io.
Casper has a pretty good answer (despite some passive aggressiveness) but I think the missing piece for you is bundle exec. When you run the $ rails ... commands on the command line, Rails uses bundler to load those dependencies/gems. Rake, for example, doesn't by default so in order to run rake test using an older version of cucumber than what is on your system, you have to use bundle exec rake test. It's a good habit to get into always using $ bundle exec ... when you're using Bundler — it's explicit, you're always sure you're using the right gems, and it ensures you don't forget to add a dependency to your Gemfile (i.e. you push to another server or another developer and they are having issues because you didn't note the need for something you use but they don't).

Resources