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

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

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

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_module

  def current_user
    #let helpers act like we're a guest
    nil
  end       

  def self.instance
    @instance ||= new
  end
end

and then use with...

Helpers to render (money) amounts

When rendering a number, you want to pretty up the string coming from #to_s:

  • Render 0.0 as 0
  • Sometimes require a minimum number of digits after the decimal separator
  • Change the decimal separator from . to , in some European countries
  • Render a dash if the given amount is nil

The attached helper that does just that. Some usage examples with their resulting strings:

Invocation Result
amount(0) 0
amount(0.0) 0
amount(0.5) 0,5
amount(1.5, :minimum_precision => 2) 1,50
`amo...

Soft-scroll to an anchor with jQuery

This snippet makes links that refer to an anchor (like "<a href="#something">...</a>") scroll softly to it.\
In this example we only do it for links that also own a data-animate attribute.

$('a[href^="#"][data-animate]').live('click', function() {
  var hash = $(this).attr('href');
  var offset = $(hash).offset();
  if (offset) {
    $('html, body').animate({ scrollTop: offset.top }, 'slow');
    location.hash = hash;
    return false;
  }
});

Note that this could basically work for any element whos...

Using StaticMatic for static pages

Update: Staticmatic will not be further developed. They suggest to switch to middleman.


If you need to make a static web page and find yourself missing all your Rails comforts, take a look at StaticMatic.

This works like an extremely stripped down version of Rails, giving you

  • HAML
  • SASS
  • helpers
  • partials

When done, everything is simply compiled to s...

Center a float horizontally

Note: We have card with all CSS centering options. You probably want to head over there and get an overview over what techniques are available for your use case and browser requirements.


If you cannot use display: inline-block, centering a float can be useful if you want to center something and at the same time make its width automatically fit some content.

Use this SASS:

.center_float_outer_container
  overflo...

Conditional comments for Internet Explorer with Haml

Internet Explorer 5+ is aware of conditional comments that let you target HTML for selected versions of IE. For example the HTML below would ask users of IE 6 and IE 7 to install Firefox:

<!--[if lt IE 8]>
  <a href='http://www.mozilla.com/en-US/firefox/'>Get a real browser</a>
<![endif]-->

You might wonder how to express such a conditional comment in your favorite templating language, Haml. You might even have converted a template back to ERB just for this ...

Playing audio in a browser

If you want to play music or sounds from a browser, your choice is to use either Flash or the new <audio> tag in HTML5. Each method has issues, but depending on your requirements you might not care about all of them.

Flash

  • Works in all desktop browsers, even Internet Explorer. Does not work on iPads or iPhones.
  • Requires you to embed a Flash component into your page which will later play the audio for you.
  • Can play MP3s or Wave files. Cannot play OGG Vorbis audio.
  • Cannot reliably seek to a given position when playing VBR-enco...

How to fix strangely disappearing or misbehaving forms

You most likely have a form element inside another form element. Don't do that. Ever.

Firefox and Chrome will discard the first form nested inside another form (but for some reason keep others). Internet Explorer will possibly act like nothing is wrong -- but break (send the outer form) when you submit.

If your application behaves normal at first but removes forms from the DOM when you Ajax around, this could be the cause. Remember this note when you think your browsers are broken once again and check for such things thoroughly bef...