How to define constants with traits

When defining a trait using the Modularity gem, you must take extra steps to define constants to avoid caveats (like when defining subclasses through traits).

tl;dr

In traits, always define constants with explicit self.

If your trait defines a constant inside the as_trait block, it will be bound to the trait module, not the class including the trait.
While this may seem unproblematic at first glance, it becomes a problem when including trai...

Access the documentation of all locally installed gems

In case https://www.rubydoc.info/ is to slow or offline, you can also read a gem documentation offline.

Start a server with gem server and go to http://0.0.0.0:8808/. Here you will find a list of all installed gems and it is possible to navigate to the documentation if installed e.g. http://0.0.0.0:8808/doc_root/rubocop-0.77.0/


In case you set the configured RubyGems to not install documentation by default, you need to add generate the documentation for the specific gem.

gem install rubocop --document
`...

ETags with memcached

I love ETags, but there’s something that annoys me: most implementations revolve around pulling a record out of a data store and only “rendering” the response if it hasn’t been modified. 

The problem with this approach is that request has already gone through most of your application stack–parsing params, authentication, authorization, a few database lookups–so ETags are only saving you render time and some bandwidth.

While working on a Sinatra-based JSON web service that gets very heavy traffic, I wanted to find a way to short-circuit...

Always show the page if there is an error in Cucumber

Are you adding a "Then show me the page" and re-run Cucumber whenever there is a failing scenario? Don't be that guy!

Save time with the shiny new version of our cucumber_spinner gem. It comes with a Cucumber formatter that not only displays an awesome progress bar, and shows failing scenarios immediately, it will also open the current page in your browser whenever a scenario step fails.

After you installed the gem, use the formatter like this:

cucumber --format CucumberSpinner::Curiou...

How to fix "extconf.rb:8:in `require': no such file to load -- mkmf (LoadError)"

If you're on Ubuntu:

sudo apt-get install ruby-dev

On other platforms: Look for a package containing ruby header files. On Red Hat that's "ruby-devel" likely.

Shell script to clean up a project directory

Call geordi clean from a project root to remove unused and unnecessary files inside it.


This script is part of our geordi gem on github. In Geordi > 1.2 you can call geordi clean.

Speed up RSpec by deferring garbage collection

Update: This trick probably isn't very useful anymore in Ruby 2.x. The Ruby GC has improved a lot over the years.


Joe Van Dyk discovered that running the Ruby garbage collector only every X seconds can speed up your tests. I found that deferring garbage collection would speed up my RSpec examples by about 15%, but it probably depends on the nature of your tests. I also tried applying it to Cucumber f...

Silencing Deprecation Warnings in Rspec

If you’re testing the behavior of deprecated code in your Ruby project, the warning messages littered throughout your spec output is incredibly noisy.

You could silence all warnings with ::ActiveSupport::Deprecation.silenced = true, but you might miss out on an important warning in one of your dependencies. It’s tempting to remove the tests altogether (the code will be burned soon too, right?), but I figured out something a little nicer a little while back in Formtastic’s test suite.

Iterate over every n-th element of a Range in Ruby

If you want to iterate over a Range, but only look at every n-th element, use the step method:

(0..10).step(5).each do |i|
  puts i
end

# Prints three lines:
# 0
# 5
# 10

This is useful e.g. to iterate over every Monday in a range of Dates.

If you are using Rails or ActiveSupport, calling step without a block will return an array of matching elements:

(0..10).step(5) 
# => [0, 5, 10]

Default block arguments for Ruby 1.8.7

When your block takes an argument that should have an default, only in Ruby 1.9 you can say:

block = lambda do |message, options = {}|
  # ...
end

If you are on Ruby 1.8.6 or 1.8.7 you must resort to the following workaround:

block = lambda do |*args|
  message = args[0]
  options = args[1] || {}
end

Overriding unary operators in Ruby

This must be one of the coolest, yet quite unknown, technique in Ruby. For certain types of problems (e.g. when you have a set of rules) this gives you such an elegant way of describing the solution. There’s no meta programming or monkey patching involved, it’s short and sweet and best of all: it’s very intuitive.

Word boundaries in MySQL regular expressions

In regular expressions you can use the zero-width pattern \b to match the beginning or end of a word:

note.title =~ /\bfoo\b/

Unfortunately \b is not available in MySQL. You can use [[:<:]] and [[:>:]] to match the beginning and end of a word instead:

SELECT * FROM notes WHERE title REGEXP "[[:<:]]foo[[:>:]]"

These markers are unique to MySQL and not available in Ruby regular expressions.

RSpec matcher to check if two numbers are the same

You can usually just use the eq matched to compare two numbers:

expect(deal.total).to eq(120)

If the actual value is a BigDecimal, you might have issues when you match it against a Float:

expect(deal.total_price).to eq(1200.99)

In these cases, try matching it against another BigDecimal:

expect(deal.total_price).to eq BigDecimal(1200.99)

If you don't like the syntax, our rspec_candy gem has a matcher that will compare Fixnums (integers), Floats and `BigDecima...

The Ruby Infinite Hash

How to create an infinitely nestable hash that always defaults to a new hash if a key does not map to a value.

Force net/http to verify SSL certificates

Ruby's net/http is setup to never verify SSL certificates by default. Most ruby libraries do the same. That means that you're not verifying the identity of the server you're communicating with and are therefore exposed to man in the middle attacks. This gem monkey-patches net/http to force certificate verification and make turning it off impossible.

Capistrano cowboy deploys

Sometimes, you just need to shoot from the hip…or deploy your local changes without committing them. Put this snippet from Jesse Newland in ~/.caprc and now you can cap cowboy deploy.

Ruby: Checking if a class is a descendant of another class

If you want to find out whether a Class object is directly inheriting from another class, use superclass:

ActiveRecord::RecordNotFound.super_class == ActiveRecord::ActiveRecordError # => true

To check if another class is an ancestor (not necessarily the direct superclass, but e.g. the superclass of the superclass):

ActiveRecord::RecordNotFound.ancestors.include?(StandardError) # => true

Note that ancestors also includes the receiving class itself as well as any included modules (which is quite...

Check if two arrays contain the same elements in Ruby, RSpec or Test::Unit

RSpec 1, RSpec 2

To test whether two arrays have the same elements regardless of order, RSpec 1 and 2 give you the =~ matcher:

actual_array.should =~ expected_array

Rspec 3

With RSpec 3's expect syntax you can choose one of these two matchers:

expect(actual_array).to match_array(['1', '2', '3'])
expect(actual_array).to contain_exactly('1', '2', '3')

Note how match_array takes an argument, but contain_exactly takes a list of elements as varargs.

Test::Unit

If y...

Encode or decode HTML entities

Use the htmlentities gem.

Encoding works like this:

require 'htmlentities'
coder = HTMLEntities.new
string = "<élan>"
coder.encode(string)               # => "&lt;élan&gt;"
coder.encode(string, :named)       # => "&lt;&eacute;lan&gt;"
coder.encode(string, :decimal)     # => "&#60;&#233;lan&#62;"
coder.encode(string, :hexadecimal) # => "&#x3c;&#xe9;lan&#x3e;"

Decoding works like this:

require 'htmlentities'
coder = HTMLEntities.new
string = "&eacute;lan"
cod...

Never use YAML.load with user input

You can get YAML.load to instantiate any Ruby object by embedding the desired class name into the YAML code. E.g. the following will create a new User object and set @email and @password to the given values:

--- !ruby/object:User
email: me@somewhere.com
password: secret

Considering the security implications, you should never trust YAML from untrusted sources. If you are looking for a simple, secure and readable data transfer format, use Object#to_json and JSON.parse.

Another way around YAML.load is [`YAML.safe_...

Open a page in the default browser

Use the Launchy gem:

Launchy.open('http://www.ruby-lang.org/')

Change the current directory without side effects in Ruby

To temporarily change the current working directory in Ruby, call Dir.chdir with a block. The previous working directory will be restored when the block ends:

Dir.chdir('/usr/local') do
  # do stuff in /usr/local
end

Ruby 2.0 Refinements in Practice

The first thing you need to understand is that the purpose of refinements in Ruby 2.0 is to make monkey-patching safer. Specifically, the goal is to make it possible to extend core classes, but to limit the effect of those extensions to a particular area of code. Since the purpose of this feature is make monkey-patching safer, let’s take a look at a dangerous case of monkey-patching and see how this new feature would improve the situation.

MySQL: Select a default value for NULL fields

If you need to do calculations inside the database and can not use Ruby objects you may run into problems when encountering fields with NULL values:

SELECT foo, bar, foo - bar AS baz FROM plop;
+-----+------+------+
| foo | bar  | baz  |
+-----+------+------+
|  30 |   20 |   10 |
|  30 | NULL | NULL |
+-----+------+------+

Solve this by using IFNULL: it returns the selected value if present and a given alternative if it would select NULL:

SELECT foo, bar, foo - IFNULL(bar, 0) AS baz FROM plop;
+-...