2016-03-25 202 views
32

我有一個值將是四件事之一:布爾值true,布爾值false,字符串「true」或字符串「false」。如果它是一個字符串,我想將該字符串轉換爲布爾值,否則將其保持不變。換句話說:Ruby:如何將字符串轉換爲布爾型

「真實」 應該成爲真正的

「假」 應該成爲假

真正應該忠於

假應該留假

+2

結果*有*是真值還是假值的兩個值之一或者結果是真是假?如果是後者,那麼'false'已經是假的,並且'true'和''true''都是真的,所以結果不是已經正確的唯一值是''false'':'如果input = ='假'然後真正的其他輸入結束'應該這樣做。 –

+0

這是一個很棒的評論Jorg,但是我會假設對於某些應用程序來說,有必要使布爾值爲true或false,而不僅僅是一個真或假的值。 – emery

+1

Emery,如果你需要返回一個布爾值,你可以在兩個「nots」之前加上@Jörg的表達式:'!!(如果input =='false'then true else input end)'。第二個'!'將返回值轉換爲與你想要的相反的布爾值。第一個'!'然後進行修正。這個「詭計」已經存在很長時間了。並不是每個人都喜歡它。 –

回答

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

這是驚人的,有人解釋它是如何工作的? – null

+0

是的,@null,to_s方法將布爾值true或false轉換爲「true」或「false」,如果最初是字符串,則該值保持不變。現在我們可以肯定地將「true」或「false」作爲字符串......並且我們只需要使用==檢查字符串是否等於「true」。如果是,則原始值爲真或「真」。如果不是,那麼原始值是錯誤的,「錯誤的」或者完全不相關的東西。 – emery

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

否則你將不得不檢查它是否是一個String類型,如果是,那麼檢查它是否爲'真',如果是,則返回true。爲什麼所有這些比較? – archana

+7

你的代碼作爲一行'value.to_s =='true'? true:false' –

+0

if/elsif/end對於初學者來說可能是最易讀的。當使用elsif語句時,to_s可能不是實際需要的,因爲當布爾值與字符串不匹配時,它不會在「if」或「elsif」下執行任何塊,然後布爾值將保持不變。 – emery

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

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

https://rubygems.org/gems/to_bool這樣的寶石可以使用,但它可以很容易地寫入一行使用正則表達式或三元組。

正則表達式例如:

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 
+1

注意:'\ A' /'\ z'是字符串的開始/結束,'^'/'$'是開始/結束的行。所以如果'var ==「true \ nwhatevs」',那麼'布爾== true'。 – cremno

3

雖然我喜歡散列方法(我過去曾經用過類似的東西),但由於您只關心匹配真值,因爲 - 其他所有東西都是假的 - 您可以檢查包含在數組中:

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

,或者如果其它值可被視爲truthy:

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

你必須,如果做其他的東西你原來value可能是混合的情況:再次

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

但是,對於你的你的問題的具體說明,你可以與最後一個例子作爲您的解決方案脫身。

1

在軌,我以前也做過這樣的事情:

class ApplicationController < ActionController::Base 
    # ... 

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

    # ... 
end 

,如果你想爲鐵軌會爲你的數據庫以相同的方式,以配合您的布爾字符串的比較,這是很好。

-4

什麼smthing像:

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

如果輸入來自世界各地,這是相當危險的。 –

+0

從不使用外部數據的評估 – jacopobeschi

35

如果您使用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_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

+0

這很有幫助,但我希望Rails中的「FALSE_VALUES」集合也包含「no」。 – pjrebsch

7

我經常使用這個模式來延長紅寶石的核心行爲,使其更容易對付任意轉換數據類型布爾值,這使得它很容易對付不同的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是假的,其他均爲真)
  • 真布爾值(真/假)
  • 一個字符串( 「真」, 「假」, 「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 
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,」 如果你擔心大寫字母。

+1

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

相關問題