Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I submit a boolean parameter in Rails?

I'm submitting a parameter show_all with the value true. This value isn't associated with a model.

My controller is assigning this parameter to an instance variable:

@show_all = params[:show_all]

However, @show_all.is_a? String, and if @show_all == true always fails.

What values does Rails parse as booleans? How can I explicitly specify that my parameter is a boolean, and not a string?

like image 507
nfm Avatar asked Sep 09 '10 03:09

nfm


4 Answers

UPDATE: Rails 5:

ActiveRecord::Type::Boolean.new.deserialize('0')

UPDATE: Rails 4.2 has public API for this:

ActiveRecord::Type::Boolean.new.type_cast_from_user("0") # false

PREVIOUS ANSWER:

ActiveRecord maintains a list of representations for true/false in https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/column.rb

2.0.0-p247 :005 > ActiveRecord::ConnectionAdapters::Column.value_to_boolean("ON")
2.0.0-p247 :006 > ActiveRecord::ConnectionAdapters::Column.value_to_boolean("F")

This is not part of Rails' public API, so I wrapped it into a helper method:

class ApplicationController < ActionController::Base
  private

  def parse_boolean(value)
    ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
  end
end

and added a basic test:

class ApplicationControllerTest < ActionController::TestCase
  test "parses boolean params" do
    refute ApplicationController.new.send(:parse_boolean, "OFF")
    assert ApplicationController.new.send(:parse_boolean, "T")
  end
end
like image 137
Wojtek Kruszewski Avatar answered Nov 09 '22 18:11

Wojtek Kruszewski


I wanted to comment on zetetic answer but as I can't do that yet I'll post this as an answer.

If you use

@show_all = params[:show_all] == "1"

then you can drop ? true : false because params[:show_all] == "1" statement itself will evaluate to true or false and thus ternary operator is not needed.

like image 45
Uģis Ozols Avatar answered Nov 09 '22 17:11

Uģis Ozols


This question is rather old, but since I came across this issue a couple of times, and didn't like any of the solutions proposed, I hacked something myself which allows to use multiple strings for true such as 'yes', 'on', 't' and the opposite for false.

Monkey patch the class String, and add a method to convert them to boolean, and put this file in /config/initializers as suggested here: Monkey Patching in Rails 3

class String
  def to_bool
    return true if ['true', '1', 'yes', 'on', 't'].include? self
    return false if ['false', '0', 'no', 'off', 'f'].include? self
    return nil
  end
end

Notice that if the value is none of the valid ones either for true or false, then it returns nil. It's not the same to search for ?paid=false (return all records not paid) than ?paid= (I don't specify if it has to be paid or not -- so discard this).

Then, following this example, the logic in your controller would look like this:

Something.where(:paid => params[:paid].to_bool) unless params[:paid].try(:to_bool).nil?

It's pretty neat, and helps to keep controllers/models clean.

like image 22
ismriv Avatar answered Nov 09 '22 18:11

ismriv


@show_all = params[:show_all] == "1" ? true : false

This should work nicely if you're passing the value in from a checkbox -- a missing key in a hash generates nil, which evaluates to false in a conditional.

EDIT

As pointed out here, the ternary operator is not necessary, so this can just be:

@show_all = params[:show_all] == "1"

like image 17
zetetic Avatar answered Nov 09 '22 16:11

zetetic