Joined environment file for production and staging

Often production and staging share much, so why not use a common file for that…

#config/environments/production.rb and config/environments/staging.rb
eval(File.read("#{File.dirname(__FILE__)}/production_like.rb"))
...environment specific code ...

#config/environments/production_like.rb
config.cache_classes = true
...

the File.read/eval is rather hacky, but works nevertheless 😉

Hash values through query like nested keys

How to get “x[y][z]” out of a hash ?

This made life with our form helpers a lot easier, since they take normal or nested keys <-> name of the input and prefilled value through params.

Any alternative is appreciated, since its pretty complex/hacky, the name is weird too …
(a simple to_query.split(‘=’)).inject… can work too, but would stringify all values and keys)

Usage

{'x'=>{'y'=>{'z'=>1}}}.value_from_nested_key('x[y][z]') == 1

Code

class Hash
  # {'x'=>{'y'=>{'z'=>1}}.value_from_nested_key('x[y][z]') => 1
  def value_from_nested_key(key)
    if key.to_s.include?('[')
      match, first, nesting = key.to_s.match(/(.+?)\[(.*)\]/).to_a
      value = self[first]
      nesting.split('][').each do |part|
        return nil unless value.is_a?(Hash)
        value = value[part]
      end
      value
    else
      self[key]
    end
  end
end

unrename and unrename_column for ActiveRecord

Instead of flipping values around by hand and possibly making mistakes, simply put an ‘un’ before them

Usage

class RenameStuff < ActiveRecord::Migration
  def self.up
    rename_column :users, :username, :login
    rename_column :users, :e_mail, :email
  end

  def self.down
    # simply cody and add 'un'
    unrename_column :users, :username, :login
    unrename_column :users, :e_mail, :email
  end
end

Code

# convenience method, so that rename statements do not need to be reversed by hand
class ActiveRecord::ConnectionAdapters::Table
  def unrename(a,b)
    rename b,a
  end
end
module ActiveRecord::ConnectionAdapters::SchemaStatements
  def unrename_column(table_name, a, b)
    rename_column(table_name, b, a)
  end
end

Fixing MemCache IO timeout for memcache-client

A simple hack to get no more memcache timeouts in production.
You should add some kind of error notification above the ‘nil’ line, to know that memcache is no longer behaving properly.
(If it does not work, check if MemCache.new.cache_get_with_timeout_protection is defined -> load the hack in after_initialize)

code

class MemCache
  def cache_get_with_timeout_protection(*args)
    begin
      cache_get_without_timeout_protection(*args)
    rescue MemCache::MemCacheError => e
      if e.to_s == 'IO timeout' and (Rails.env.production? or Rails.env.staging?)
        nil
      else
        raise e
      end
    end
  end
  alias_method_chain :cache_get, :timeout_protection
end

try it

start script/console
kill -s STOP memcache-pid
try reading from cache in console
kill -s CONT memcache-pid

validates_uniqness_of + mysql == SLOW

ActiveRecord`s validate_uniqueness_of produces evil SQL that will not use your existing index!

Before:
SELECT `users`.id FROM `users` WHERE `users`.`email` = BINARY ‘my@email.com’ AND `users`.id 1234) LIMIT 1; –> 0.80s

After:
SELECT `users`.id FROM `users` WHERE `users`.`email` = ‘my@email.com’ AND `users`.id 1234) LIMIT 1; –> 0.00s

Hack to make AR use faster queries on the cost that no case-sensitive queries can be made anymore.

# validates_uniqueness_of produces "column = BINARY 'text'" queries
# which will not use existing indices, so we add this 
# EVIL HACK to make 
# ALL validates_uniqueness_of in-case-sensitive
class ActiveRecord::ConnectionAdapters::MysqlAdapter
  def case_sensitive_equality_operator
    "="
  end
end