In my Ruby program, I'm trying to lazy-load a library (crack for the curious).
If I do this:
require 'rubygems'
require 'crack'
Everything is working fine. However, when I try this:
require 'rubygems'
autoload :Crack, 'crack'
A LoadError is raised. (no such file to load -- crack)
Why is this error being raised? Is it because 'crack' (and therefore my other user-installed gems) are not in my $LOAD_PATH?
edit:
Furthermore, autoload does work with the Standard Library:
autoload :Yaml, 'yaml'
works fine, and raises no errors.
You'll need to add the 'crack' gem to your $LOAD_PATH by doing:
gem 'crack'
This is necessary because RubyGems replaces Kernel#require with a method that attempts to "activate" the gem before requiring it if necessary, but doesn't do the same thing for Kernel#load - and autoload calls load on the backend.
Related
This is in my Gemfile:
gem "trinsic_service_clients", "~> 1.1"
This is at the top of my file named instantiate_clients.rb
require_relative 'trinsic_service_clients
However, when I run bundle exec ruby instantiate_clients.rb I still get this error:
Traceback (most recent call last):
1: from instantiate_clients.rb:1:in `<main>'
instantiate_clients.rb:1:in `require_relative': cannot load such file -- /home/runner/DefenselessGrowlingExtraction/trinsic_service_clients (LoadError)
When I type bundler exec gem which trinsic_service_clients I get the following:
/home/runner/DefenselessGrowlingExtraction/.bundle/ruby/2.5.0/gems/trinsic_service_clients-1.1.5018/lib/trinsic_service_clients.rb
require_relative is for code in your application. It is not for code stored in gems. For those you should use require as it will look through $LOAD_PATH for the required files.
The easy way to make use of Gemfile is to load everything in via one shot:
require 'bundler'
Bundler.require(:default)
This not only adds the gem declarations, but does default require calls as well, as in this should already require your declared gem.
There's also require 'bundler/setup' which only adds the load paths, you still need to require, but this can help minimize load times if you may not necessarily need all the gems.
require 'bundler/setup'
require 'trinsic_service_clients'
This can be useful if your Gemfile has a lot of dependencies, but the scripts you're running may only use a small subset of them.
I am trying to run some older ruby script (with old ruby version) from within a ruby script. Here is a program:
old_ruby187.rb
#!/usr/ruby/1.8.7/bin/ruby
puts "Hello"
new_ruby230.rb
#!/usr/ruby/2.3.0/bin/ruby
require "rubygems"
require "bundler"
Bundler.setup # Code works if I comment this line
puts `old_ruby187.rb`
I get bundler load error. If I execute ./new_ruby230.rb, it gives an error for the last puts command line.:
'require': no such file to load -- rubygems (LoadError)
If I comment just Bundler.setup and run it, it works fine. Not sure if Bundler.setup tries to load something for system call. I need bundler for other gems used in new_ruby230.rb script.
Any help is appreciated.
Update (02/22/2018):
I ended up using ssh when calling old ruby script. Something like:
new_ruby230.rb
#!/usr/ruby/2.3.0/bin/ruby
require "rubygems"
require "bundler"
require "socket"
Bundler.setup
puts `ssh #{Socket.gethostname} old_ruby187.rb` # this worked!
Pretty sure you're not supposed to require rubygems like that. Bundler is there to manage your gems. Remove that require statement (require "rubygems") and you should be good to go.
I've got a wrapper for my Gem, socks, inside socks.rb. The entire file is made up of require statements, and a module declaration:
# lib/socks.rb
require 'socks/version'
require 'socks/base_controller'
require 'socks/templates'
require 'socks/tasks'
require 'socks/rake_tasks'
module Socks
end
However, require 'socks/tasks' and socks/rake_tasks is giving me a LoadError: no such file to load -- socks/tasks / rake_tasks error.
Is this a problem with the alignment of the require statements, or just the code?
Code is on Github: https://github.com/Beakr/socks
EDIT: require './socks/tasks' is now working, however require './socks/rake_tasks' is not.
Ruby load files using its $LOAD_PATH. This global array is changed by e.g. rubygems and bundler to allow to find libraries in various locations. In your sock.gemspec you have defined
gem.require_paths = ["lib"]
which means that rubygems will add the lib directory of your gem to ruby's $LOAD_PATH. But it odes so only if you have installed the gem and the gemspec is thus evaluated. If you don't want to install your gem, you can test your gem using
bundle exec irb
in your gem directory, or alternatively by first adapting your $LOAD_PATH in your irb session like so:
$LOAD_PATH.push "/path/to/your/gem/lib"
require 'socks'
I'd like to use bundler/setup to include all of my listed gems but I'm not
succeeding. In go.rb I have
require 'rubygems'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('Gemfile', __FILE__)
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
which fails to require httparty as I thought it would:
$ bundle exec ruby go.rb
go.rb:5:in `<main>': uninitialized constant HTTParty (NameError)
What am I doing incorrectly?
I've created a small project for this question, here.
As far as I understand 'bundler/setup' it only manages the require path (removes the default contents and adds paths for gems that are defined in Gemfile.lock). If you don't require the libraries in question, their contents won't be available.
I believe the problem in your particular case is the following snippet:
File.expand_path('Gemfile', __FILE__)
If I run this from a file called /foo/bin/somescript, what the above code expands to is /foo/bin/somescript/Gemfile. Presumably what you actually want is /foo/bin/Gemfile, which you can get with:
File.expand_path('../Gemfile', __FILE__)
So, repeating your original code with the correction:
require 'rubygems'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __FILE__)
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
This seems to work for me, to have files in my ~/bin directory have access to libraries I've installed by running bundle install within that directory, as specified by the Gemfile therein.
I have seen many samples of Ruby code with this line (for example, http://www.sinatrarb.com/). What is purpose of this require?
# require 'rubygems'
require 'sinatra'
get '/hi' do
"Hello world!"
end
In all cases the code works without this line.
require 'rubygems' will adjust the Ruby loadpath allowing you to successfully require the gems you installed through rubygems, without getting a LoadError: no such file to load -- sinatra.
From the rubygems-1.3.6 documentation:
When RubyGems is required, Kernel#require is replaced with our own
which is capable of loading gems on demand.
When you call require 'x', this is what happens:
If the file can be loaded from the existing Ruby loadpath, it
is.
Otherwise, installed gems are searched for a file that
matches. If it's found in gem 'y', that gem is activated
(added to the loadpath).
The normal require functionality of returning false if that file
has already been loaded is preserved.
See the documentation for Kernel#require to understand why this is necessary.
It is often superfluous. It will allow you to require specific versions of particular gems though, with the gem command.
https://guides.rubygems.org/patterns/#requiring-rubygems
As an addition to prior (and correct answers): Ruby 1.9 and newer ship with RubyGems built-in, so there is no real need to require 'rubygems'. Source here