Как я могу решить неопределенный метод `[] 'на Ruby? - PullRequest
1 голос
/ 15 марта 2020

Я пытаюсь получить утверждение if для пользователей, которые указали неверные данные.

Вот мой код:

class Breweries::CLI

  def start 
    puts "Hello!"
    puts "---------------------------"
    puts "Please enter your location:"
    input = gets.strip.downcase
    @data = Breweries::API.get_breweries(input)
    @objects = Breweries::HoppyCode.all 
    if input.length < 1 
      puts "Sorry!!" 
      puts "```````"
      start
    else 
      display_info 
    end
  end 

  def display_info 
    puts "You'll love the following spots!"
    puts "********************************"
    @objects.each.with_index(1) {|brewery, index| puts "#{index}. #{brewery.name}"}  
    puts  "Please make a selection by index number for more information:"
    input = gets.strip.downcase
    if(input.to_i > 0)
      @brewery = @objects[input.to_i - 1]
      puts "name: #{@brewery.name}"
      puts "street: #{@brewery.street}"
      puts "city: #{@brewery.city}"
      puts "phone: #{@brewery.phone}"
      puts "website_url: #{@brewery.website_url}"
      display_info
    elsif (input == "quit")
      quit 
    elsif (input == "menu")
      start
    end
  end

  def quit 
    puts "Goodbye. Drink responsibly and enjoy." 
  end   

end

Когда я помещаю что-то, что может вызвать ошибку, он возвращает следующее:

Please enter your location: nvifpejvf80ejvip
 Traceback (most recent call last):
 2: from bin/breweriesCLI:6:in `<main>'
 1: from /home/munificent-format-5297/Development/breweries/lib/breweries/cli.rb:8:in `start' /home/munificent-format-5297/Development/breweries/lib/breweries/api.rb:6:in `get_breweries': undefined method `[]' for nil:NilClass (NoMethodError)

Как я могу решить неопределенный метод '[]' ошибка? Вот код API на случай, если это необходимо.

class Breweries::API

  def self.get_breweries(input)
    @breweries_hash = HTTParty.get("https://api.openbrewerydb.org/breweries?by_city=#{input}")
    breweries_obj = {
      name: @breweries_hash[1]["name"],
      street: @breweries_hash[3]["street"],
      city: @breweries_hash[4]["city"],
      phone: @breweries_hash[10]["phone"],
      website_url: @breweries_hash[11]["website_url"]
    }
    Breweries::HoppyCode.new(breweries_obj)
  end 

end 

Ответы [ 2 ]

1 голос
/ 15 марта 2020

Выявление проблемы

Существует множество способов решения проблемы с нулем, но на первый взгляд кажется, что часть проблемы здесь в том, что вы как-то ожидаете input чтобы вернуть действительный объект Ha sh из вашего вызова API, но пустая строка или экземпляр FalseClass могут этого не делать. Рассмотрим следующее:

input = gets.strip.downcase # <RETURN> here gets an empty string
input                       #=> ""
input.to_i > 0              #=> false

Затем учтите, что некоторые последующие потоки Breweries :: API.get_breweries ожидают работать вместо объекта Ha sh вместо экземпляра NilClass. В этом случае это выглядит как @breweries_hash[1]["name"] и другие операции над @breweries_hash.

Некоторые параметры

Не зная больше о вашем коде, я не не хочу быть предписывающим здесь. Но в целом вы можете выполнить одно или несколько из следующих действий:

  • Привести аргументы к ожидаемому классу в вызове метода, сигнатуре метода или теле метода. Например, для объектов Array:

    # coerce a String to an Array, raising an exception if it can't
    input = ""
    Array(input)
    #=> [""]
    
    # coerce some Array to a Hash
    array = [:name, "foo", :street, "bar"]
    Array(array.each_slice 2).to_h
    #=> {:name=>"foo", :street=>"bar"}
    
  • Явно проверьте наличие объекта Ha sh:

    fail "@breweries is not a Hash" unless @breweries.is_a? Hash
    
  • Raise исключение вместо возврата 0, если input на самом деле не является действительным целочисленным представлением:

    input = Integer(gets.strip.downcase)
    
  • Проверьте, есть ли у вас Ha sh или объект Array отвечает на соответствующие вызовы метода и вызывает более полезное сообщение об исключении:

    raise sprintf("@brewery: %s", @brewery.class) unless @brewery.respond_to? :[]
    

Есть и другие вещи, которые вы могли бы сделать также. Вообще говоря, вам нужно изменить свой код, чтобы проверить возвращаемое значение вашего вызова, чтобы убедиться, что он не равен нулю, а затем соответствующим образом переходить / поднимать / спасать в зависимости от того, ожидаете ли вы когда-либо nils действительного возвращаемого значения. от Breweries :: API.get_breweries.

Примечание по использованию исключений для неисключительных обстоятельств

Как правило, вы должны вызывать исключения только для действительно неожиданных обстоятельств или когда программа должен быть остановлен, потому что некоторые условия не могут (или не должны) обрабатываться в программе во время выполнения. Что лучше в вашем конкретном случае использования, действительно является дизайнерским решением и выходит за рамки первоначального вопроса. Однако вы можете прочитать Exceptional Ruby от Avdi Grimm для более глубокого объяснения того, когда исключения могут быть лучше, чем ветвление или обработчики (или наоборот), но выбор в вашем коде немного левее центра. проблемы, с которой вы на самом деле сейчас сталкиваетесь.

1 голос
/ 15 марта 2020

Когда ввод недопустим, вызов

@breweries_hash = HTTParty.get("...")

возвращает не тот объект, который вы ожидаете (я бы посоветовал вернуть пустой ха sh.), Что делает невозможным получение деталей в следующих строках. В зависимости от того, как вы справитесь с этим, вы можете решить, например, досрочно вернуться из этой функции, или raise, или сделать что-то еще.

Чтобы подойти к этому, начните с отладки проблемы, например:

@breweries_hash = HTTParty.get("...")
puts @breweries_hash.inspect
...

Таким образом, вы увидите, что возвращается, и получите представление о том, как с этим справиться.

Если я прав, и то, что возвращается, является пустым ха sh, возможно, вы захотите досрочно вернуться из этой функции.

@breweries_hash = HTTParty.get("...")
return if @breweries_hash.empty?
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...