2016-03-25 15 views
32

konvertieren Ich habe einen Wert, der einer von vier Dingen sein wird: Boolean True, Boolean False, die Zeichenfolge "True" oder die Zeichenfolge "False". Ich möchte die Zeichenfolge in einen booleschen Wert konvertieren, wenn es eine Zeichenfolge ist, andernfalls lasse sie unverändert. Mit anderen Worten:Ruby: Wie eine Zeichenfolge in boolean

"true" sollte

"false" wahr werden sollte

true false werden sollte wahr bleiben

falsch sollte

+2

Muss das Ergebnis * einer der beiden Werte 'true' oder' false' sein oder ist es ausreichend, wenn das Ergebnis truthy oder falsch ist? Wenn letzteres ist, dann ist "falsch" bereits falsch, und sowohl "wahr" als auch "wahr" sind truthy, also ist der einzige Wert, für den das Ergebnis nicht bereits korrekt ist, "false": 'if input = = 'false' dann wahr else input end 'sollte es tun. –

+0

Das ist ein toller Kommentar Jörg, aber ich würde annehmen, dass es für einige Anwendungen notwendig ist, den booleschen Wert wahr oder falsch zu haben und nicht nur einen Wert, der truthy oder falsch ist. – emery

+1

Emery, wenn Sie einen booleschen Wert zurückgeben möchten, könnten Sie @ Jörgs Ausdruck mit zwei "nots" voranstellen: '!! (wenn input == 'false' dann true else input end)'. Das zweite '!' Wandelt den Rückgabewert in einen booleschen Wert um, der das Gegenteil dessen ist, was Sie wollen; Das erste '!' macht dann die Korrektur. Dieser "Trick" gibt es schon lange. Nicht jeder mag es. –

Antwort

52
def true?(obj) 
    obj.to_s == "true" 
end 
+0

das ist erstaunlich, kann jemand erklären, wie es funktioniert? – null

+0

Ja, @null, die to_s-Methode konvertiert boolesche Wahr- oder Falsch-Werte in "Wahr" oder "Falsch" und belässt den Wert unverändert, wenn es ursprünglich eine Zeichenfolge war. Jetzt sind wir sicher, entweder "wahr" oder "falsch" als eine Zeichenkette zu haben ... und wir müssen nur == prüfen, ob die Zeichenkette gleich "wahr" ist. Wenn dies der Fall ist, war der ursprüngliche Wert entweder wahr oder "wahr". Wenn dies nicht der Fall ist, war der ursprüngliche Wert falsch, "falsch" oder etwas, das völlig unabhängig ist. – emery

10
if value.to_s == 'true' 
    true 
elsif value.to_s == 'false' 
    false 
end 
+0

Sonst müssen Sie überprüfen, ob es ein Typ String ist und wenn ja, dann prüfen Sie, ob es 'wahr' ist und wenn ja, dann geben Sie wahr zurück. Warum all diese Vergleiche? – archana

+7

Ihr Code als Einzeiler 'value.to_s == 'true'? true: false –

+0

Das if/elsif/end ist wahrscheinlich für einen Anfänger am besten lesbar. Das to_s wird wahrscheinlich nicht wirklich benötigt, wenn die elsif-Anweisung verwendet wird, da es keinen Block unter "if" oder "elsif" ausführt, wenn der boolesche Wert nicht mit einer Zeichenfolge übereinstimmt, und dann bleibt der boolesche Wert intakt. – emery

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

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

falsch bleiben Ein Juwel wie https://rubygems.org/gems/to_bool kann verwendet werden, aber es kann leicht in einer Zeile geschrieben werden mit eine Regex oder Ternär.

regex Beispiel:

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

ternäres Beispiel:

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

Der Vorteil für die regex Methode ist, dass reguläre Ausdrücke sind flexibel und können eine Vielzahl von Mustern entsprechen. Zum Beispiel, wenn Sie vermuten, dass var irgendetwas von "True" sein könnte, "False", 'T', 'F', 't' oder 'f', dann können Sie die Regex ändern:

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

Hinweis: '\ A' /' \ z' ist Start/Ende des Strings und '^'/'$' ist Start/Ende der Zeile.Also, wenn 'var ==" true \ nwhatevs "' dann 'boolean == true'. – cremno

3

Obwohl ich den Hash-Ansatz mag (ich habe es in der Vergangenheit für ähnliche Dinge verwendet), da Sie nur Truthy-Werte wirklich gut finden - da sonst alles falsch ist - können Sie nach einem Array suchen :

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

oder wenn andere Werte als truthy werden:

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

würden Sie haben andere Dinge zu tun, wenn das Original value könnte Fall gemischt werden:

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

aber auch hier für Ihre spezifische Beschreibung Ihres Problems, könnten Sie mit diesem letzten Beispiel als Lösung wegkommen .

1

In Schienen, ich habe vorher so etwas getan:

class ApplicationController < ActionController::Base 
    # ... 

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

    # ... 
end 

das ist schön, wenn Sie versuchen, Ihre boolean Strings Vergleiche in der gleichen Weise wie Schienen für Ihre Datenbank würde passen.

-4

Was smthing wie:

boolean_str = 'false' 
boolean = eval(boolean_str) 
+4

es ist ziemlich gefährlich, wenn die Eingabe von außerhalb der Welt kommt. –

+0

nie Eval von externen Daten verwenden – jacopobeschi

35

Wenn Sie Rails verwenden 5 können Sie ActiveModel::Type::Boolean.new.cast(value) tun.

Verwenden Sie in Rails 4.2 ActiveRecord::Type::Boolean.new.type_cast_from_user(value).

Das Verhalten ist etwas anders, da in Rails 4.2 der wahre Wert und die falschen Werte überprüft werden.In Rails 5 werden nur falsche Werte überprüft - es sei denn, die Werte sind Null oder stimmen mit einem falschen Wert überein, es wird angenommen, dass sie wahr sind. Falsche Werte sind die gleiche in beiden Versionen: FALSE_VALUES = [false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"]

Rails 5 Quelle: https://github.com/rails/rails/blob/5-1-stable/activemodel/lib/active_model/type/boolean.rb

+0

Dies ist hilfreich, obwohl ich wünsche, dass die Menge von 'FALSE_VALUES' in Rails auch" Nein "enthalten. – pjrebsch

7

Ich habe dieses Muster häufig verwendet, um das Kernverhalten von Ruby zu verlängern, um es einfacher mit der Umwandlung von beliebigen Datentypen umgehen zu boolesche Werte, die es einfach macht mit unterschiedlichen URL-Parameter zu behandeln usw.

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 

Also lassen Sie uns sagen, dass Sie einen Parameter foo haben, die sein kann:

  • eine ganze Zahl (0 falsch ist, alle anderen sind wahr)
  • ein wahrer Boolescher (true/false)
  • eine Zeichenfolge ("wahr", "falsch", "0", "1", " TRUE“,‚false‘)
  • nil

Statt eine Reihe von conditionals zu verwenden, können Sie nur foo.to_boolean anrufen und es wird für Sie den Rest der Magie tun.

In Rails, ich füge dies zu einem Initialisierer namens core_ext.rb in fast allen meiner Projekte, da dieses Muster so üblich ist.

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

Denken Sie nicht zu viel:

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 

Sie auch ".downcase" hinzufügen können, wenn Sie Großbuchstaben besorgt sind.

+1

'nil.to_s == 'wahr' # false' – juliangonzalez

Verwandte Themen