No need to first require 'rubygems'? - ruby

I am currently reading through this guide: http://guides.rubygems.org/what-is-a-gem/
Under the third section ("Requiring code"), it says that if I run require 'rake', it should fail, because "because RubyGems isn’t loaded yet.". However, when I run require 'rake', (without running require 'rubygems', it works! Is the guide incorrect or am I using a wrong version of Ruby or has something changed?

You are probably running Ruby 1.9.
Per The RubyGems User Guide:
The default Ruby 1.9 package now
includes RubyGems by default on most
platforms (presently Debian based
systems split this out into a separate
package). This means that on Ruby 1.9
and above, you will not need to
require 'rubygems' in order to load
gem libraries.

If you have RUBYOPT=rubygems set in your environment when you launch Ruby, then Ruby Gems will automatically be required. Or if you launch ruby with the argument -rubygems, which is equivalent. Or if you're using Ruby 1.9 or later, Rubygems should automatically be required.
One (or more) of these things is probably true on your system.

Related

What does it mean when a Ruby script starts with Gem?

I am working on learning Ruby and one thing that I have seen in several instances and cannot understand are scripts that start with the keyword gem.
An example can been seen in the Sensu code.
gem "amqp", "1.3.0"
require "amqp"
require File.join(File.dirname(__FILE__), "base")
I understand the require statement for accessing another gem, but what does the exact gem "amqp", "1.3.0" mean?
This is the gem method that Rubygems adds to Kernel (Rubygems is required by default in current Ruby versions). It activates a specific version of a gem (version 1.3.0 of the amqp gem in this case), meaning that the gems lib dir (or whatever dirs the gem specifies) is added to your LOAD_PATH, as are the lib dirs of any dependent gems it has.
It also checks that there are no version incompatibilities with any already activated gems.
All gems are activated when you use them. This normally happens when you call require. Calling gem activates the gem but doesn’t require any files from it, hence the line require "amqp" below (note the difference between amqp the gem, which the gem method refers to, and amqp the file, which is contained in the amqp gem and is what the require method is refering to).
This method is used to ensure you are using a specific version of a gem, without needing to use Bundler (or something similar). Bundler also has a gem method used in Gemfiles, but this is a different (but similar) method.
It’s also used to specify that you want to use the gem version of a library that is also part of the standard library (say if you want to use a more recent version). For example the Yaml library distributed with Ruby is Psych which is also available as a gem.

ruby gem statement - what does it do?

I think I have a basic understanding of what require/include statements at the top of a ruby script are doing, like
require 'rspec'
These statements are easy to google and find relevant results. But sometimes I have seen a gem statement like
gem 'rspec'
What does this line do?
In ruby code, gem(gem_name, *requirements) defined in Kernel tells Ruby to load a specific version of gem_name. That's useful when you have installed more than one version of the same gem.
For example, if you have installed two versions of rspec, say 2.12.0 and 2.13.0, you can call gem before require to use specific version. Note that gem should come before the require call.
gem 'rspec', '=2.12.0'
require 'rspec'
A gem 'gem_name' without version uses the latest version on your machine, and that's unnecessary. You can call require without gem to get the same behavior.
And besides, in Bundler::Dsl, gem is used to tell bundler to prepare/install specific version of ruby gems. You'll see that in Gemfile
The original behaviour of require, before Rubygems, was to search all the directories listed in the $LOAD_FILES variable for the file, and to load the first one it finds that matches. If no matching file was found, require would raise a LoadError.
Rubygems changes this process. With Rubygems, require will search the existing $LOAD_PATH as before, but if there is no matching file found then Rubygems will search the installed gems on your machine for a match. If a gem is found that contains a matching file, that gem is activated, and then the $LOAD_PATH search is repeated. The main effect of activating a gem is that the gems lib directory is added to your load path. In this way the second search of the load path will find the file being required.
Normally this will mean that the latest version of a gem that you have installed gets activated. Sometimes you will want to use a different version of a gem, and to do that you can use the gem method. The gem method activates a gem, and you can specify the version you want, but doesn’t require any files. When you later require the files you want, you’ll get them from the gem version you specified.
In Ruby, gems are packages with functionality that can be used out of the box (as libraries in other Programming languages).
The gems that you use with your Ruby Project can easily be managed with a tool called "bundler", just google it. The snippet of code you posted is part of the spec file that bundler uses to install and update all the libraries that you specify for your project.
If you are developing a Ruby on Rails, using gems an managing them with bundler is very common and so to say best practice.
Gems are just great because there are so many useful libraries that extend default functionality, eg of rails, and that you can use out of the box!
For a list of gems, visit rubygems.org

how to set a ruby application to run on multiple environments

I have developed a simple ruby application without any MVC, and runs on command prompt using ruby 1.9.2 . It also has a Gemfile. I want this application to run on machines running ruby 1.8.7 and 1.9.3 as well. So how can I set it right for multiple environments.
Please Guide.
Thanks
At first you have to make sure that your code is compatible with the syntax of ruby 1.8 and 1.9 https://stackoverflow.com/a/21621/335523
Then make sure that the gems you used support both versions of ruby. (Read through their github page or documentation)
If you are using gems that do not suport both versions of ruby you have to find alternative gems that provide the same functionality in each environment and specify them in your gem file like this:
gem 'rcov', :platforms => :ruby_18
gem 'simplecov', :platforms => :ruby_19

Difference between gem and require (require open-uri)

I just wanted to understand for my self.
I'm using the nokogiri gem (for parsing HTML). If I got it right to open URLs I need to use a method from the gem 'open-uri'.
But when I include it in my Gemfile (on Windows developer's machine):
gem 'open-uri' - there is an error while bundle install that it can not find gem.
So If I use require 'open-uri' - its working.
So can some explain what is going on?
You're using bundler for your gem dependecies and you're doing it right but OpenUri is part of the Ruby standard library. That's why you only need to require it if you want to use it in your code.
require is used to load another file and execute all its statements. This serves to import all class and method definitions in the file. require also keeps track of which files have been previously required so it doesn't execute it twice.
A RubyGem is a software package, commonly called a “gem”. Gems contain a packaged Ruby application or library. The RubyGems software itself allows you to easily download, install, and manipulate gems on your system.
- What is a Gem?:
The Gemfile is then used by bundler to install the specified gems.
open-uri is not a gem but part of the Ruby Standard Library so it just needs to be required.

How do I add conditional rubygem requirements to a gem specification?

Is it possible to add a gem dependency only if the person is using a certain version of ruby?
Background: I'm working on a fork of a project that uses Test::Unit::Autorunner and the like. They are part of the standard library in ruby 1.8, but aren't part of the standard library in 1.9.1, and is instead in the "test-unit" gem. I want to add a dependency that says that if someone's using ruby 1.9.1 or later, install the "test-unit" gem, but if they're using 1.8 or earlier, they don't need to install anything.
If you look at the gemspec documentation for add_dependency, there isn't an option for a ruby version. Perhaps you could use the post_install_message attribute to tell the user to install the gem if they're using ruby 1.9.
I did this exact thing for a project. The trick is to add the script as an extension, which will then get executed at install time on the user's machine.
Here are code snippets and links to our github:
First, when in the gemspec (we're actually using a Rakefile to generate it, but the result ends up the same) source
# This file *needs* to be named this, there are other files
# for other extension processors
s.extensions << 'ext/mkrf_conf.rb'
And then the relevant lines in that mkrf_conf.rb source
require 'rubygems/dependency_installer.rb'
inst = Gem::DependencyInstaller.new
inst.install "test-unit" if RUBY_VERSION > "1.9"
Gem doesn't support conditional dependencies (except on gem builder's environment -as noted above), and bundler is not a viable option to solve this either - see https://github.com/carlhuda/bundler/issues/1281
hay ... i'm kind of a ruby newbie ... if this is the best way to do it.
any way ... i wish i can do that using only Ruby .... though u can use your operating system shell to do that, by using this in your program installer, just execute (works for Linux based operating systems):
$ruby --version
(u can execute that from a ruby installer file, just like: ruby --version)
and put a possibility according to output, if it's 1.9.1 add an extra line to execute:
$ sudo gem install gem_name
else, just leave it be.
Checkout this tutorial in the Ruby Programming wikibook.
Tt shows how to install different versions of dependencies depending on what version of ruby the installee is using.
(short answer--it ain't as easy as it should be)
You can't. You need to build two gems, one with
spec.required_ruby_version = '~> 1.8.6'
and one with
spec.required_ruby_version = '~> 1.9.1'
spec.add_dependency 'test-unit', '~> 2.0.5'
Gemspecs are just ruby files anyway, so you can execute any ruby code inside them, so:
spec.add_dependency = 'test-unit', '>= 2.0' if RUBY_VERSION =~ '1.9'
EDIT: Specs run only on the builders machine.

Resources