Setting up mocha with sinon and chai

I was unable to quickly find a solution for this, so here’s a little guide on how to set it up together in a proper way.

First, install the libraries:

npm install mocha --save-dev
npm install sinon --save-dev
npm install chai --save-dev

I come from the Ruby world, so I expect to have a spec command, spec_helper.js file and specs living inside spec/ directory (with a nested structure).

Inside package.json file define the spec command:

"scripts" : {
  "spec": "mocha --opts spec/mocha.opts"

We will be using BDD style (expect().to()) of chai. Inside spec/mocha.opts add:

--recursive **/*_spec.js
--require spec/spec_helper.js
--ui bdd

Create spec/spec_helper.js, which will require chai and sinon and we will require `spec_helper.js` inside all specs (similarly to how RSpec in Ruby world works).

const sinon = require('sinon');
const expect = require('chai').expect

global.sinon = sinon;
global.expect = expect;

And now create your spec file (spec/module_spec.js). You should not be required to include any libraries there. Now you can run your specs:

npm run spec


Writing NullObject in Ruby to please Rubocop gods

Lets get right to it. Here’s how one can write a NullObject in a modern, Rubocop-friendly manner:

class NullObject
  def method_missing method, *args, &block
    if respond_to? method

  def respond_to_missing? _name, _include_private = false

One of the things you should support is the fallback to super. I achieve that by the if/else block. In practice super is never reached, so this feels a little bit like a waste.

The other thing is to declare whether your object (NullObject) should respond to methods it doesn’t have. A true null object should respond to all methods, so I set respond_to_missing? to true.

Just for posterity, here’s how you could write specs for it:

describe NullObject do
  it 'returns nil for any method call' do
    null =

    expect(null.missing_method).to be_nil
    expect(null.something_other_missing_method(1, 2, 3)).to be_nil

  it 'responds to missing methods' do
    null =

    expect(null.respond_to?(:missing_method)).to be true

Additional reading about the NullObject pattern:


Run Rails 2.3 application using Ruby 2.1

There is a way to have your old Rails 2.3.something application running using latest Ruby from the 2.1 branch. However, it is moderately complex and requires quite a few hacks. Not everything works perfect with this setup, though. Common exceptions are performance tests and some of the generators, but I regard those as minor annoyances.

I’m using 2-3-stable branch of Rails, which means version 2.3.18 plus some additional unreleased patches on top of it and a recently released Ruby 2.1.8.

This guide assumes that you are using Bundler to manage your gems. If not, please follow this guide first.


gem 'rails', :github => 'rails/rails', :branch => '2-3-stable'
gem 'rake'
gem 'json'
gem 'iconv'

group :test do
  gem 'test-unit', '1.2.3'

And then:

$ bundle update rails rake json iconv test-unit


Remove the following line:

require 'rake/rdoctask'


Change the following block after rescue Gem::LoadError => load_error to look like this:

if load_error.message =~ /Could not find RubyGem rails/
  STDERR.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
  exit 1


Update your Ruby version used for Capistrano deployments. Only if you’re using Capistrano with RVM.

set :rvm_ruby_string, '2.1.8'


Change hardcoded Rails version:

RAILS_GEM_VERSION = '2.3.18' unless defined? RAILS_GEM_VERSION

Before block add the following:

# Rails 2.3 and Ruby 2.0+ compatibility hack
if RUBY_VERSION >= '2.0.0'
  module Gem
    def self.source_index

    def self.cache

    SourceIndex = Specification

    class SourceList
      # If you want vendor gems, this is where to start writing code.
      def search(*args); []; end
      def each(&block); end
      include Enumerable

Additional initializers


# ActiveRecord::Callbacks compatibility fix

module ActiveRecord
  module Callbacks


    def callback(method)
      result = run_callbacks(method) { |result, object| false == result }

      # The difference is here, the respond_to must check protected methods.
      if result != false && respond_to_without_attributes?(method, true)
 result = send(method)


      return result


# Encoding issues with Ruby 2+
# backport #3937 to Rails 2.3.8

class ERB
  module Util
    def html_escape(s)
      s = s.to_s
      if s.html_safe?
        silence_warnings { s.gsub(/[&"'><]/n) { |special| HTML_ESCAPE[special] }.html_safe }


# Patch to make i18n work with Ruby 2+

module I18n
  module Backend
    module Base
      def load_file(filename)
        type = File.extname(filename).tr('.', '').downcase

        raise, filename) unless respond_to?(:"load_#{type}", true)

        data = send(:"load_#{type}", filename) # TODO raise a meaningful exception if this does not yield a Hash

        data.each { |locale, d| store_translations(locale, d) }


# This is a very important monkey patch to make Rails 2.3.18 to work with Ruby 2+
# If you're thinking to remove it, really, don't, unless you know what you're doing.

if Rails::VERSION::MAJOR == 2 && RUBY_VERSION >= '2.0.0'
  require 'rails_generator'
  require 'rails_generator/scripts/generate'

  Rails::Generator::Commands::Create.class_eval do
    def template(relative_source, relative_destination, template_options = {})
      file(relative_source, relative_destination, template_options) do |file|
        # Evaluate any assignments in a temporary, throwaway binding
        vars = template_options[:assigns] || {}
        b = template_options[:binding] || binding
        # this no longer works, eval throws "undefined local variable or method `vars'"
        # vars.each { |k, v| eval "#{k} = vars[:#{k}] || vars['#{k}']", b }
        vars.each { |k, v| b.local_variable_set(:"#{k}", v) }

        # Render the source file with the temporary binding, nil, '-').result(b)


# This is a very important monkey patch to make Rails 2.3.18 to work with Ruby 2+
# If you're thinking to remove it, really, don't, unless you know what you're doing.

if Rails::VERSION::MAJOR == 2 && RUBY_VERSION >= '2.0.0'
  module ActiveRecord
    module Associations
      class AssociationProxy
        def send(method, *args)
          if proxy_respond_to?(method, true)
            @target.send(method, *args)


# Set default encoding for everything coming in and out of the app
# TODO this could/should be removed when upgrading to Rails 3+
Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = Encoding::UTF_8


# convert all params into UTF-8 (from ASCII-8BIT)

raise "Check if this is still needed on " + Rails.version unless Rails.version == '2.3.18'

class ActionController::Base

  def force_utf8_params
    traverse = lambda do |object, block|
      if object.kind_of?(Hash)
        object.each_value { |o|, block) }
      elsif object.kind_of?(Array)
        object.each { |o|, block) }
    force_encoding = lambda do |o|
      o.force_encoding(Encoding::UTF_8) if o.respond_to?(:force_encoding)
    end, force_encoding)
  before_filter :force_utf8_params



Installing Ruby 1.8.7-head for chruby using ruby-build on OS X 10.11 (El Capitan)

Unfortunately ruby-install won’t let you install Ruby version 1.8.7 any more. Here’s how to install it using ruby-build so that it could still be used by chruby:

brew install ruby-build
brew install openssl libyaml libffi
brew install apple-gcc42
brew install openssl098
  # dependencies

mkdir -p ~/.rubies
  # if doesn't exist

brew link openssl098 --force
  # 1.8.7 requires OpenSSL 0.9.8 (or lower)

ruby-build 1.8.7-p375 ~/.rubies/ruby-1.8.7
  # compile 1.8.7-head (p375 is the same as HEAD)

brew unlink openssl098
  # revert symlinking

chruby 1.8.7
  # switch to 1.8.7

Chruby with Phusion Passenger

This guide will tell you how to use chruby together with Phusion Passenger.

What we want to achieve is automatic Ruby version switching in Passenger based on the Ruby used by the project.

I’m using zsh, but with small modifications it should also work with bash or any other shell type.


  • latest chruby
  • latest Passenger
  • .ruby-version file present in each app/project

The gist of it is that you need a chruby wrapper script, which will be executed separately for each project by Passenger. Place it in ~/bin or at any other place where you keep your local binaries:


# Wrapper for chruby to work with Phusion Passenger
# Based on:

source /usr/local/share/chruby/
source /usr/local/share/chruby/


# original call
exec "ruby" "$@"

After that you need to configure Passenger to make use of this script. I’m on OS X, so the file I’m editing is at /etc/apache2/other/passenger.conf:

# chruby wrapper for Passenger use
PassengerDefaultRuby /Users/<your-username>/bin/chruby-wrapper

# Passenger must read ENV variables for the chruby-wrapper script to work
PassengerLoadShellEnvvars on

# Run Passenger application instance as your current user
PassengerUserSwitching on

That’s it! Good luck!


Testing database transactions explicitly with RSpec

TL;DR; you cannot do it reliably with RSpec.

The long story goes like this. Lets say you have a code executing an AR rollback when something fails:

def call
  Model.transaction do

    unless send_notification
      raise ActiveRecord::Rollback

This update_reason is a block of code, which does some database operation, like an INSERT or UPDATE:

def update_reason
  object.update reason: reason

And send_notification is just some external API call.

So when you write a spec for this code, you might want to write something like this:

describe '#call' do
  it 'does not update the reason when sending the notification fails' do
    allow(object).to receive(:send_notification).and_return false
    expect {
    }.not_to change(object, :reason)  

And, surprise, surprise, the above spec will fail! The `reason` will change on the object, even though the logic says it should not.

Why is that? This is because normally you have your whole example spec wrapped in a transaction and rolled back after the example has been run. Since your code opens up a new, nested transaction internally (with the #call method: Model.transaction do). This messes things up and now the rollback in the nested transaction does not really roll back anything. Adding require_new: true doesn’t help. Disabling transaction just for this one spec does not work either. Unfortunately.

Something like this works, but it’s not ideal:

expect {
}.to raise_exception ActiveRecord::Rollback  

Additional reading:

* How to test that a certain function uses a transaction in Rails

A deep_reject method for hashes in Ruby

Recently, while adding missing functionality for the i18n-js gem I’ve stumbled into a problem. I needed to have a method to “deep reject” keys in the hash. There are some examples in the wild doing that, but they all solve this problem by adding a new method to the Hash class. I wanted a generic method, which would take the hash as an argument.

After some head scratching, tinkering and tweaking, I’ve come up with a correct solution (at least I think it’s correct). Here it is:

def self.deep_reject(hash, &block)                                                   
  hash.each_with_object({}) do |(k, v), memo|                                        
    unless, v)                                                          
      if v.is_a?(Hash)                                                               
        memo[k] = deep_reject(v, &block)                                             
        memo[k] = v                                                                  

You use it like this:

hash = {:a => {:b => 1, :c => 2}}

result = deep_reject(hash) { |k, v| k == :b }

result # => {:a => {:c => 2}}

Enabling I18n locale fallbacks in Rails

This guide is valid for i18n version 0.7.0+ and Rails 4.1+

Strangely enough enabling custom locale fallbacks is harder than it should be. Here’s what you need to enable custom locale fallbacks with i18n gem.

First, you need to set config.i18n.fallbacks = true for all environments in a Rails application (config/environments/*.rb).

Then you need to have this in your config/application.rb:

# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
config.i18n.default_locale = :en

# Enforce available locales
config.i18n.enforce_available_locales = true

# Custom I18n fallbacks
config.after_initialize do
  I18n.fallbacks = :"de-DE", ch: :"de-DE", gb: :"en-US")

The above will enable custom fallbacks from at and ch locales to the German language and from gb locale to English. The enforce_available_locales bit is optional.

If you also use i18n-js to have your translated phrases available in javascript, here’s the exemplary fallbacks snippet you need to put inside your javascript code:

I18n.locales["at"] = ["de", "en"]
I18n.locales["ch"] = ["de", "en"]
I18n.locales["gb"] = ["en"]

Testing CSRF protection in Rails

Ever wanted to test your CSRF protection in a Rails app? For example, in a situation when you have a custom “remember me” cookie set and you need to overwrite Rails’ handle_unverified_request to clear it so it does not open a big security hole in your app? I know I did and it took me a while to find out how to do that, so I figured it would be good to write about it.

Here’s how to do it (in Test::Unit, but it’s the same for RSpec):

setup do                                                           
  # Enable CSRF protection in this test                            
  ActionController::Base.allow_forgery_protection = true           
teardown do                                                        
  # Disable CSRF protection for all other tests                    
  ActionController::Base.allow_forgery_protection = false          

Adding the above will make it so that the authenticity_token is added to each generated <form> element and will be required to be sent with each non GET request.