Как я могу помешать моему методу контроллера Rails вернуть nil на мой взгляд? - PullRequest
0 голосов
/ 06 июня 2019

У меня есть простое приложение, которое вызывает API и возвращает данные о погоде.Пользователь может искать город, и возвращается текущая температура.У меня проблема, хотя, когда поле поиска пустое или город не распознан, я получаю ошибку undefined method [] 'для nil: NilClass`.Вот мой код:

reports_controller.rb

class ForecastsController < ApplicationController
  def current_weather
    @token = Rails.application.credentials.openweather_key
    @city = params[:q]
    if @city == nil
      @forecast = ""
    else
      @forecast = OpenWeatherApi.new(@city, @token).my_location_forecast
    end
  end
end

services / open_weather_api.rb

class OpenWeatherApi
  include HTTParty
  base_uri "http://api.openweathermap.org"

  def initialize(city, appid)
    @options = { query: { q: city, APPID: appid } }
  end

  def my_location_forecast
    self.class.get("/data/2.5/weather", @options)
  end
end

current_weather.html.erb

<%= form_tag(current_weather_forecasts_path, method: :get) do %>
  <%= text_field_tag(:q) %>
  <%= submit_tag("Search") %>
<% end %><br>

<p>Current temperature: <%= @forecast['main']['temp'].to_i - 273 %>°C</p>

Очевидно, что код ['main']['temp'].to_i - 273 не может быть вызван на nil, но как я могу предотвратить @forecast, чтобы он был nil, когда ничего не передается в форме или когда API не распознает город?

Ответы [ 4 ]

1 голос
/ 06 июня 2019

Вы можете попробовать ...

if @city.nil?
  @forecast = {}

Чтобы @forecast всегда отвечал как хеш, а затем, на ваш взгляд, вы можете использовать dig, что позволит вам детализировать хеш дажедля узлов, которых нет ...

<p>Current temperature: <%= @forecast.dig('main', 'temp').to_i - 273 %>°C</p>

Но лучше может быть

<% if @forecast.present? %>
  <p>Current temperature: <%= @forecast.dig('main', 'temp').to_i - 273 %>°C</p>
<% else %>
  <p>You need to select a city!</p>
<% end %>
0 голосов
/ 07 июня 2019

можно попробовать

<p>Current temperature: <%= @forecast['main']['temp'].to_i - 273 if @forcast['main']['temp'].present? %>°C</p>
0 голосов
/ 06 июня 2019

Вы можете просто использовать оператор безопасной навигации (&) перед каждым методом, чтобы предотвратить это.

<p>Current temperature: <%= @forecast['main']['temp']&.to_i - 273 %>°C</p>

См. на этот вопрос и ответы , чтобы узнать о нем больше.

По сути, это предотвращает undefined method for nil:NilClass. если значение пусто / ноль.

0 голосов
/ 06 июня 2019

Используя последний комментарий, вы можете обернуть эту логику в объект просмотра и сделать что-то подобное в качестве опции:

class ForecastsController < ApplicationController
  def current_weather
    @city = params[:q]

    @temperature = ForecastView.new(city).temperature
  end
end

class ForecastView
  DESCRIPTIVE_NAME_HERE = 273

  def initialize(city)
    @city = city
    @token = Rails.application.credentials.openweather_key
  end

  def temperature
    forecast.dig('main', 'temp').to_i - DESCRIPTIVE_NAME_HERE
  end

  private

  attr_reader :city, :token

  def forecast
    return {} if city.blank?

    OpenWeatherApi.new(city, token).my_location_forecast
  end
end

<p>Current temperature: <%= @temperature %>°C</p>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...