Update: Aggregated RSpec/Cucumber test coverage with RCov

Our rcov:all task for aggregated RSpec/Cucumber coverage was overhauled extensively. Among other things it now works for Rails 2 and 3 and has an option to ignore shared traits.

RCov: The difference between "code coverage" and "total coverage"

Code coverage is the ratio of code lines kissed by a test vs. the total number of lines in your source files. This sounds meaningful, but isn't.

Total coverage additionally ignores whitespace and comments when computing the coverage ratio, which is what you want.

Fix AssociationTypeMismatch

When you're getting this error, one possibility is that you've created a select field for an association instead of the associated object's id. Example:

form.select :unit, Unit.for_select

will be expected to deliver a real Unit object, whereas

form.select :unit_id, Unit.for_select

will make Rails typecast the String value from the select field to the unit's ID.

Managing Rails locale files with i18n-tasks

When internationalizing your Rails app, you'll be replacing strings like 'Please enter your name' with t('.name_prompt'). You will be adding keys to your config/locales/*.yml files over and over again. Not to miss any key and place each at the right place is a challenging task.

The gem i18n-tasks has you covered. See its README for a list of things it will do for you.

Note

The i18n-tasks gem does not understand aliases and will duplicate all referenced data when it writes locales. If yo...

Request a gzipped response from a web server using Wget

To reduce download time, application servers usually serve content using gzip compression, if the browser supports it.

When using a tool like Wget to explicitly download an application's response, the server responds with the uncompressed version:

wget http://example.com/

If you are curious about the compressed file's size, pass the corresponding HTTP header:

wget --header="accept-encoding: gzip" http://example.com/

Embed Google Analytics code for some environments only

When you use google analytics to track your visitors interactions, you should ensure that it runs on your production site only. Otherwise it will spoil your statistics. To prevent this, test for the right environment and place the JS-code afterwards:

- if Rails.env.production?
  :javascript
    var _gaq = _gaq || [];
    _gaq.push(['_setAccount', 'UA-XXXXXXXX-X']);
    _gaq.push(['_trackPageview']);
    ...

How to fix "unknown role" errors in Capistrano recipes

When you have a complex recipe setup with multistage deployment you may run into this error:

`role_list_from': unknown role `something' (ArgumentError)

Consider this task definition:

namespace :foo do
  task :bar, :roles => :something do
    # do crazy stuff
  end
end

Whenever we call foo.bar in our recipe, Capistrano will fail if you deploy to a stage where none of the servers has the role the error complains about, "something" in this case.

However, you can [hack around it](http://groups.google.com/group/ca...

Scenario outlines in Cucumber

Scenario outlines allow us to more concisely express repetitive examples through the use of a template with placeholders.

Graticule computes NULL distance for some records (and how to fix that)

The SQL code generated by Graticule's spherical distance computation is insufficient and can lead to NULL distances in edge cases.

The reason for this is that MySQL is performing several sine and cosine computations which can result in slight rounding errors -- which is usually okay. Rarely, though, for the exact center of the given circle, it is then asked to compute the arc cosine of a result like 1.0000000001.

Since this i...

ActsAsTaggableOn: Cache tag lists

For performance improvements (and to remove the need for eager loading), the ActsAsTaggableOn gem supports caching your tag lists directly in your model. To enable this, simply add a cached_tag_list column to your table.

Example:

class Company < ActiveRecord::Base
  acts_as_taggable_on :categories
end

The cache column has to be named cached_category_list.

Existing data

If you already have existing data, you have to save all records with tags once, after you've added the ...

Error "execution expired (Timeout::Error)" when using Selenium and Webmock

If you get the above error when running tests in bulk (but not individually), it's actually the fault of Webmock.

Updating Webmock to version 1.7+ fixes this.

Find geocoded records that are close to a location (radius search)

When you have objects in your database that hold latitude and longitude and you want to find others that are close to given coordinates you can use the Graticule gem.

Graticule

Graticule offers several methods to compute the distance between two geo-dated objects but fetching records from the database that are within a given radius of a location is a bit trickier:

def close_destinations(latitude, longitude)
  distance_sql = Graticule::Distance::Spherical.to_sql(:latitude => l...

"Require group" doesn't work with Ubuntu's default Apache installation

If you want to use Require group $GROUPNAME on your default Apache installation like this:

<Directory "/var/www/foobar">
    Order allow,deny
    Allow from all
    Options None
    AllowOverride all
    AuthName "Area 51"
    AuthType Basic
    AuthBasicProvider external
    AuthExternal pwauth
    Require group admin
</Directory>

You need to first install libapache2-mod-auth-sys-group. You don't get any error message if you haven't installed it but it doesn't work.

sudo apt-get install...

Declare different CSS background-images for different locales

If you would like to use language specific layout (e.g. background-images) in your applications stylesheets you can achieve this easily by using the lang attribute in your views (ERB):

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= I18n.locale || 'en' %>" lang="<%= I18n.locale || 'en'%>">
...
</html>

or in HAML:

%html :xmlns => "http://www.w3.org/1999/xhtml", :"xml:lang" => I18n.locale || 'en', :lang => I18n.locale || 'en'

Then, in your stylesheet you can for example declare different background-images fo...

How to manage Thunderbird mailing lists

You can group contacts using a mailing list in Thunderbird for easier access and less trouble when trying to find out who to send a message to. Here is how to do this:

  1. Open your Thunderbird address book
  2. Press the "New List" button
  3. Choose a name for your list and add contacts. There will be auto completion from your address book.

When sending e-mails you can now add a recipient with the mailing list's name and the e-mail will be sent to all its members.

Preparing your test database: mind the differences

Instead of running all missing migrations on your test database with rake db:migrate RAILS_ENV=test you can also use a handful of rake tasks to prepare the database structure directly. They can produce different results, though.

In a nutshell, to ensure your test database gains the correct structure:

  • Don't use rake db:test:prepare carelessly
  • or use rake db:test:clone_structure ← preferred :)
  • or use rake db:migrate RAILS_ENV=test and don't mix it with other ways, like some of the rake tasks.

rake db:test:prepare
------------...

state_machine: Test whether an object can take a transition

When using state_machine you sometimes need to know whether an object may execute a certain transition. Let's take an arbitrary object such as a blog article as an example that has those states:

A -> B -> C -> D

Additionally, you have transitions between the states as shown above. Let's call the transition between 'A' and 'B' transition_ab for simplicity. \
Given an object in state 'A'. You can call object.transition_ab but calling object.transition_bc! will obviously fail because ...

Login forms: Disable browser prompt to remember the password

In order to prevent the browser from asking whether to remember the password, give a form an autocomplete attribute with the value off:

<form "/session" method="post" autocomplete="off">
  ...
</form>

Rails example

form_for @model, :html => { :autocomplete => "off" } do |form|

Ruby: Downloading files from the Internet

This is easy:

require 'open-uri'

File.open('/target/path/to/downloaded.file', "wb") do |file|
  file.write open('http://example.com/your.file').read
end

Basic Authentication

When your file is protected by HTTP Basic Authentication, pass your credentials as hash:

File.open('/target/path/to/downloaded.file', "wb") do |file|
  file.write open('http://example.com/your.file', :http_basic_authentication => [your_username, your_password]).read
end

Rails 3.1 error message: Could not find a JavaScript runtime

After starting the Rails server in a freshly generated Rails 3.1 project you could see an error message such as

/usr/lib/ruby/gems/1.8/gems/execjs-1.3.0/lib/execjs/runtimes.rb:50:in `autodetect': Could not find a JavaScript runtime. See https://github.com/sstephenson/execjs for a list of available runtimes. (ExecJS::RuntimeUnavailable)

Just add a JavaScript runtime to your Gemfile and the error vanishes.

Examples:

gem 'therubyracer'
gem 'extjs'

MySQL: Do not use "WHERE id IN (SELECT ....)"

Note: This applies specifically to MySQL. In PostgreSQL for example, this is not an issue.

If you care about performance, never use a query like

UPDATE users SET has_message = 1 WHERE users.id IN (SELECT user_id FROM messages)

MySQL does not optimize this and seems to scan the temporary table, which isn't indexed, for every row in the update statement. This applies to other statements than UPDATE as well.

Instead, either use a JOIN like

UPDATE users INNER JOIN messages ON messages.user_id = users.id SET has_message =...

Change the MySQL default character set on Amazon Relational Database Service (RDS)

Look here for informations how you can show the MySQL default character set.

At first you need the Amazon RDS Command Line Toolkit

  • download and unzip the [Amazon RDS Command Line Toolkit](http://aws.amazon.com/developertools/A...

How to use html_safe correctly

By default, Rails views escape HTML in any strings you insert. If you want to insert HTML verbatim, you need to call #html_safe. However, #html_safe does not "unescape" a string. It merely marks a string as safe for unescaped insertion.

How html_safe works

Calling html_safe on a String returns a new object that looks and acts like a String, but actually is a ActiveSupport::SafeBuffer:

"foo".length
# => 3
"foo".class
# => String

"foo".html_safe.length
# => 3
"foo".html_safe.class
# => ActiveSupport::S...

Cucumber.yml was found, but could not be parsed.

If you encounter the error message above when running cucumber, just execute...
rm rerun.txt
...in the Rails directory.

Or run...
tests
...from the geordi gem. This will do the work for you automatically.