I have controller as follows
def city
params.require(:id)
begin
#data = #user.city_details(Integer(params[:id]),
params[:flag]
rescue ArgumentError => e
render_error(:bad_request, e.message)
end
end
model.rb
def city_details(id, flag = 'N')
StoredProcedure::User::GetCityDetails.exec!(
id,
flag
)
end
end
so you can see in model i have flag value default 'N'. How do i update controller so that if flag value is passed as true then update it to Y and if passed false then update it to N?
flag = params[:flag] == '1' ? 'Y' : 'N'
#data = #user.city_details(params[:id].to_i, flag)
I assume that you have some sort of checkbox that will return '1' for true and '0' for false (usual case in rails). If not, alter params[:flag] == '1' condition to your needs.
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 is a string, otherwise leave it unmodified. In other words:
"true" should become true
"false" should become false
true should stay true
false should stay false
If you use Rails 5, you can do ActiveModel::Type::Boolean.new.cast(value).
In Rails 4.2, use ActiveRecord::Type::Boolean.new.type_cast_from_user(value).
The behavior is slightly different, as in Rails 4.2, the true value and false values are checked. In Rails 5, only false values are checked - unless the values is nil or matches a false value, it is assumed to be true. False values are the same in both versions:
FALSE_VALUES = [false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"]
Rails 5 Source: https://github.com/rails/rails/blob/5-1-stable/activemodel/lib/active_model/type/boolean.rb
def true?(obj)
obj.to_s.downcase == "true"
end
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:
an integer (0 is false, all others are true)
a true boolean (true/false)
a string ("true", "false", "0", "1", "TRUE", "FALSE")
nil
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
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
Don't think too much:
bool_or_string.to_s == "true"
So,
"true".to_s == "true" #true
"false".to_s == "true" #false
true.to_s == "true" #true
false.to_s == "true" #false
You could also add ".downcase," if you are worried about capital letters.
if value.to_s == 'true'
true
elsif value.to_s == 'false'
false
end
h = { "true"=>true, true=>true, "false"=>false, false=>false }
["true", true, "false", false].map { |e| h[e] }
#=> [true, true, false, false]
In a rails 5.1 app, I use this core extension built on top of ActiveRecord::Type::Boolean. It is working perfectly for me when I deserialize boolean from JSON string.
https://api.rubyonrails.org/classes/ActiveModel/Type/Boolean.html
# app/lib/core_extensions/string.rb
module CoreExtensions
module String
def to_bool
ActiveRecord::Type::Boolean.new.deserialize(downcase.strip)
end
end
end
initialize core extensions
# config/initializers/core_extensions.rb
String.include CoreExtensions::String
rspec
# spec/lib/core_extensions/string_spec.rb
describe CoreExtensions::String do
describe "#to_bool" do
%w[0 f F false FALSE False off OFF Off].each do |falsey_string|
it "converts #{falsey_string} to false" do
expect(falsey_string.to_bool).to eq(false)
end
end
end
end
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
A gem like https://rubygems.org/gems/to_bool can be used, but it can easily be written in one line using a regex or ternary.
regex example:
boolean = (var.to_s =~ /^true$/i) == 0
ternary example:
boolean = var.to_s.eql?('true') ? true : false
The advantage to the regex method is that regular expressions are flexible and can match a wide variety of patterns. For example, if you suspect that var could be any of "True", "False", 'T', 'F', 't', or 'f', then you can modify the regex:
boolean = (var.to_s =~ /^[Tt].*$/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.
I have a little hack for this one. JSON.parse('false') will return false and JSON.parse('true') will return true. But this doesn't work with JSON.parse(true || false). So, if you use something like JSON.parse(your_value.to_s) it should achieve your goal in a simple but hacky way.
Rubocop suggested format:
YOUR_VALUE.to_s.casecmp('true').zero?
https://www.rubydoc.info/gems/rubocop/0.42.0/RuboCop/Cop/Performance/Casecmp
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.
You could just add !! before the variable:
!!test_string
Close to what is already posted, but without the redundant parameter:
class String
def true?
self.to_s.downcase == "true"
end
end
usage:
do_stuff = "true"
if do_stuff.true?
#do stuff
end
This function works for any input:
def true?(value)
![false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"].include? value
end
then you have:
true?(param) #returns true or false
I'm having an issue with boolean expected behavior. I can make the desired result but I'm not sure why the strange behavior occurs. This produces a wrong result:
def palindrome?(string)
rev = string.reverse
if rev == string
true
else
false
end
end
palindrome?("abc") == false # => true
palindrome?("abcba") == true # => true
palindrome?("z") == true # => true
while this produces the correct result:
def palindrome?(string)
rev = string.reverse
if rev == string
true
end
end
palindrome?("abc") == false # => false
palindrome?("abcba") == true # => true
palindrome?("z") == true # => true
The following might be similar:
def nearby_az(string)
counter = 0
string = string.split("")
if string.count == 1
false
elsif (string.index("z") - string.index("a")) <= 3
true
else
false
end
end
nearby_az("a") == false # => true
nearby_az("z") == false # => true
Because Ruby method will return the result of executing the last expression. For this if statement:
if rev == string
true
end
it will return nil if rev != string.
Actually, your first function is producing the correct result. The problem is the second formula. It returns nothing if the string is not a palindrome; it only returns true if the string is a palindrome. Therefore,
palindrome?("abc") == false
for the second equation returns false because palindrome?("abc") returns nothing because "abc" is not a palindrome, and so it is not equal to false.
The second implementation of palindrome? will return nil if it is not a palindrome. Thus nil == false # => false. In Ruby, all functions return something although it may be nil.
I need a simple function to return "true" or "false" the argument passed to it is:
1 or 0, or true or false
I currently had something like this, so the answer, if possible, should be concise as per below:
def boolean(value); return value ? ( value == 1 ? "true" : "false) : nil; end
Thanks.
Some ideas:
def boolean(x)
%w{1 true}.include?(x).to_s
end
def boolean(x)
(x == '1' || x == 'true').to_s
end
There's also the wannabe bool gem:
require 'wannabe_bool'
'1'.to_b # => true
'0'.to_b # => false
'true'.to_b # => true
'false'.to_b # => false
You might want to have a look how Rails does this typecasting in its database connection adapter:
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON'].to_set
# convert something to a boolean
def value_to_boolean(value)
if value.is_a?(String) && value.empty?
nil
else
TRUE_VALUES.include?(value)
end
end
See: docs for ActiveRecord::ConnectionAdapters::Column
I think this'll work, comments are welcome though:
def b(k); return k ? ( (k == "1" || k == "true") ? "true" : "false" ) : nil; end
puts b("1")
puts b("0")
puts b("true")
puts b("false")
Result:
true
false
true
false
I have the following code: i ? "x" : "y" But instead of only returning either "x" or "y" I also want to set i either true or false. i ? ("x"; i = false) : ("y"; i = true) however does not work.
(i ? "x" : "y").tap{i = !i}
or
(i = !i) ? "y" : "x"
But if this turns out to be an XY-situation (I don't write "XY-question" here because the OP has not asked any question), then this might be more elegant:
letter = ["x", "y"].cycle
letter.next #=> "x"
letter.next #=> "y"
letter.next #=> "x"
letter.next #=> "y"
...
If you want to return 'x' or y', then 'x' or 'y' needs to be the last statement:
i ? (i = false; 'x') : (i = true; 'y')
If you think of it like this, maybe it would make more sense:
if i
i = false
'x'
else
i = true
'y'
end
Keep in mind that setters in Ruby (and many other languages) return the value being set. For example, i = false returns false.
You should use ternary operator only in the simplest cases because readability and side-effect issues.
Ruby Code Style
But if you really want it you could do something like this:
!(i = !i) ? 'x' : 'y'