Mam wartość, która będzie jedną z czterech rzeczy: logiczna prawda, logiczna fałsz, ciąg „prawda” lub ciąg „fałsz”. Chcę przekonwertować ciąg na wartość logiczną, jeśli jest to ciąg, w przeciwnym razie pozostawić go niezmienionym. Innymi słowy:
„prawda” powinna stać się prawdą
„fałsz” powinien stać się fałszem
prawda powinna pozostać prawdziwa
fałsz powinien pozostać fałszywy
ruby
string
boolean
type-conversion
szmergiel
źródło
źródło
true
ifalse
czy to wystarczy, jeśli wynik jest truthy lub falsey? Jeśli to drugie, tofalse
jest już falsey i obatrue
i'true'
są truthy, więc jedyną wartością, dla której wynik nie jest już prawidłowy, to'false'
:if input == 'false' then true else input end
powinien to zrobić.!!(if input == 'false' then true else input end)
. Drugi!
konwertuje zwracaną wartość na wartość logiczną, która jest przeciwieństwem tego, czego chcesz; pierwszy!
następnie dokonuje korekty. Ta „sztuczka” istnieje od dawna. Nie wszystkim się to podoba.Odpowiedzi:
źródło
obj.to_s.downcase == 'true'
downcase!
a przydzielisz 1 obiekt mniej.downcase
powieli istniejący ciąg. Kiedy Frozen String Literals stanie się domyślną opcją Rubiego, będzie to miało mniejsze znaczenie.Jeśli używasz Rails 5, możesz to zrobić
ActiveModel::Type::Boolean.new.cast(value)
.W Railsach 4.2 użyj
ActiveRecord::Type::Boolean.new.type_cast_from_user(value)
.Zachowanie jest nieco inne, ponieważ w Railsach 4.2 sprawdzane są wartości prawda i fałsz. W Railsach 5 sprawdzane są tylko wartości fałsz - o ile wartości nie są zerowe lub nie pasują do wartości fałsz, przyjmuje się, że są prawdziwe. Fałszywe wartości są takie same w obu wersjach:
FALSE_VALUES = [false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"]
Rails 5 Źródło: https://github.com/rails/rails/blob/5-1-stable/activemodel/lib/active_model/type/boolean.rb
źródło
FALSE_VALUES
w Railsach zawierał również „nie”.ActiveRecord::Type::Boolean::FALSE_VALUES << "no"
do inicjatora.ActiveModel::Type::Boolean.new.cast(value)
rozróżniana jest wielkość liter ... więc 'False' przyjmie wartość true, tak jak każdy inny ciąg z wyjątkiem 'false'. puste łańcuchy''
domyślnie mają wartość nil, a nie fałsz. ^^ cenne informacje dostarczone tutaj przez @thomasfedb na temat dostosowywania inicjatoraActiveModel::Type::Boolean.new.cast(nil)
również powracanil
.ActiveRecord::Type::Boolean::FALSE_VALUES
jest zamrożona.Często używałem tego wzorca, aby rozszerzyć podstawowe zachowanie Rubiego, aby ułatwić sobie konwersję dowolnych typów danych na wartości logiczne, co bardzo ułatwia radzenie sobie z różnymi parametrami adresu URL itp.
Powiedzmy, że masz parametr,
foo
którym może być:Zamiast używać kilku warunków, możesz po prostu zadzwonić,
foo.to_boolean
a resztę magii wykona za Ciebie.W Railsach dodaję to do inicjalizatora nazwanego
core_ext.rb
w prawie wszystkich moich projektach, ponieważ ten wzorzec jest tak powszechny.źródło
"buy"=~/b/ => 0
Ale("buy"=~/b/).to_boolean => false
Nie myśl za dużo:
Więc,
Możesz również dodać „.downcase”, jeśli martwisz się dużymi literami.
źródło
nil.to_s == 'true' #false
źródło
value.to_s == 'true' ? true : false
if true then true, if false then false
Zgadnij co? Możesz go całkowicie usunąć!value.to_s == 'true' ? true : false
powinno byćvalue.to_s == 'true'
źródło
W aplikacji rails 5.1 używam tego podstawowego rozszerzenia zbudowanego na
ActiveRecord::Type::Boolean
. Działa idealnie dla mnie, gdy deserializuję wartość logiczną z ciągu JSON.https://api.rubyonrails.org/classes/ActiveModel/Type/Boolean.html
zainicjuj podstawowe rozszerzenia
rspec
źródło
Praca w Railsach 5
źródło
ActiveModel::Type::Boolean.new.cast("False") # => true
... Użyj to_s.downcase na wejściu to dobry pomysłW Railsach wolę używać
ActiveModel::Type::Boolean.new.cast(value)
jak wspomniano w innych odpowiedziach tutajAle kiedy piszę zwykły Ruby lib. następnie używam hacka, w którym
JSON.parse
(standardowa biblioteka Ruby) zamieni ciąg znaków „prawda” natrue
i „fałsz” nafalse
. Na przykład:Przykład z aplikacji na żywo:
źródło
Mam mały hack do tego.
JSON.parse('false')
powrócifalse
iJSON.parse('true')
wróci prawda. Ale to nie działaJSON.parse(true || false)
. Tak więc, jeśli używasz czegoś takiegoJSON.parse(your_value.to_s)
, powinieneś osiągnąć swój cel w prosty, ale hakerski sposób.źródło
Klejnot taki jak https://rubygems.org/gems/to_boolMożna użyć , ale można go łatwo zapisać w jednej linii za pomocą wyrażenia regularnego lub trójskładnika.
przykład wyrażenia regularnego:
potrójny przykład:
Zaletą metody regex jest to, że wyrażenia regularne są elastyczne i mogą pasować do wielu różnych wzorców. Na przykład, jeśli podejrzewasz, że zmienna może mieć dowolną wartość „True”, „False”, „T”, „F”, „t” lub „f”, możesz zmodyfikować to wyrażenie regularne:
źródło
\A
/\z
to początek / koniec napisu, a^
/$
to początek / koniec linii. Więc jeślivar == "true\nwhatevs"
wtedyboolean == true
.var.eql?('true') ? true : false
bardzo mi się podoba . Dzięki!Chociaż podoba mi się podejście haszujące (użyłem go w przeszłości do podobnych rzeczy), biorąc pod uwagę, że tak naprawdę zależy Ci tylko na dopasowywaniu prawdziwych wartości - ponieważ - wszystko inne jest fałszywe - możesz sprawdzić, czy jest włączona do tablicy:
lub jeśli inne wartości można uznać za prawdziwe:
musiałbyś zrobić inne rzeczy, jeśli oryginał
value
może być mieszany:ale znowu, dla twojego konkretnego opisu problemu, ostatni przykład może ci ujść na sucho jako rozwiązanie.
źródło
W szynach robiłem wcześniej coś takiego:
Co jest fajne, jeśli próbujesz dopasować swoje porównania ciągów logicznych w taki sam sposób, jak railsy dla twojej bazy danych.
źródło
Blisko tego, co już zostało opublikowane, ale bez zbędnego parametru:
stosowanie:
źródło