Подтвердить что ты не робот

Ruby: как преобразовать строку в boolean

У меня есть значение, которое будет одной из четырех вещей: boolean true, boolean false, строка "true" или строка "false". Я хочу преобразовать строку в логическое значение, если это строка, иначе оставить ее немодифицированной. Другими словами:

"true" должно стать истинным

"false" должно стать ложным

true должно оставаться верным

false должен оставаться ложным

4b9b3361

Ответ 1

def true?(obj)
  obj.to_s.downcase == "true"
end

Ответ 2

Если вы используете Rails 5, вы можете сделать ActiveModel::Type::Boolean.new.cast(value).

В Rails 4.2 используйте ActiveRecord::Type::Boolean.new.type_cast_from_user(value).

Поведение немного отличается, так как в Rails 4.2 проверяется истинное значение и ложные значения. В Rails 5 проверяются только ложные значения - если значения не равны нулю или не соответствуют ложному значению, оно считается истинным. В обеих версиях значения False одинаковы: FALSE_VALUES = [false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"]

Rails 5 Источник: https://github.com/rails/rails/blob/5-1-stable/activemodel/lib/active_model/type/boolean.rb

Ответ 3

Я часто использовал этот шаблон для расширения основного поведения Ruby, чтобы упростить работу с преобразованием произвольных типов данных в логические значения, что позволяет легко справляться с различными параметрами URL и т.д.

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

Итак, скажем, у вас есть параметр foo, который может быть:

  • целое число (0 - false, все остальные - true)
  • true boolean (true/false)
  • строка ( "true", "false", "0", "1", "TRUE", "FALSE" )
  • ноль

Вместо того, чтобы использовать кучу условных выражений, вы можете просто вызвать foo.to_boolean, и он сделает остальную магию для вас.

В Rails я добавляю это в инициализатор с именем core_ext.rb почти во всех моих проектах, так как этот шаблон настолько распространен.

## 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

Ответ 4

if value.to_s == 'true'
  true
elsif value.to_s == 'false'
  false
end

Ответ 5

h = { "true"=>true, true=>true, "false"=>false, false=>false }

["true", true, "false", false].map { |e| h[e] }
  #=> [true, true, false, false] 

Ответ 6

Не думайте слишком много:

bool_or_string.to_s == "true"  

Итак,

"true".to_s == "true"   #true
"false".to_s == "true"  #false 
true.to_s == "true"     #true
false.to_s == "true"    #false

Вы также можете добавить ".downcase", если вас беспокоят заглавные буквы.

Ответ 7

Хотя мне нравится хеш-подход (я использовал его в прошлом для подобных вещей), учитывая, что вы действительно заботитесь только о соответствии правных значений, поскольку - все остальное ложно - вы можете проверить включение в массив:

value = [true, 'true'].include?(value)

или если другие значения могут считаться правдивыми:

value = [1, true, '1', 'true'].include?(value)

вам придется делать другие вещи, если ваш оригинальный value может быть смешанным:

value = value.to_s.downcase == 'true'

но опять же, для вашего конкретного описания вашей проблемы, вы можете уйти с этим последним примером в качестве своего решения.

Ответ 8

Можно использовать драгоценный камень, например https://rubygems.org/gems/to_bool, но его можно легко записать в одну строку с помощью регулярного выражения или тройная.

Пример

regex:

boolean = (var.to_s =~ /^true$/i) == 0

тернарный пример:

boolean = var.to_s.eql?('true') ? true : false

Преимущество метода регулярных выражений состоит в том, что регулярные выражения являются гибкими и могут соответствовать широкому спектру шаблонов. Например, если вы подозреваете, что var может быть любым из "True", "False", "T", "F", "t" или "f", вы можете изменить регулярное выражение:

boolean = (var.to_s =~ /^[Tt].*$/i) == 0

Ответ 9

В приложении rails 5.1 я использую это базовое расширение, построенное поверх ActiveRecord::Type::Boolean. Он отлично работает для меня, когда я deserialize boolean из строки JSON.

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

инициализировать расширения ядра

# 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

Ответ 10

У меня есть небольшой взлом для этого. JSON.parse('false') вернет false а JSON.parse('true') вернет true. Но это не работает с JSON.parse(true || false). Итак, если вы используете что-то вроде JSON.parse(your_value.to_s) это должно достичь вашей цели простым, но хакерским способом.

Ответ 11

В рельсах я ранее делал что-то вроде этого:

class ApplicationController < ActionController::Base
  # ...

  private def bool_from(value)
    !!ActiveRecord::Type::Boolean.new.type_cast_from_database(value)
  end
  helper_method :bool_from

  # ...
end

Хорошо, если вы пытаетесь сопоставить логические сравнения строк таким же образом, как и рельсы для вашей базы данных.

Ответ 12

В Rails я предпочитаю использовать ActiveModel::Type::Boolean.new.cast(value) как упоминалось в других ответах здесь

Но когда я пишу простой Ruby lib. затем я использую хак, где JSON.parse (стандартная библиотека Ruby) преобразует строку "true" в true и "false" в false. Например:

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

Пример из живого приложения:

require 'json'
if JSON.parse('az group exists --name derrentest')
  'az group create --name derrentest --location uksouth'
end

подтверждено в Ruby 2.5.1

Ответ 13

Один из способов - написать код таким образом, чтобы он прямо отражал бизнес-логику, точно выраженную OP:

def true_or_false answer
  if answer == true || answer == false
    answer
  elsif answer == "true"
    true
  else
    false
  end
end

Ответ 14

Как насчет smthing как:

boolean_str = 'false'
boolean = eval(boolean_str)