This is part 4 of a 5-part series on Ruby tips and tricks gleaned from our team’s pull requests over the last two years. Part 1 covers blocks and ranges, part 2 deals with destructuring and type conversions, and part 3 talks about exceptions and modules.
The Rails console is really useful for interactive debugging, and the same approach can come in very handy for non-Rails projects. Using irb from the the stdlib it’s surprisingly easy to get something up and running for your own project.
This example assumes you’ve put your code in
lib/ and your project has a
sensible entry point that you can
require to load up all the code.
I’ve added an example of setting up a Sequel database connection, you can
replace this with whatever setup code you might need, or just remove it. You
can also remove the
require "bundler/setup" if you’re not using Bundler.
Save this in the base directory of you project as
console and run
chmod +x console on the command line to make the file executable. You can now
start up a console session with
./console in the base directory of your
Any methods, instance variables, or constants you declare before the
IRB.start will be available during the console session, but it creates a new
scope so local variables aren’t accessible. Anything after will be run once you
When you’re debugging on the console irb shows you the result of each
expression by calling
#inspect on the result. Usually this gives you a fairly
low-level representation helpful in debugging, however in the case of Floats
it’s not quite as useful as it could be. Due to the way Ruby (and indeed most
programming languages) represent floating point numbers they are rarely
exactly the value you specify. An easy way to see the true value is using
Other times you can have the opposite problem, the detailed output from
#inspect can obscure what it is you’re actually looking for.
In this case you can redefine
#inspect on the class in hand in your test or
console script to return something more intuitive.
For the same reason it can often be helpful to define a custom
your own classes.
Sometimes you’re trying to hunt down a bug and you’re faced with two outputs
nearly identical, but not quite. You don’t want to hunt though the output
yourself, but using
diff seems like a lot of effort when you have to save
each output to a file, especially when you’re constantly changing things and
running the code again to narrow the problem down. Fortunately it turns out
Ruby has a handy diff method hidden away in the stdlib.
As a highly dynamic language, one that allows you to change almost anything at any time, Ruby sometimes makes it embarrassingly tricky to work out where a method is actually defined. It turns out Ruby can keep track of all this for you.
This shows us the
#to_set method on an Array instance comes from the
Enumerable module, and is actually defined on line 635 of
set.rb from the
There’s no set way to layout your Ruby project, but there are a few things that are good practice if you want to package your code up as a gem, and make sense for other projects too.
RubyGems works by adding a directory for each gem to the load path (the list to
search for files when you
require). You don’t want this to be the base
directory of your project, as you’d then make all the ancillary files
(Gemfile, tests, build scripts, etc) in your gem available to any users. To
work around this you usually put your code in a directory called
lib, and set
require_path attribute in your gemspec to
However now everything in your
lib directory can now potentially be loaded
require "name". This is fine for your core class or module, but say
you have an
api.rb file, this is a potentially common name and may clash with
other gems or the user’s code. For this reason it’s a good idea to have a
single main .rb file in your
lib directory, and then have a name-spaced
directory within this for the rest of your code.
Any ancillary files can go in your base directory, and most people will have a
spec) directory in there too.
This gives us the layout:
Usually you’d use one file per class, and name the file for the class,
snake_case rather than CamelCase. Directories under
lib would match your
name-spaces, thus you’d expect
lib/my_project/foo.rb to look something like
I’ll often have a couple of extra files that don’t map directly to a class, a
lib/my_project/errors.rb that contains all the Exception classes for my
project, and sometimes a
lib/my_project/constants.rb that contains constants
being used across the project.
Don’t feel the need to strictly follow the ‘one class per file’ rule, if you have a small helper class only used by one other it’s fine to bundle it in with the other.
When it comes to requiring files within your project you’ll want to use
require is great for loading up other gems and things
from the stdlib, but as it searches the global variable
for the thing you have required you can’t determine exactly what it’s going to
require_relative always follows the path starting from the file it’s
called in, meaning that no matter what it will always find the same file. This
is especially useful in your tests, as then you know for sure which bits of code
you are testing.
It’s usually a good idea to require all your classes, or at least the core ones,
lib/my_project.rb file. This way if packaged up as a gem or when
writing tests, scripts, etc there’s a single ‘entry point’ file to require and
you get everything.
Ruby comes packaged with some great documentation, and a handy little tool for
navigating it called
ri. It’s really simple to use, just run
ri at the
command line. Once it’s running you can enter a class name to get an overview of
that class and a list of methods. You can view class methods with
ClassName.method, and instance methods with
The docs for any gems you have installed will also be available though
assuming the authors have written any.
Documentation for gems can also be viewed by running
gem server and visiting
You can build the documentation for you own code using the
rdoc command, just
supply it with the directory of your code, and any additional files. It will
output to a
doc folder, open
doc/index.html in your web browser to see what
it has generated.
This will give you an outline of your classes and methods, but you can make the documentation much more helpful to others by writing comments using the rdoc format. These comments become the descriptions of classes and methods in the rdoc output.
Head on to Part 5.