Dump your database with dumple

This tool is used on our application servers (and called when deploying) but it also works locally.
Just call dumple development from your project directory to dump your database.


This script is part of our geordi gem on github.

Validate an XML document against an XSD schema with Ruby and Nokogiri

The code below shows a method #validate which uses Nokogiri to validate an XML document against an XSD schema. It returns an array of Nokogiri::XML::SyntaxError objects.

require 'rubygems'
gem 'nokogiri'
require 'nokogiri'

def validate(document_path, schema_path, root_element)
  schema = Nokogiri::XML::Schema(File.read(schema_path))
  document = Nokogiri::XML(File.read(document_path))
  schema.validate(document.xpath("//#{root_element}").to_s)
end

v...

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
`...

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...

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.

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...

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.

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...

Open a page in the default browser

Use the Launchy gem:

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

Virtual attributes for array fields

When a has_many association basically serves to store a list of associated strings (tags, categories, ...), it can be convenient to represent this association as a string array in the containing model. Here is an example for this pattern from the acts-as-taggable-on gem:

post = Post.last
p post.tag_list # ['foo', 'bar', 'baz']
post.tag_list = ['bam']
p post.tag_list # ['bam']

This string array tag_list is magical in several ways:

  • It is read from and written to a `has...

Manipulate an array attribute using multiple check boxes

E.g. when you're using a tagging gem, you have seen virtual attributes that get and set a string array:

post = Post.last
puts post.tag_list # ['foo', 'bar', 'baz']
post.tag_list = ['bam']
puts post.tag_list # ['bam']

If you would like to create a form displaying one check box per tag, you can do this:

- form_for @post do |form|
  = form.check_box :tag_list, { :multiple => true }, 'foo', nil
  = form.check_box :tag_list, { :multiple => true }, 'bar', nil
  =...

Use the back button in Cucumber

In order to go back one page in your Cucumber tests, you can use the following step definition for Capybara:

When(/^I go back$/) do
  visit page.driver.request.env['HTTP_REFERER']
end

If you're on Webrat, this should work:

When(/^I go back$/) do
  visit request.env["HTTP_REFERER"])
end

An improved version of this step is now part of our gem spreewald on Github.

Test a gem in multiple versions of Rails

Plugins (and gems) are typically tested using a complete sample rails application that lives in the spec folder of the plugin. If your gem is supposed to work with multiple versions of Rails, you might want to use to separate apps - one for each rails version.

For best practice examples that give you full coverage with minimal repitition of code, check out our gems has_defaults and assignable_values. In particular, take a look at:

  • Multiple `sp...

Install a specific version of a gem

To install webmock 1.5.0:

sudo gem install webmock --version "=1.5.0"

or
sudo gem install webmock -v "=1.5.0"

Prevent Bundler from downloading the internet

As a user of Bundler you have spent significant time looking at this message:

Fetching source index for http://rubygems.org/

To make Bundler skip this index update and only use installed gems, you can use the --local option:

bundle install --local

Unfortunately this does not work with bundle update.

It is said that Bundler 1.1 will use a feature of Rubygems.org that allows partial index updates. Hopefully the wh...

Defining and using sub-classes with modularity

Given this class:

class Foo
  class Bar
  end
end

If you want to clean up this code with the modularity gem, you might try something like this:

class Foo
  does 'bar'
end

module BarTrait
  as_trait do
    class Bar
    end
  end
end

Note that this changes Bar's full class name from Foo::Bar to BarTrait::Bar. If you have methods inside Foo (or other classes), you would have to change all references accordingly, which is quite unpleasant.

You can solve it like that:
`...

Install gems for all bundled projects

This is a bash script for those of you who need to install all gems for all projects (e.g. to get started quickly on a newly installed system).

Put it into your ~/bin/ and run it from the directory that holds your projects.

Note that, like the vanilla bundle install, this will fail whenever a new gem compiles native components and requires a missing system dependency.

Fix LoadError with Rails 3 applications on Passenger

After switching to Rails 3 you may get a LoadError with the following message when trying to use your application via passenger:
no such file to load -- dispatcher

Your Passenger version is most likely out of date.

Update the gem, then install the apache module again:
sudo gem install passenger
sudo passenger-install-apache2-module

Follow any instructions. Update your /etc/apache2/httpd.conf with the lines given at the end of the installation process to use the version you just installed.

Migrating to RSpec 2 from RSpec 1

You will need to upgrade to RSpec >= 2 and rspec-rails >= 2 for Rails 3. Here are some hints to get started:

  • In RSpec 2 the executable is rspec, not spec.
  • RSpec and rspec-rails have been completely refactored internally. All RSpec classes have been renamed from Spec::Something to RSpec::Something. This also means that every require 'spec/something' must now be require 'rspec/something'.
  • In spec_helper.rb, Spec::Runner.configure becomes RSpec.configure
  • It has become really hard to extend specific example groups ...

Shell script to quickly switch Apache sites

I prefer the application that I'm currently working on to be reachable at http://localhost/.

So when I switch to another project, I use this handy shell script to set one site as the current one. Call it just like this:
apache-site makandra-com

Note that it disables all other sites in your Apache configuration so you would not want to use this on production machines.
Furthermore it will also enable the default site if that was available.

When you call apache-site with no arguments, it will list all available sites.


...

On memoizing methods that return a scope

Be careful when memoizing a method that returns a scope, e.g.:

def variants
  scoped(:conditions => { :name => name })
end

memoize :variants

Because of the way memoize is implemented, that method now no longer returns a scope but its loaded target array.

The best solution is to use the Memoizer gem instead.

A workaround is to roll your own memoization:

def variants
  @va...

Working around the ancestry gem's way of object destruction

The ancestry gem allows you to easily use tree structures in your Rails application.

There is one somewhat unobvious pitfall to it: its way of applying the orphan_strategy which defines how it handles children of an object going to be destroyed.

What's this all about?

In many cases you might want to disallow destruction if there are any child nodes present. The restrict strategy does the trick but raises an exception when destroy is called:
has_ancestry :orphan_st...

Install the Nokogiri gem on Ubuntu servers

You need to install the following packages before you can build the Nokogiri gem:

sudo apt-get install libxml2-dev libxslt1-dev