Rails 3.1 gives you free down migrations

In Rails 3.1+, instead of defining a separate up and down method you can define a single method change:

class AddComparisonFieldsToReport < ActiveRecord::Migration
  def change
    add_column :reports, :compare, :boolean
    update "UPDATE reports SET compare = #{quoted_false}"
    add_column :reports, :compare_start_date, :date
    add_column :reports, :compare_end_date, :date
  end
end

Migrating up works as expected:

b rake db:migrate
==  AddComparisonFieldsToReport: migrating ====================================
-- ad...

Mysql/Mysql2 agnostic database.yml

If you upgrade to the mysql2 gem, you will run into the problem that the server's database.yml (which is usually not under version control) needs to change exactly on deploy.

You can however make your database.yml work for mysql and mysql2 at the same time. Simpy do this

production:
   adapter: <%= defined?(Mysql2) ? 'mysql2' : 'mysql' %>
   #...

Solve Flash performance issues in Ubuntu

The linked article describes how to use a Firefox addon "Flash-Aid" to install a better build of Flash and apply some optimizations.

With this I can now properly watch fullscreen HD videos under Ubuntu.

Geordi: Use load-dump script to source a database dump into your database

This script loads a dump into your development database.

You can provide the full path to you database dump like this:

load-dump path/to/my.dump

When you call load-dump without any arguments it will show a menu with all dumps in your ~/dumps/ folder.

load-dump

This script is part of our geordi gem on github.

Rails asset pipeline: Why relative paths can work in development, but break in production

The problem

When using the asset pipeline your assets (images, javascripts, stylesheets, fonts) live in folders inside app:

app/assets/fonts
app/assets/images
app/assets/javascripts
app/assets/stylesheets

With the asset pipeline, you can use the full power of Ruby to generate assets. E.g. you can have ERB tags in your Javascript. Or you can have an ERB template which generates Haml which generates HTML. You can chain as many preprocessors as you want.

When you deploy, Rails runs assets:precompile...

Loading half a billion rows into MySQL

Some advice for bulk loading many records into InnoDB and finishing before the sun burns out. Use with care.

IE-friendly mobile-first CSS with Sass 3.2

Building CSS mobile-first is the way forward, because blah blah blah progressive enhancement blah. Problem is, Internet Explorer prior to 9 ignores anything within media query blocks, leaving those browsers with mobile styles.

Not all of us can get away with that, but thankfully, as Chris Eppstein points out, Sass 3.2 (not yet released) can generate a separate stylesheet with everything it needs to create a "desktop" look.

This page was built mobile-first where smaller width devices get a single column layout, but IE8 and below still get a...

How could it be that my database.yml disappears?

Probably was in the repository once and got deleted in a commit that you pulled.

Plotting graphs in Ruby with Gruff

Geoffrey Grosenbach has created Gruff for easily plotting graphs. It is written in pure Ruby and integrates with Rails applications.

It provides features as automatic sizing of dots and lines (the more values, the thinner the graph's elements), custom or predefined themes, different styles (bar, line, dot and many more) and multiple graphs in one chart.

Installation

In your Gemfile:

gem 'rmagick', :require => false
gem 'gruff'

Then run bundle install (and don't forget to restart your development server.)

Usage

This i...

The Ruby Toolbox – a collection of good gems

If you need a gem for a certain purpose, be sure to check this site.


The rankings are determined by counting up the number of forks and watchers of various github projects, so I'd view it less as "this is what I should be using," and more as "these are some things I should check out." At the very least, they're all likely to be under active development and fairly up to date, and it's very useful to see groups of gems broken down by category.

Guide to localizing a Rails application

Localizing a non-trivial application can be a huge undertaking. This card will give you an overview over the many components that are affected.

When you are asked to give an estimate for the effort involved, go through the list below and check which points are covered by your requirements. Work with a developer who has done a full-app localization before and assign an hour estimate to each of these points.

Static text

  • Static strings and template text in app must be translated: Screens, mailer templates, PDF templates, helpe...

MySQL 5.1: Switch to InnoDB Plugin for better performance

MySQL version 5.1 comes with an alternative, faster InnoDB implementation (called "InnoDB Plugin").

Switching is easy:

  • Stop your mysqld with sudo stop mysql
  • Add the following lines to your /etc/mysql/my.cnf under the [mysqld] section
    ignore-builtin-innodb
    plugin-load=innodb=ha_innodb_plugin.so
  • Start your mysqld with sudo start mysql

The file format has not changed, your tables should survive this.

Note: This is not necessary in MySQL 5.5, where the new implementation is the default.

How to use pessimistic row locks with ActiveRecord

When requests arrive at the application servers simultaneously, weird things can happen. Sometimes, this can also happen if a user double-clicks on a button, for example.

This often leads to problems, as two object instances are modified in parallel maybe by different code and one of the requests writes the results to the database.

In case you want to make sure that only one of the requests "wins", i.e. one of the requests is fully executed and completed while the other one at least has to wait for the first request to be completed, you ha...

When using time zones, beginning_of_day / end_of_day is broken in Rails 2 for any Date or DateTime

Using beginning_of_day or end_of_day on Date or DateTime objects in Rails 2.x applications will never respect time zones, which is horrible.\
This is fixed in Rails 3, though.

Even when using Date.current or DateTime.current you will get regular Time or DateTime objects:

>> Date.current.beginning_of_day.class
=> Time # not a ActiveSupport::TimeWithZone as expected
>> DateTime.current.beginning_of_day.class
=> DateTime ...

salesking/king_dtaus

DTAUS & DTAZV are formats for German bank transfers and is short for "Datenträgeraustausch". The format itself totally sucks because it was established in the last century, to be used on floppy disks. Still almost all German banks use it (they only seem innovative at robbing), and it is therefore supported in common banking programs too.

This gem saves you all the trouble when generating DTAUS- or DTAZV-text.

Why has_many :through associations can return the same record multiple times

An association defined with has_many :through will return the same record multiple times if multiple join models for the same record exist (a n:m relation). To prevent this, you need to add ->{ uniq } as second argument to has_many (below Rails 4 it is a simple option: has_many :xyz, :uniq => true).

Example

Say you have an Invoice with multiple Items. Each Item has a Product:

class Invoice < ActiveRecord::Base
  has_many :items
  has_many :products, :through => :items
end

class Item < ActiveRecord::Base
  ...

Validate attachment presence using paperclip

Make sure you call the methods in the following order and not vice versa:

has_attached_file :image
validates_attachment_presence :image

Validation with condition works fine, too:

validates_attachment_presence :image, :if => :method

This is because validates_attachment_presence is only available after saying has_attached_file.

Shell script to deploy changes to production and not shoot yourself in the foot

Geordi, our collection of command line tools, has been extended by another command deploy-to-production. This script encapsulates the following workflow:

  • Pull the production branch.
  • Show which commits from the master would make it to production with this deploy.
  • Ask if you want to proceed.
  • If yes, merge the master into the production branch, push and deploy with bundle exec cap production deploy:migrations

The script will ask you for the names of your master branch, production branch an...

validates_acceptance_of is skipped when the attribute is nil

validates_acceptance_of :terms only works if terms is set to a value. The validation is skipped silently when terms is nil.

While this behavior is useful to validate acceptance in the frontend and not the admin backend, it also makes it very easy to unintentionally skip the validation altogether by forgetting to add the checkbox to a form. E.g. validates_acceptance_of :terms_with_typo will be skipped silently even if there is no column with t...

Change how Capybara sees or ignores hidden elements

Short version

  • Capybara has a global option (Capybara.ignore_hidden_elements) that determines whether Capybara sees or ignores hidden elements.
  • Prefer not to change this global option, and use the :visible option when calling page.find(...). This way the behavior is only changed for this one find and your step doesn't have confusing side effects.
  • Every Capybara driver has its own notion of "visibility".

Long version

Capybara has an option (Capybara.ignore_hidden_elements) to configure the default...

Customize path for Capybara "show me the page" files

When you regularly make use of Cucumber's "show me the page" step (or let pages pop up as errors occur), the capybara-20120326132013.html files will clutter up your Rails root directory.

To tell Capybara where it should save those files instead, put this into features/support/env.rb:

Capybara.save_and_open_page_path = 'tmp/capybara'

Fix [RubyODBC]Cannot allocate SQLHENV when connecting to MSSQL 2005 with Ruby 1.8.7. on Ubuntu 10.10

I followed this nice guide Connecting to MSSQL with Ruby on Ubuntu - lambie.org until I ran in the following errors:

irb(main):001:0> require "dbi"; dbh = DBI.connect('dbi:ODBC:MyLegacyServer', 'my_name', 'my_password')

DBI::DatabaseError: INTERN (0) [RubyODBC]Cannot allocate SQLHENV
  from /usr/lib/ruby/1.8/dbd/odbc/driver.rb:36:in `connect'
  from /usr/lib/ruby/1.8/dbi/handles/driver.rb:33:in `connect'
  from /usr/lib/ruby...