[Ruby-on-rails] शून्य पर "अपरिभाषित विधि" त्रुटियों से बचने के लिए हैश के लिए .try () के समतुल्य?


Answers

रूबी 2.3.0-पूर्वावलोकन 1 की घोषणा में सुरक्षित नेविगेशन ऑपरेटर का परिचय शामिल है।

एक सुरक्षित नेविगेशन ऑपरेटर, जो पहले से ही सी #, ग्रोवी और स्विफ्ट में मौजूद है, को obj&.foo रूप में नील हैंडलिंग को आसान बनाने के लिए पेश किया गया है। Array#dig और Hash#dig भी शामिल है।

इसका मतलब कोड के नीचे 2.3 के रूप में है

account.try(:owner).try(:address)

को फिर से लिखा जा सकता है

account&.owner&.address

हालांकि, किसी को सावधान रहना चाहिए कि #try प्रतिस्थापन में गिरावट नहीं है। इस उदाहरण पर एक नज़र डालें:

> params = nil
nil
> params&.country
nil
> params = OpenStruct.new(country: "Australia")
#<OpenStruct country="Australia">
> params&.country
"Australia"
> params&.country&.name
NoMethodError: undefined method `name' for "Australia":String
from (pry):38:in `<main>'
> params.try(:country).try(:name)
nil

इसमें एक समान प्रकार का तरीका भी शामिल है: Array#dig और Hash#dig । तो अब यह

city = params.fetch(:[], :country).try(:[], :state).try(:[], :city)

को फिर से लिखा जा सकता है

city = params.dig(:country, :state, :city)

दोबारा, #dig #try के व्यवहार की प्रतिलिपि नहीं #dig है। तो मूल्य वापस करने के साथ सावधान रहें। यदि params[:country] लौटाता है, उदाहरण के लिए, एक इंटीजर, TypeError: Integer does not have #dig method होगी।

Question

रेल में हम किसी त्रुटि से बचने के लिए कोई मान मौजूद नहीं होने पर निम्न कार्य कर सकते हैं:

@myvar = @comment.try(:body)

समकक्ष क्या है जब मैं एक हैश में गहरी खुदाई कर रहा हूं और कोई त्रुटि नहीं लेना चाहता हूं?

@myvar = session[:comments][@comment.id]["temp_value"] 
# [:comments] may or may not exist here

उपर्युक्त मामले में, session[:comments]try[@comment.id] काम नहीं करता है। क्या होगा?




जब आप ऐसा करते हैं:

myhash[:one][:two][:three]

आप सिर्फ "[]" विधि में कॉल का एक गुच्छा कर रहे हैं, त्रुटि तब होती है जब मायहाश [: एक] शून्य लौटाता है, क्योंकि शून्य में [] विधि नहीं होती है। तो, निकलस को एक [] विधि जोड़ने के लिए एक सरल और बदसूरत तरीका है, जो शून्य देता है: मैं इसे रेल ऐप में निम्नानुसार सेट कर दूंगा:

विधि जोड़ें:

#in lib/ruby_extensions.rb
class NilClass
  def [](*args)
    nil
  end
end

फ़ाइल की आवश्यकता है:

#in config/initializers/app_environment.rb
require 'ruby_extensions'

अब आप डर के बिना नेस्टेड हैश को कॉल कर सकते हैं: मैं यहां कंसोल में प्रदर्शन कर रहा हूं:

>> hash = {:foo => "bar"}
=> {:foo=>"bar"}
>> hash[:foo]
=> "bar"
>> hash[:doo]
=> nil
>> hash[:doo][:too]
=> nil



@myvar = session.fetch(:comments, {}).fetch(@comment.id, {})["temp_value"]

रूबी 2.0 से, आप कर सकते हैं:

@myvar = session[:comments].to_h[@comment.id].to_h["temp_value"]

रूबी 2.3 से, आप कर सकते हैं:

@myvar = session.dig(:comments, @comment.id, "temp_value")



उपयोग करने का प्रयास करें

@myvar = session[:comments][@comment.id]["temp_value"] if session[:comments]



हैश के साथ try करने का उचित उपयोग @sesion.try(:[], :comments)

@session.try(:[], :comments).try(:[], commend.id).try(:[], 'temp_value')



एक और दृष्टिकोण:

@myvar = session[:comments][@comment.id]["temp_value"] rescue nil

यह थोड़ा खतरनाक भी माना जा सकता है क्योंकि यह बहुत अधिक छुपा सकता है, व्यक्तिगत रूप से मुझे यह पसंद है।

यदि आप अधिक नियंत्रण चाहते हैं, तो आप कुछ इस पर विचार कर सकते हैं:

def handle # just an example name, use what speaks to you
    raise $! unless $!.kind_of? NoMethodError # Do whatever checks or 
                                              # reporting you want
end
# then you may use
@myvar = session[:comments][@comment.id]["temp_value"] rescue handle