Rails 5

ActiveModel::Type::Boolean.new.cast('t')     # => true
ActiveModel::Type::Boolean.new.cast('true')  # => true
ActiveModel::Type::Boolean.new.cast(true)    # => true
ActiveModel::Type::Boolean.new.cast('1')     # => true
ActiveModel::Type::Boolean.new.cast('f')     # => false
ActiveModel::Type::Boolean.new.cast('0')     # => false
ActiveModel::Type::Boolean.new.cast('false') # => false
ActiveModel::Type::Boolean.new.cast(false)   # => false
ActiveModel::Type::Boolean.new.cast(nil)     # => nil

source:

Rails 4.2

ActiveRecord::Type::Boolean.new.type_cast_from_database(value)

source

Rails 4.1 and bellow

ActiveRecord::ConnectionAdapters::Column.value_to_boolean 'f'  # => false
ActiveRecord::ConnectionAdapters::Column.value_to_boolean 't'  # => true
ActiveRecord::ConnectionAdapters::Column.value_to_boolean '0'  # => false
ActiveRecord::ConnectionAdapters::Column.value_to_boolean '1'  # => true
ActiveRecord::ConnectionAdapters::Column.value_to_boolean nil  # => false

source

Why do you need to know about this ?

The thing is "false" String is not the same as false Boolean. String "false" is actually truthy value:

expect("false").to be_truthy  # this will pass
expect(false).to be_falsey    # this will pass
expect("false").to eq false   # this will fail !

This is highly dangerouse as:

# app/controllers/stupid_controller.rb
class StupidController < ApplicationController
  def create
    user = User.create(email: params[:email])
    if params[:make_him_admin]
      user.make_him_an_admin!
    end

    render json: { result: 'ok' }
  end
end

Therefore if you submit:

{
  "email":"[email protected]",
  "make_him_admin": "false"
}

You will make him admin!

params['make_him_admin'] == "false" and "false" != false but it’s actually evaluated as a truthy value (non false and non nil means truthy) therefore that if statement pass !!

If you are expecting String values "false" "true" (or maybe "t","f", …) from outside input I highly recommend to convert them to boolean before you pass them to your code or store in DB

You should also consider doing this when:

  • before storing to JSON store (postgresql)
  • before rendering the value in JSON API
  • before you apply logic in your code
  • or if you are accepting checkbox value from Rails form helper
  • Etc…

Discussion