How can I debug require in Ruby 1.9 - ruby

According to the Tin Man's opinion, i open a new question.
Original questions is here: How does Rubygem require all gems?
Original code i used to debug:
require 'debugger'
debugger
require 'thor'
Here's the dilemma:
debug with the default -rdebug, i cant go to Rubygem's source code
debug with debugger gem, i have to require before i debug (the way i tried in the previous question, which is unacceptable because something important had happened before i get there)
Hope to find a way to debug IT.

When rubygems is required it replaces Ruby’s Kernel.require method with its own that searches for required files in the installed gems. The integration with Ruby 1.9 and above is basically a call to require 'rubygems' during start up. This can be disabled with the (poorly documented) --disable-gems option to the ruby executable. You could make use of this to set up your debugging before explicitly calling require 'rubygems'.
# start with ruby --disable-gems
require 'debug' #standard library debug - doesn't load rubygems
require 'rubygems' #now you can debug this
If you want to use the debugger gem for your debugging it’s still possible but a little trickier as you have to load debugger without loading Rubygems. In order to do this you’ll need to manually set up your load path to include Debugger’s lib dir, as well as the lib dirs of any gems Debugger depends on. This is basically what Rubygems does for you when you call require 'debugger' with Rubygems loaded.
To determine what libs Debugger needs, you can use this command:
ruby -e "lp = $:.dup; gem 'debugger'; puts $: - lp"
This is little Ruby script that first takes a copy of the load path ($: is the load path, you can also use $LOAD_PATH), then activates the Debugger gem, then prints out the difference between the new load path and the original. This will give you the dirs that activating debugger adds to the load path.
On my machine this looks like this:
$ ruby -e "lp = $:.dup; gem 'debugger'; puts $: - lp"
/Users/matt/.rvm/gems/ruby-1.9.3-p385/gems/columnize-0.3.6/lib
/Users/matt/.rvm/gems/ruby-1.9.3-p385/gems/debugger-ruby_core_source-1.2.0/lib
/Users/matt/.rvm/gems/ruby-1.9.3-p385/gems/debugger-linecache-1.2.0/lib
/Users/matt/.rvm/gems/ruby-1.9.3-p385/gems/debugger-1.5.0/lib
You can now use this to create a script to use Debugger to debug require 'rubygems':
# start with ruby --disable-gems
# set up the load path without loading rubygems
$:.unshift '/Users/matt/.rvm/gems/ruby-1.9.3-p385/gems/columnize-0.3.6/lib'
$:.unshift '/Users/matt/.rvm/gems/ruby-1.9.3-p385/gems/debugger-ruby_core_source-1.2.0/lib'
$:.unshift '/Users/matt/.rvm/gems/ruby-1.9.3-p385/gems/debugger-linecache-1.2.0/lib'
$:.unshift '/Users/matt/.rvm/gems/ruby-1.9.3-p385/gems/debugger-1.5.0/lib'
# require debugger and start it
require 'debugger'
debugger
require "rubygems" #now you can debug this with debugger

Related

How to require the proper version of test/unit

I'm trying to require the new (i.e. not the one bundled with ruby) version of test/unit. As per the instructions I installed it with gem i test-unit. But now when I require test/unit I seem to be requiring the old version. For example, I don't have the method Test::Unit.at_start. This happens even when I explicitly require the full path to the new test/unit installation.
Is there any way for me to investigate which symbols are being loaded and why?
Since Ruby comes with an implementation of test/unit (it’s actually a Minitest compatibility wrapper) calling require 'test/unit' will load that version, since it is already on the load path. Calling require '/absolute/path/to/test/unit' will load the new file, but when that file calls e.g. require 'test/unit/testcase it will load the files from stdlib, resulting in a mix of classes (so don’t do that).
What you need to do is activate the gem with the gem method before you require it. That will ensure the gem lib path is on your load path before the stdlib, so require will find those files first.
gem 'test-unit' # You can also pass a specific version as a second
# argument to `gem` if you want.
require 'test/unit' # This will find the gem version.
# Now the gem version will be loaded.

Rackup: cannot load such file 'sinatra'

I already installed sinatra gem and in irb, if I type,
require 'sinatra'
It returns true.
But when I do
rackup -d config.ru
It tells me
nil
Exception `LoadError' at /usr/local/lib/ruby/1.9.1/rubygems/custom_require.rb:36 - cannot load such file -- sinatra
Here is my config.ru
require './app'
set :environment, ENV['RACK_ENV'].to_sym
set :app_file, 'app.rb'
disable :run
run Sinatra::Application
app.rb
require 'rubygems'
require 'sinatra'
get '' do
'Hello World'
end
I don't know what is going wrong.
$ which ruby
/usr/local/bin/ruby
$ which rackup
/usr/local/bin/rackup
$ ruby -v
ruby 1.9.3p374 (2013-01-15 revision 38858) [x86_64-linux]
$ rackup -v
Rack 1.2 (Release: 1.5)
I think this is just the verbose output from setting the -d option. Does the server actually start (after producing a load of output)?
What’s happening is this. Using -d sets Ruby’s $DEBUG flag to true. Rack then tries to load the app through the config.ru, which in turn loads your app.rb. The first thing in app.rb is require 'sinatra'.
Rubygems replaces the original require method with its own. When you call require it tries to load the file normally using the existing load path and the original require method. If the gem hasn’t been loaded this will raise a LoadError, which Rubygems catches before loading the gem.
With the $DEBUG flag set, Ruby will produce a message when an exception is raised even though it is rescued and dealt with, and this is what you’re seeing.
To avoid this simply omit the -d flag to your call to rackup (perhaps enabling warnings with -w would give you a sufficiently verbose output without swamping you in too much detail).
If the server isn’t starting then it will be a different issue rather than not finding Sinatra. If that is the case you’ll need to check the rest of the output for clues.
(Note that I originally thought something else was happening, and that’s what my questions int he comments were about.)
my guess is that your rackup script is a binstub of a 'rack' gem
installed in a diff ruby1.9x vm
maybe earlier version of ruby1.9.2
so it can't see the sinatra installed
I'd try 'which rackup' on the command line
This is definitely issue of load path. Anyway try to setup required ruby and gems via RVM and Bundler. It makes sure that Ruby interpreter and load paths are consistent.

Strange require statement errors in Ruby?

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'

require 'rubygems'

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

I have a gem installed but require 'gemname' does not work. Why?

The question I'm really asking is why require does not take the name of the gem. Also, In the case that it doesn't, what's the easiest way to find the secret incantation to require the damn thing!?
As an example if I have memcache-client installed then I have to require it using
require 'rubygems'
require 'memcache'
My system also doesn't seem to know about RubyGems' existence - unless I tell it to. The 'require' command gets overwritten by RubyGems so it can load gems, but unless you have RubyGems already required it has no idea how to do that. So if you're writing your own, you can do:
require 'rubygems'
require 'gem-name-here'
If you're running someone else's code, you can do it on the command line with:
ruby -r rubygems script.rb
Also, there's an environment variable Ruby uses to determine what it should load up on startup:
export RUBYOPT=rubygems
(from http://www.rubygems.org/read/chapter/3. The environment variable thing was pointed out to me by Orion Edwards)
(If "require 'rubygems' doesn't work for you, however, this advice is of limited help :)
There is no standard for what the file you need to include is. However there are some commonly followed conventions that you can can follow try and make use of:
Often the file is called the same
name as the gem. So require mygem
will work.
Often the file is
the only .rb file in the lib
subdirectory of the gem, So if you
can get the name of the gem (maybe
you are itterating through
vendor/gems in a pre 2.1 rails
project), then you can inspect
#{gemname}/lib for .rb files, and
if there is only one, its a pretty
good bet that is the one to require
If all of that works, then all you can do is look into the gem's directory (which you can find by running gem environment | grep INSTALLATION | awk '{print $4}' and looking in the lib directory, You will probably need to read the files and hope there is a comment explaining what to do
The require has to map to a file in ruby's path. You can find out where gems are installed by running 'gem environment' (look for INSTALLATION DIRECTORY):
kburton#hypothesisf:~$ gem environment
RubyGems Environment:
- RUBYGEMS VERSION: 1.2.0
- RUBY VERSION: 1.8.7 (2008-08-08 patchlevel 71) [i686-linux]
- INSTALLATION DIRECTORY: /usr/local/ruby/lib/ruby/gems/1.8
- RUBY EXECUTABLE: /usr/local/ruby/bin/ruby
- EXECUTABLE DIRECTORY: /usr/local/ruby/bin
- RUBYGEMS PLATFORMS:
- ruby
- x86-linux
- GEM PATHS:
- /usr/local/ruby/lib/ruby/gems/1.8
- GEM CONFIGURATION:
- :update_sources => true
- :verbose => true
- :benchmark => false
- :backtrace => false
- :bulk_threshold => 1000
- REMOTE SOURCES:
- http://gems.rubyforge.org/
kburton#editconf:~$
You can then look for the particular .rb file you're attempting to require. Additionally, you can print the contents of $: from irb to see the list of paths that ruby will search for modules:
kburton#hypothesis:~$ irb
irb(main):001:0> $:
=> ["/usr/local/ruby/lib/ruby/site_ruby/1.8", "/usr/local/ruby/lib/ruby/site_ruby/1.8/i686-linux", "/usr/local/ruby/lib/ruby/site_ruby", "/usr/local/ruby/lib/ruby/vendor_ruby/1.8", "/usr/local/ruby/lib/ruby/vendor_ruby/1.8/i686-linux", "/usr/local/ruby/lib/ruby/vendor_ruby", "/usr/local/ruby/lib/ruby/1.8", "/usr/local/ruby/lib/ruby/1.8/i686-linux", "."]
irb(main):002:0>
Also rails people should remember to restart the rails server after installing a gem
You need to include "rubygems" only if you installed the gem using gem . Otherwise , the secret incantation would be to fire up irb and try different combinations . Also , you can pass the -I option to the ruby interpreter so that you include the instalation directory of the gem , in the LOAD_PATH .
Note that $LOAD_PATH is an array , which means you can add directories to it from within your script.
The question I'm really asking is why require does not take the name of the gem.
Installing a gem gets the files onto your system. It doesn't make any claims as to what those files will be called.
As laurie points out there are several conventions for how they are named, but there's nothing to enforce that, and many gem authors unfortunately don't stick to them.
Also, In the case that it doesn't, what's the easiest way to find the secret incantation to require the damn thing!?
Read the docs for your gem?
I find googling for rdoc gemname will usually find the official rdocs for your gem, which usually show you how to use it.
Memcache is perhaps not the best example, as they assume you'll be using it from rails, and the 'require' will have already been done for you, but most other ones I've seen have examples which show the correct 'require' incantations
I had this problem because I use rvm and was trying to use the wrong version of ruby. The gem in question needed 1.9.2 and I had set 2.0.0 as my default! Maybe a dumb error but one that someone else arriving on this page will probably have made.
An issue I just ran into was that the actual built gem was not including all the files that it should have.
The issue with files was that there was a syntax mistake in the in the gemspec, but no errors were thrown during the build.
Just adding this here in case anybody else runs into the same issue.
It could also be the gem name mismatch:
e.g.
dummy-spi-0.1.1/lib/spi.rb should be named dummy-spi-0.1.1/lib/dummy-spi.rb
then you can
require 'dummy-spi'
I too had this problem since installing OS X Lion, and found that even if I ran the following code I would still get the warning message.
require 'rubygems'
require 'nokogiri'
I tried loads of solutions posted here and on the web, but in the end my work around solution was to simply follow the instructions at http://martinisoftware.com/2009/07/31/nokogiri-on-leopard.html to reinstall LibXML & LibXSLT from source, but ensuring the version of LibXML I installed matched the one that was expected by Nokogiri.
Once I had done that, the warnings went away.
Watch source of gem and check lib directory. If there is no rb file then you must point to gem main rb file in subdirectory:
require 'dir/subdir/file'
for /lib/dir/subdir/file.rb.

Resources