स्ट्रिंग "सच" और "झूठी" बूलियन के लिए


85

मेरे पास एक रेल एप्लिकेशन है और मैं पृष्ठभूमि में अपने खोज दृश्य को क्वेरी करने के लिए jQuery का उपयोग कर रहा हूं। फ़ील्ड q(खोज शब्द) start_date, end_dateऔर हैं internalinternalक्षेत्र एक चेकबॉक्स है और मैं उपयोग कर रहा हूँ is(:checked)विधि यूआरएल कि क्वेरी की जाती है निर्माण करने के लिए:

$.getScript(document.URL + "?q=" + $("#search_q").val() + "&start_date=" + $("#search_start_date").val() + "&end_date=" + $("#search_end_date").val() + "&internal=" + $("#search_internal").is(':checked'));

अब मेरी समस्या यह है params[:internal]क्योंकि "सच्चा" या "असत्य" युक्त एक स्ट्रिंग है और मुझे इसे बूलियन में डालने की आवश्यकता है। बेशक मैं इसे इस तरह कर सकता हूं:

def to_boolean(str)
     return true if str=="true"
     return false if str=="false"
     return nil
end

लेकिन मुझे लगता है कि इस समस्या से निपटने के लिए एक और रूबिश तरीका होना चाहिए! है ना…?

जवाबों:


133

जहां तक ​​मुझे पता है कि बुलिंग के लिए कास्टिंग स्ट्रिंग्स के रास्ते में कोई निर्माण नहीं किया गया है, लेकिन अगर आपके स्ट्रिंग्स में केवल शामिल हैं 'true'और 'false'आप निम्न के लिए अपने तरीके को छोटा कर सकते हैं:

def to_boolean(str)
  str == 'true'
end

8
बस थोड़ा सा संशोधन == 'सच' || str = '1'
AMTourky

30
शायद str.downcase == पूर्णता के लिए 'सही'
JEMaddux

@AMTourky यह नहीं होना चाहिए str == 'सच' || str == '1' दो "==" के साथ?
पास्कल

@Lowryder हाँ! यदि डिफ़ॉल्ट check_box का उपयोग किया जा रहा है।
7URm3n

49

ActiveRecord इसे करने का एक साफ तरीका प्रदान करता है।

def is_true?(string)
  ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(string)
end

ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES स्ट्रिंग्स के रूप में सच्चे मूल्यों के सभी स्पष्ट प्रतिनिधित्व हैं।


16
और भी सरल, बस ActiveRecord::ConnectionAdapters::Column.value_to_boolean(string)(स्रोत) apidock.com/rails/v3.0.9/ActiveRecord/ConnectionAdapters/Column/…
माइक एटलस

हाँ, नवीनतम संस्करणों में!
सत्या कल्लूरी

6
ActiveRecord::Type::Boolean.new.type_cast_from_user("true")=> सत्य ActiveRecord::Type::Boolean.new.type_cast_from_user("T")=> सच
एलेक्सचैफी

झूठी मान सूची को ActiveModel में ले जाया गया है :: प्रकार :: रेल 5 में बूलियन
divideByZero

ActiveModel::Type::Booleanबहुत अधिक उपयुक्त पथ जैसा लगता है - जबकि ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES"सत्य" मूल्यों में निहित है, कोई यह तर्क दे सकता है कि यह केवल संयोगवश मामला है, और उन मूल्यों को जो उस विशिष्ट उपयोग के मामले के लिए सत्य माना जाना चाहिए, लेकिन अन्य को शामिल नहीं किया जा सकता है। दूसरी ओर, ActiveModel::Type::Booleanजाहिरा तौर पर एक सामान्य तरीके से उपयोग करने के लिए डिज़ाइन किया गया है।
Lyndsy साइमन

24

सुरक्षा सूचना

ध्यान दें कि इसके नंगे रूप में यह उत्तर केवल प्रश्न में एक के बजाय नीचे सूचीबद्ध अन्य उपयोग के मामले के लिए उपयुक्त है। जबकि ज्यादातर तय है, वहाँ कई YAML संबंधित सुरक्षा भेद्यताएँ हैं जो उपयोगकर्ता इनपुट को YAML के रूप में लोड करने के कारण हुईं।


एक चाल जिसका उपयोग मैं स्ट्रिंग्स को बूल्स में परिवर्तित करने के लिए करता हूं YAML.load, जैसे:

YAML.load(var) # -> true/false if it's one of the below

YAML बूल काफी सत्य / झूठे तार स्वीकार करता है:

y|Y|yes|Yes|YES|n|N|no|No|NO
|true|True|TRUE|false|False|FALSE
|on|On|ON|off|Off|OFF

एक और उपयोग मामला

मान लें कि आपके पास इस तरह से कॉन्फ़िगर कोड का एक टुकड़ा है:

config.etc.something = ENV['ETC_SOMETHING']

और कमांड लाइन में:

$ export ETC_SOMETHING=false

अब चूंकि ENVवर्जन कोड के अंदर एक बार स्ट्रिंग कर रहा है, इसलिए इसका config.etc.somethingमान स्ट्रिंग "false"होगा और यह गलत तरीके से मूल्यांकन करेगा true। लेकिन अगर आप ऐसा करते हैं:

config.etc.something = YAML.load(ENV['ETC_SOMETHING'])

सब ठीक हो जाएगा। यह .yml फ़ाइलों के रूप में अच्छी तरह से लोडिंग विन्यास के साथ संगत है।


1
यदि स्ट्रिंग आपके नियंत्रण में है तो यह अच्छा है। इस प्रश्न के मामले में, प्रदान किए गए मान उपयोगकर्ता के ब्राउज़र से आते हैं और इस तरह, उन्हें असुरक्षित माना जाना चाहिए। YAML आपको किसी भी रूबी ऑब्जेक्ट को अनुक्रमित / अस्वाभाविक बनाने की अनुमति देता है और यह संभावित रूप से खतरनाक है। कई घटनाएं हुई हैं: google.com/webhp?q=rails+yaml+vulnerability
Teoulas

1
@Teoulas, मैं आपसे पूरी तरह सहमत हूँ। वास्तव में, मैं एक नोटिस जोड़ रहा हूं ताकि लोग असुरक्षित तरीके से इसका इस्तेमाल न करें।
हालिल Ö ज़गुर

16

इसे संभालने के लिए कोई बिल्ट-इन तरीका नहीं है (हालाँकि एक्शनपैक इसके लिए सहायक हो सकता है)। मैं कुछ इस तरह की सलाह दूंगा

def to_boolean(s)
  s and !!s.match(/^(true|t|yes|y|1)$/i)
end

# or (as Pavling pointed out)

def to_boolean(s)
  !!(s =~ /^(true|t|yes|y|1)$/i)
end

झूठे / सच्चे शाब्दिक के बजाय 0 और गैर-0 का उपयोग करने के लिए क्या काम करता है:

def to_boolean(s)
  !s.to_i.zero?
end

3
आपको गार्ड की आवश्यकता नहीं है और "" यदि आप उपयोग करते हैं "!! (s = ~ / regex_here /)" क्योंकि "nil = ~ / कुछ भी /" रिटर्न nil।
पैवेलिंग

आह वास्तव में। मैंने इसे जोड़ा, लेकिन पुराने को भी रखा, क्योंकि मुझे लगता है कि .matchइसे पढ़ना थोड़ा आसान है।
मार्सेल जैकवर्थ

7

ActiveRecord::Type::Boolean.new.type_cast_from_userरेल के आंतरिक मानचित्रण ConnectionAdapters::Column::TRUE_VALUESऔर ConnectionAdapters::Column::FALSE_VALUES:

[3] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("true")
=> true
[4] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("false")
=> false
[5] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("T")
=> true
[6] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("F")
=> false
[7] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("yes")
DEPRECATION WARNING: You attempted to assign a value which is not explicitly `true` or `false` ("yes") to a boolean column. Currently this value casts to `false`. This will change to match Ruby's semantics, and will cast to `true` in Rails 5. If you would like to maintain the current behavior, you should explicitly handle the values you would like cast to `false`. (called from <main> at (pry):7)
=> false
[8] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("no")
DEPRECATION WARNING: You attempted to assign a value which is not explicitly `true` or `false` ("no") to a boolean column. Currently this value casts to `false`. This will change to match Ruby's semantics, and will cast to `true` in Rails 5. If you would like to maintain the current behavior, you should explicitly handle the values you would like cast to `false`. (called from <main> at (pry):8)
=> false

तो आप इस तरह से एक आरंभक में अपना खुद का to_b( to_boolया to_boolean) विधि बना सकते हैं :

class String
  def to_b
    ActiveRecord::Type::Boolean.new.type_cast_from_user(self)
  end
end

2
यह ActiveRecord :: टाइप :: Boolean.new.cast (मान) रेल में 5 (नीचे सीडब्ल्यूटी देखें)
डेव बर्ट

6

आप wannabe_bool रत्न का उपयोग कर सकते हैं। https://github.com/prodis/wannabe_bool

यह मणि #to_bस्ट्रिंग, इंटेगर, प्रतीक और नीलक्लास कक्षाओं के लिए एक विधि लागू करता है ।

params[:internal].to_b

6

रेल 5 में आप ActiveRecord::Type::Boolean.new.cast(value)इसे बूलियन में डालने के लिए उपयोग कर सकते हैं ।


1
हालांकि जागरूक रहें, ActiveRecord :: प्रकार :: Boolean.new.cast ("42") सही
divideByZero

3

मुझे नहीं लगता कि रूबी में ऐसा कुछ भी बनाया गया है। आप स्ट्रिंग क्लास को फिर से खोल सकते हैं और वहाँ to_bool विधि जोड़ सकते हैं:

class String
    def to_bool
        return true if self=="true"
        return false if self=="false"
        return nil
    end
end

फिर आप इसे अपने प्रोजेक्ट में कहीं भी उपयोग कर सकते हैं, जैसे: params[:internal].to_bool


2
मैं निश्चित रूप से एक to_boolसमारोह वापसी नहीं करना चाहता हूँ nil; यह गलत लगता है। अन्य रूपांतरण कार्य ऐसा नहीं करते हैं: "a".to_iरिटर्न 0, नहींnil
क्रीज़ जूल

3

शायद str.to_s.downcase == 'true'पूर्णता के लिए। फिर strशून्य या 0 होने पर भी कुछ भी दुर्घटनाग्रस्त नहीं हो सकता ।


2

पुण्य के स्रोत कोड को देखते हुए , मैं शायद कुछ इस तरह से करूंगा:

def to_boolean(s)
  map = Hash[%w[true yes 1].product([true]) + %w[false no 0].product([false])]
  map[s.to_s.downcase]
end

1

आप केवल जोड़कर विचार कर सकते हैं internalअपने यूआरएल के लिए अगर यह सच है, तो अगर चेकबॉक्स चेक नहीं किया जाता है और आप संलग्न नहीं है यह params[:internal]होगा nil, जो रूबी में गलत का आकलन।

मैं उस विशिष्ट jQuery से परिचित नहीं हूं जिसका आप उपयोग कर रहे हैं, लेकिन क्या आप URL स्ट्रिंग को मैन्युअल रूप से बनाने की तुलना में कॉल करना चाहते हैं? क्या आपकी नज़र $getऔर पर है $ajax?


1

आप स्ट्रिंग क्लास में to_boolean की विधि जोड़ सकते हैं। तब आप 'true.to_boolean या' 1'to_boolean कर सकते थे

class String
  def to_boolean
    self == 'true' || self == '1'
  end
end

-5

मुझे आश्चर्य है कि किसी ने भी इस सरल समाधान को पोस्ट नहीं किया। यदि आपके तार "सच्चे" या "झूठे" होने जा रहे हैं।

def to_boolean(str)
    eval(str)
end

4
Thats क्योंकि यह समाधान एक सुरक्षा Desaster है। : D
18

1
इस समाधान के साथ समस्या उपयोगकर्ता इनपुट है - यदि कोई टाइप करता है to_boolean("ActiveRecord::Base.connection.execute('DROP TABLE *')"), तो यह आपके डेटाबेस को नष्ट कर देगा (और सच लौटाएगा!)। मज़े करें: डी
बेन ऑबिन

अच्छे अंक। मैं संदर्भ के बारे में नहीं सोच रहा था। मैं कम से कम पात्रों को लागू करने के लिए सोच रहा था। :)
पोवेस

कहा भेद्यता के लिए एक आसान तय: bool = nil; bool = eval(str) if ["true", "false"].include?(str)बस सोचा कि मैं स्पष्टीकरण के लिए जोड़ना चाहिए।
फर्नांडो कोर्डेइरो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.