How to use Rails URL helpers in any Ruby class

If you have any class which requires access to some path methods generated by your routes. Even though you could technically include Rails.application.routes.url_helpers, this may include way too many methods and even overwrite some class methods in the worst case.

Instead, most of the time the following is advised to only make the desired methods available:

class Project
  delegate :url_helpers, to: 'Rails.application.routes'

  def project_path
    url_helpers.project_path(self)
  end
end

Invoices: How to properly round and calculate totals

While it might seem trivial to implement an invoice that sums up items and shows net, gross and vat totals, it actually involves a lot of rules and caveats. It is very easy to create invoices where numbers don't add up and a few cents are missing. A missing cent is a big deal for an accountant, so it is important for your invoices to list correct numbers.

Note that this is not legal advice. Also note that while this note has a number of code examples in Ruby and MySQL, the concepts apply to all programming languages and data stores.

When ...

Always show all form errors during development

You've been there: A form cannot be submitted, but you don't see a validation error because the field at fault has no corresponding input field on the form. Because this is usually a bug, you insert debug information listing all errors into the form view. And once the bug is fixed, you forget to take out that debug information.

There is a better way. By copying one of the attached initializers into config/initializers, your forms will always render a small box listing all form errors in the bottom right corner of the screen. This box is n...

Distance of time in what you like: days, months, years

Sometimes the Rails helper #distance_of_time_in_words is using too much magic.
When you need a time difference in a specific unit, use this method:
^
def distance_of_time_in(unit, from, to)
diff = to - from

  if 1.respond_to? unit
    distance = diff / 1.send(unit)
    distance.abs.round
  else
    raise ArgumentError, "#{unit.inspect} is not supported as unit"
  end
end

distance_of_time_in(:days, Time.now, 1.year.ago)
=> 365

Remove the .abs if you want the mathematical *differ...

How to make a single check box (or image, etc) align vertically

Consider this HTML:

<div style="line-height: 42px">
  <input type="checkbox" />
</div>

Even though the surrounding container defines a line-height, which vertically centers its inline elements, the check box will be top aligned if it is the only element inside the container.

It will be aligned correctly if the HTML looks like this:

<div style="line-height: 42px">
  <input type="checkbox" /> foo
</div>

Complex explanation here.

So the ac...

Ruby GetText will eval scripts containing ActiveRecord classes

When the Ruby parser module of Ruby-GetText comes across a file in one of its search directories (e.g. lib/scripts/) and finds out that you are defining ActiveRecord classes inside it, it evaluates the whole file. Here is how to avoid that.

What's happening?

Let's say you have the following script which is only run once, manually, via script/runner:

# lib/scripts/doomsday.rb
class User < ActiveRecord::Base; end
User.destroy_all

In that case we ...

Detect the current Rails environment from JavaScript or CSS

Detecting if a Javascript is running under Selenium WebDriver is super-painful. It's much easier to detect the current Rails environment instead.

You might be better of checking against the name of the current Rails environment. To do this, store the environment name in a data-environment of your <html>. E.g., in your application layout:

<html data-environment=<%= Rails.env %>>

Now you can say in a pi...

How to stub class constants in RSpec

Hint: There's another card with this helper for Cucumber features.


Sometimes you feel like you need to stub some CONSTANT you have defined in an other class. Since actually constants are called constants because they're constant, there's no way to easily stub a constant.

Here are three solutions for you.

Easiest solution

Rethink! Do you really need CONSTANT = %w[foo bar] to be constant? In many cases, setting it as a...

Capybara - The missing API

The Capybara API is somewhat hard for parse for a list of methods you can call on a Capybara node. Below you can find such a list. It's all copied from the Capybara docs, so all credit goes to the Capybara committers.

When you talk to Capybara from a Cucumber step definition, you always have page as the document root node, or whatever you scoped to by saying within(selector) { ... }. You can select child notes by calling page.find(selector) or page.all(selector). You can call the same ...

How to grep through the DOM using the Capybara API

When your Cucumber feature needs to browse the page HTML, and you are not sure how to express your query as a clever CSS or XPath expression, there is another way: You can use all and find to grep through the DOM and then perform your search in plain Ruby.

Here is an example for this technique:

Then /^I should see an image with the file...

How to diff two strings in Ruby

When you need to use diff in either some Ruby code or your Rails app, use the differ gem.

puts Differ.diff "foo", "boo"
# => {"boo" >> "foo"}

Usage

There are several variants available, all using the base method diff(to, from, separator = "\n").
You have diff_by_line, diff_by_word, diff_by_char and may of course use your own separator:

puts Differ.diff 'Hauptsatz, und mein Nebensatz.', 'Hauptsatz, und dein Nebensatz.', ','
# => Hauptsatz,{" und dein Nebensatz." >> " un...

JSONP - Wikipedia

Under the same origin policy, a web page served from server1.example.com cannot normally connect to or communicate with a server other than server1.example.com. An exception is the HTML <script> element. Taking advantage of the open policy for <script> elements, some pages use them to retrieve Javascript code that operates on dynamically-generated JSON-formatted data from other origins. This usage pattern is known as JSONP. Requests for JSONP retrieve not JSON, but arbitrary JavaScript code.

Use Capybara on any HTML fragment or page

I think this pattern is really useful not just for upgrading suites from Webrat, but really anywhere you have an HTML fragment or string that you’d like to use Capybara’s matchers on.

Hide your Selenium browser window with a VNC server

This is now part of geordi. Please don't follow the instructions below, if you use geordi.

Inspired by the recent headless Selenium note, I found yet another solution for the problem to hide your selenium tests away.

This has the advantages
^

  • not to require a gem (so you do not force this on others)
  • to allow you to take a look at the running webdriver if necessary

Simply make a script th...

simple_format helper for Javascript

The Javascript code below is a rough equivalent to the simple_format helper that ships with Rails:

function simpleFormat(str) {
  str = str.replace(/\r\n?/, "\n");
  str = $.trim(str);
  if (str.length > 0) {
    str = str.replace(/\n\n+/g, '</p><p>');
    str = str.replace(/\n/g, '<br />');
    str = '<p>' + str + '</p>';
  }
  return str;
}

Unlike the Rails helper, this does not preserve whitespace. You probably don't care.

A few hints when upgrading to Ruby 1.9

Note: If you are currently working with Ruby 1.8.7 or 1.9.3, we recommend to upgrade to Ruby 2.1 first. From our experience this upgrade is much smoother than the jump from 2.1 and 2.2, while still giving your the huge performance gains of Ruby 2. Also, if you're on Ruby 1.8.7, we recommend to skip a troublesome upgrade to 1.9.3 and go straight to 2.1.


When trying to make a Rails app run on Ruby 1.9, you're likely to encounter several issues. Here are a few solutions (obviously not exhaustive):

When running `bundle ...

Rails 3: Make "link_to :remote => true" replace HTML elements with jQuery

In Rails 2, you could use link_to_remote ... :update => 'id' to automatically replace the content of $('#id').

To do the same in Rails 3, include usual rails-ujs JavaScript, and put this into your application.js:

$(function() {
  $('[data-remote][data-replace]')
    .data('type', 'html')
    .live('ajax:success', function(event, data) {
      var $this = $(this);
      $($this.data('replace')).html(data);
      $this.trigger('ajax:replaced');...

Virtual attributes for date fields

Note that this card is very old. You might want to use ActiveType for your auto-coerced virtual attributes instead.


We sometimes give our models virtual attributes for values that don't need to be stored permanently.

When such a virtual attribute should contain Date values you might get unexpected behavior with forms, because every param is a string and you don't get the magic type casting that ...

Shell script to generate a Git commit with Pivotal Tracker story ID and title

We usually generate our commit messages from Pivotal Tracker IDs and titles, like
[#15775609] Index view for conflicts

The geordi command commit automates this. (See: Pretty Commit messages via geordi).

Just run geordi commit and it will connect to PT and let you select from a list of all started and finishes stories. Then it runs git commit with the generated message (i.e. all staged changes will be commited).

When running for the first time, Geordi will request your PT...

Configuring ActionMailer host and protocol for URL generation

When you generate a URL in a mailer view, ActionMailer will raise an error unless you previously configured it which hostname to use.

There are two options to set the default_url_options of ActionMailer:

  1. Hardcoded solution (preferred solution when using Rails with ActiveJob/Sidekiq or Cronjobs)
  2. Dynamic solution

1. Hardcoded solution

When you are sending mails from outside the request cycle, e.g. ActiveJob/Sidekiq or Cronjobs, y...

Popular mistakes when using nested forms

Here are some popular mistakes when using nested forms:

  • You are using fields_for instead of form.fields_for.
  • You forgot to use accepts_nested_attributes in the containing model. Rails won't complain, but nothing will work. In particular, nested_form.object will be nil.
  • The :reject_if option lambda in your accepts_nested_attributes call is defined incorrectly. Raise the attributes hash given to your :reject_if lambda to see if it looks like you expect.
  • If you are nesting forms into nested forms, each model involved ne...

How to build the perfect number of blank records for a nested form

When you render a nested form for a Movie which has_many :actors, you want to render the right number of blank Actor forms. The right number means:

  • A minimum number of blank forms so the user can add more Actors to an existing Movie, e.g. 2.
  • A minimum total number of forms (both blank and pre-filled) so the user sees more than just 2 blank Actor forms when she is entering Actors for the first time, e.g. 5.

For the example above, this is the desired progression of the number of blank forms:

| Number of actors | Number of ...

Force Google Chrome to run in English on Linux

If you need Google Chrome to run in English, and your system locale is a non-English one, you have two options:

  • Switch your system to an English locale
  • Head over to /opt/google/chrome/locales/ and remove any .pak files except those starting with “en”. They reappear when Chrome gets updated.

This may help you running your Selenium tests using the Chrome driver on applications that choose the language from what the browser sends as preferred language (which Chrome guesses from your system locale).

How to use helper methods inside a model

Simple

If you want to use a helper_method my_helper_method inside a model, you can write

ApplicationController.helpers.my_helper_method

When using multiple helpers

delegate :helpers, to: ApplicationController
helpers.my_helper_method
helpers.my_other_helper-method

More flexible

If you need a bit more flexibility, for example if you also need to override some methods, you can do this:

class HelperProxy < ActionView::Base
  include ApplicationController.master_helper_modu...