I have a value that will be one of four things: boolean true, boolean false, the string \"true\", or the string \"false\". I want to convert the string to a boolean if it i
In Rails I prefer using ActiveModel::Type::Boolean.new.cast(value)
as mentioned in other answers here
But when I write plain Ruby lib. then I use a hack where JSON.parse
(standard Ruby library) will convert string "true" to true
and "false" to false
. E.g.:
require 'json'
azure_cli_response = `az group exists --name derrentest` # => "true\n"
JSON.parse(azure_cli_response) # => true
azure_cli_response = `az group exists --name derrentesttt` # => "false\n"
JSON.parse(azure_cli_response) # => false
Example from live application:
require 'json'
if JSON.parse(`az group exists --name derrentest`)
`az group create --name derrentest --location uksouth`
end
confirmed under Ruby 2.5.1
I've frequently used this pattern to extend the core behavior of Ruby to make it easier to deal with converting arbitrary data types to boolean values, which makes it really easy to deal with varying URL parameters, etc.
class String
def to_boolean
ActiveRecord::Type::Boolean.new.cast(self)
end
end
class NilClass
def to_boolean
false
end
end
class TrueClass
def to_boolean
true
end
def to_i
1
end
end
class FalseClass
def to_boolean
false
end
def to_i
0
end
end
class Integer
def to_boolean
to_s.to_boolean
end
end
So let's say you have a parameter foo
which can be:
Instead of using a bunch of conditionals, you can just call foo.to_boolean
and it will do the rest of the magic for you.
In Rails, I add this to an initializer named core_ext.rb
in nearly all of my projects since this pattern is so common.
## EXAMPLES
nil.to_boolean == false
true.to_boolean == true
false.to_boolean == false
0.to_boolean == false
1.to_boolean == true
99.to_boolean == true
"true".to_boolean == true
"foo".to_boolean == true
"false".to_boolean == false
"TRUE".to_boolean == true
"FALSE".to_boolean == false
"0".to_boolean == false
"1".to_boolean == true
true.to_i == 1
false.to_i == 0
Although I like the hash approach (I've used it in the past for similar stuff), given that you only really care about matching truthy values - since - everything else is false - you can check for inclusion in an array:
value = [true, 'true'].include?(value)
or if other values could be deemed truthy:
value = [1, true, '1', 'true'].include?(value)
you'd have to do other stuff if your original value
might be mixed case:
value = value.to_s.downcase == 'true'
but again, for your specific description of your problem, you could get away with that last example as your solution.
Working in 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
In rails, I've previously done something like this:
class ApplicationController < ActionController::Base
# ...
private def bool_from(value)
!!ActiveRecord::Type::Boolean.new.type_cast_from_database(value)
end
helper_method :bool_from
# ...
end
Which is nice if you're trying to match your boolean strings comparisons in the same manner as rails would for your database.
def true?(obj)
obj.to_s.downcase == "true"
end