Using Arel to Compose SQL Queries

Arel is a library that was introduced in Rails 3 for use in constructing SQL queries. Every time you pass a hash to where, it goes through Arel eventually. Rails exposes this with a public API that we can hook into when we need to build a more complex query.

[Openstack] "Failed to schedule_prep_resize: No valid host was found." when trying to resize an instance

If you get this error while trying to resize an openstack instance:

# nova resize fooinstance 16 --poll

==> /var/log/nova/nova-scheduler.log <==
2014-01-30 17:40:34 WARNING nova.scheduler.manager [req-aaaaaaa-bbbb-cccc-dddd-1ed34b64adef bajd7394hftgs71dba31d642342effa0f bfe2djhg6538sg384jgb82ks070ce0b] Failed to schedule_prep_resize: No valid host was found. 
2014-01-30 17:40:34 WARNING nova.scheduler.manager [req-aaaaaaa-bbbb-cccc-dddd-1ed34b64adef bajd7394hftgs71dba31d642342effa0f bfe2djhg6538sg384jgb82ks070ce0b] Setting ...

Bash: Setting the title of your terminal tab

If your terminal has many tabs, you'll want to keep them organized. To change their title from the prompt, run this function:

function tab_title {
  if [ -z "$1" ]
  then
    title=${PWD##*/} # current directory
  else
    title=$1 # first param
  fi
  echo -n -e "\033]0;$title\007"
}

Put it into your ~/.bashrc to have it always available. Adjust to your needs.

Usage

$> tab_title
# title set to the current directory's name
$> tab_title new_title
# title set to "new_title"

Auto-setting the title
=================...

How to load only a subset of a massive MySQL dump

I had a huge MySQL dump that took forever (as in: days) to import, while I actually just wanted to have the full database structure with some data to use on my development machine.

After trying several suggestions on how to speed up slow MySQL dump imports (which did not result in any significant improvement), I chose to import just some rows per table to suffice my needs. Since editing the file was not an option, I used a short Ruby script to manage that.

Here is how:

pv huge.dump | ruby -e 'ARGF.each_line { |l| m = l.match(/^INSERT ...

Don't use "self" as a Javascript variable

You might sometimes use self to capture the context of this before it is destroyed by some function.

Unfortunately self is also an alias for window, the global top-level object. Save your future self some headaches and use another name like me instead (Coffeescript chose to use _this).

The new Modularity 2 syntax

We have released Modularity 2. It has many incompatible changes. See below for a script to migrate your applications automatically.

There is no does method anymore

We now use traits with the vanilla include method:

class Article < ActiveRecord::Base
  include DoesTrashable
end

When your trait has parameters, use square brackets:

class Article < ActiveRecord::Base
  include DoesStripFields[:name, :brand]
end

Note how you ...

Careful with '||=' - it's not 'memoize'

When you do something like this in your code:

def var_value
  @var ||= some_expensive_calculation
end

Be aware that it will run some_expensive_calculation every time you call var_value if some_expensive_calculation returns nil.

This illustrates the problem:

def some_expensive_calculation
  puts "i am off shopping bits!"
  @some_expensive_calculations_result
end

When you set @some_expensive_calculations_result to nil, ||= runs some_expensive_calculation every time....

Threads and processes in a Capybara/Selenium session

TLDR: This card explains which threads and processes interact with each other when you run a Selenium test with Capybara. This will help you understand "impossible" behavior of your tests.


When you run a Rack::Test (non-Javascript) test with Capybara, there is a single process in play. It runs both your test script and the server responding to the user interactions scripted by your test.

A Selenium (Javascript) test has a lot more moving parts:

  1. One process runs your test script. This is the process you...

Careful when writing to has_many :through associations

tl;dr: Using has_many associations with a :through option can lead to lost or duplicate records. You should avoid them, or only use them to read records.

Consider this:

class User < ActiveRecord::Base
end

class Party < ActiveRecord::Base
  has_many :invitations
  has_many :users, through: :invitations, include: :user, order: 'users.name'
end

class Invitation < ActiveRecord::Base
  belongs_to :party
  belongs_to :user
  
  after_create :send_invite
  
  def send_invite
  ...

Auto-coerced virtual attributes with Virtus

We've since created ActiveType which has a restricted subset of Virtus' features. It might be enough for your needs.

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

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

How to silence "I18n.enforce_available_locales" deprecation warnings

Before Rails 3.2.14, when supplying an invalid locale to I18n, it would fall back to its config.i18n.default_locale (which is :en by default). Eventually, this will be changed to raise an error by default -- for now, it shows a deprecation warning.

Since Rails 3.2.14 and 3.2.15 did not include security updates, you might not have applied them and probably now encounter these deprecation warnings after upgrading to 3.2.16 (or 4.0.2):

[deprecated] I...

Cancelling the ActiveRecord callback chain

Goal Within before_* Within after_*
Cancel later callbacks throw :abort throw :abort
Rollback the transaction throw :abort raise ActiveRecord::Rollback

When a callback raises an error

Exceptions raised in callbacks always rollback the transaction, but only exceptions that are not ActiveRecord::Rollback will bubble up to the caller.

Further readi...

howto fix spreewald issue „database configuration does not specify adapter (ActiveRecord::AdapterNotSpecified)“

This error occurs when you already have a database.yml which defines the database for the cucumber environment instead of test. (Spreewald database.sample.yml has changed)

Fix

Change cucumber to test in your databse.yml

test:    # <---
  adapter: mysql2
  database: spreewald_test
  encoding: utf8
  host: localhost
  username: root
  password: password

Whitelist Carrierwave attributes correctly

Say you have a User with a Carrierwave attribute #avatar:

class User < ActiveRecord::Base
  mount_uploader :avatar, AvatarUploader
end

When whitelisting the avatar field in the controller, you might do this:

params[:user].permit(:avatar)

But you probably want this:

params[:user].permit(:avatar, :avatar_cache, :remove_avatar)

In this example:

  • :avatar_cache allows a newly upload image to persist through form roundtrips in the case of validation errors (something that isn't possibl...

How to find out the type of a model's attribute

When you want to find out the data type of an attribute, you can just use ActiveRecord's columns_hash method.

It returns a hash of column objects that include a type attribute (and more database-related information).

Example:

Contract.columns_hash['id'].type
 => :integer
Contract.columns_hash['active'].type
 => :boolean
Contract.columns_hash['updated_at'].type
 => :datetime

Mysql collate, searching case sensitive

Usually our mysql queries are not case sensitive. In order to query case sensitive, you can use the mysql COLLATE clause.
The collate clause lets you specify a collation, which basically is a set of rules for comparing characters in a given character set.

The suffixes ci, cs, bin of a collation stand for case insensitive, case sensitive and binary, respectively. A binary collation such as utf8_bin is case sensitive as well since it compares the characters based on their numeric values.

SELECT * FROM use...

Your database tables should always have timestamps

Whenever you create a table from a database migration, remember to add updated_at and created_at timestamps to that table. Without those timestamps, investigating future bug reports will be hell. Always have timestamps.

Adding timestamps to new tables

When you create a table using create_table, you can add timestamps by using the timestamps shortcut:

class CreateEpisode < ActiveRecord::Migration
  def change
    create_table :episodes do |t|
      t.string :name
      t.timestam...

Carrierwave – Recreate versions

A snippet of the carrierwave documentation

You might come to a situation where you want to retroactively change a version or add a new one. You can use the recreate_versions! method to recreate the versions from the base file. This uses a naive approach which will re-upload and process the specified version or all versions, if none is passed as an argument.

Call recreate_versions! on a mounted uploader.

A common usecase

User.all.each { |user| user.avatar.r...

A simpler default controller implementation

Rails has always included a scaffold script that generates a default controller implementation for you. Unfortunately that generated controller is unnecessarily verbose.

When we take over Rails projects from other teams, we often find that controllers are the unloved child, where annoying glue code has been paved over and over again, negotiating between request and model using implicit and convoluted protocols.

We prefer a different approach. We believe that among all the classes in a Rails project, controllers are some of the hardest to...

How to not repeat yourself in Cucumber scenarios

It is good programming practice to Don't Repeat Yourself (or DRY). In Ruby on Rails we keep our code DRY by sharing behavior by using inheritance, modules, traits or partials.

When you reuse behavior you want to reuse tests as well. You are probably already reusing examples in unit tests. Unfortunately it is much harder to reuse code when writing integration tests with Cucumber, where you need to...

PostgreSQL vs. Rails migration: How to change columns from string to integer

When writing Rails migrations to convert a string column to an integer you'd usually say:

change_column :table_name, :column_name, :integer

However, PostgreSQL will complain:

PG::DatatypeMismatch: ERROR:  column "column_name" cannot be cast automatically to type integer
HINT:  Specify a USING expression to perform the conversion.

The "hint" basically tells you that you need to confirm you want this to happen, and how data shall be converted. Just say this in your migration:

change_column :table_name, :column_name, 'i...

ActiveRecord::StatementInvalid: Mysql2::Error: closed MySQL connection

I recently experienced the error ActiveRecord::StatementInvalid: Mysql2::Error: closed MySQL connection. Apparently this happens when there is a timeout during query execution. In order to fix this you can reconnect to your db.

Therefore either add reconnect: true to your database.yml for automatic reconnection when the error occurs or catch the error and manually and reconnect explicitly via ActiveRecord::Base.connection.reconnect!

Be aware that reconnecting will have the following impact on your current connection:

  • Any active tr...

How to change the locale of a PostgreSQL cluster

There may be reasons to change the locale of your Postgres cluster. A popular one is your development system's locale being used by default (which may be annoying). Here is how to do that.

Beware: By following the steps below, you will drop and recreate your cluster. You will lose all data (including roles). Instructions below include a procedure for dumping and restoring all cluster data (including roles). While it worked at the time of writing, you should have extra backup strategies for a production database.

  1. Find the cluster you...

PostgreSQL cheat sheet for MySQL lamers

So you're switching to PostgreSQL from MySQL? Here is some help...

General hints on PostgreSQL

  • \? opens the command overview
  • \d lists things: \du lists users, \dt lists tables etc

Command comparison

Description MySQL command PostgreSQL equivalent
Connect to the database mysql -u $USERNAME -p sudo -u postgres psql
Show databases SHOW DATABASES; \l[ist]
Use/Connect to a database named 'some_database' USE some_database; \c some_dat...