Bulk-change multiple table rows in a migration

Using rename_column, remove_column, etc. more than once in a migration makes that migration run slower than it should. Use change_table instead.

Consider this migration:

add_column :users, :name, :string
remove_column :users, :first_name
remove_column :users, :last_name
rename_column :users, :cool, :awesome

Migrating in this case means that all those commands are processed step by step, causing 4 SQL statements to change the table. In turn, your database needs to modify the table structure 4 times. When working on hu...

Rails ERD – Entity-Relationship Diagrams for Rails

Gem to generate entity relationship diagrams from your Rails 3 ActiveRecord models. The diagram style is pretty and configurable.

Ubuntu 11.10: Playing sound over front and back panel (or headphones and speakers) at once

I have a pair of headphones connected to my desktop's back panel and a headset connected to the front panel. I used to play sound over both outputs, but this suddenly stopped working this week.

Apparently, (perhaps through some update) "jack sensing" got turned on, which disables the back panel as soon as you connect something to your front panel audio jack.

To disable this feature, I used alsamixer (use the arrow keys to navigate right to "auto mute", and disable with the up key). For some reason the corresponding checkbox in the `gnome...

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

How to ignore new files or changed files in git

How to ignore new files

Globally

Add the path(s) to your file(s) which you would like to ignore to your .gitignore file (and commit them). These file entries will also apply to others checking out the repo.

Locally

Add the path(s) to your file(s) which you would like to ignore to your .git/info/exclude file. These file entries will only apply to your local working copy.

How to ignore changed files (temporarily)

In order to ignore changed files to being listed...

How to define a custom context menu within HTML (Firefox 8+)

Since Firefox 8 it is possible to define custom context menus (right clicking) with HTML markup.

Configuration for Rails, the Right Way

I still see people promoting various gems and plugins to handle miscellaneous configuration elements for your application. One little known secret is that Rails 3 allows you to define your own configuration elements trivially.

Create a new gemset with RVM

To use different Ruby versions on your computer you can use the Ruby Version Manager. It also allows you to pack different gemsets for each of your applications. In order to create on of those just type ...

rvm use 1.8.7-p323@makandra_project_xy --create

This command creates and switches to the newly created gemset.

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.

Excel files can't hold more than 65535 rows per worksheet

"Classic" Excel (XLS) has a magic limit of 65535 rows per worksheet. This was fixed in XLSX but the version used by the Spreadsheet gem can only write XLS files.

If you want to write more data, consider hacking around it using in_groups_of and writing multiple column sets of your data (i.e. split 1 block of 3 columns and 100000 rows into 4 blocks of 3 (12 in total) columns and 25000 rows).

You can do this until you reach the other limit of 256 columns. After that, open up a new workbook or consider a ...

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

Run a script on the server

You have to specify the environment with -e env_name or RAILS_ENV=env_name if you want to run a script on the server.

at Rails 2 it's script/runner

bundle exec script/runner -e env_name path/to/script.rb argument1 argument2 ...

at Rails 3 it's rails runner

RAILS_ENV=env_name bundle exec rails runner path/to/script.rb argument1 argument2 ...

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

See with tig which git commits touch a file or files or folders

tig path_to_file_or_files_or_path_with_wildcard

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|

Large forms are slow on the iPad

  • Forms with many inputs (600+ in my case) become extremely unresponsive on an iPad, up to the point where it can take several seconds for a control to respond to touch commands.
  • This is true for both iPad 1 and iPad 2 models.
  • While certain CSS styles can lead to performance issues, removing those styles won't help if the form simply is very large.
  • A workaround is to only show a limited number of form inputs at the time, e. g. by toggling groups of form...

Be careful with "memoize"

ActiveSupport's memoize has a dangerous feature you might not know about.

Assume you have

class DeepThought
  extend ActiveSupport::Memoizable

  def life_universe_and_everything
     # some lengthy calculation returning 42
  end
  memoize :life_universe_and_everything
end

Then #life_universe_and_everything will of course cache the result after calculating it once. However, you can trigger a recalculation by calling #life_universe_and_everything(true).

If, however, your method looks like

de...

jQuery 1.7 Released

Two new methods on and off are the new way of declaring event handlers. bind, delegate and live area deprecated. Also better performance for delegated events.

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

Multi-line Ruby block in Haml

There are several options, but most of them are impractical. The best way is to use the :ruby filter:

:ruby
  puts javascript_include_tag(
    'lib/jquery-1.6.1.min.js',
    'lib/jquery-rails-ujs.js',
    'lib/jquery-ui-1.8.13.custom.min.js',
    'lib/jquery.ui.datepicker-de.js',
    'lib/jquery-ui-timepicker-addon.min.js',
    'lib/jquery.tools.min.js',
    'application.js',
    'google-maps.js',
    :cache => true
  )

...