我在控制器操作中有很多实例变量,我试图将它们移到外观中,但是遇到了错误。我是Rails的新手,所以有点麻烦。
我的应用程序联系Open Weather API,并返回一些天气参数(温度,风,湿度等)。该API调用是在服务类中处理的,我正在尝试使用Facade模式,并在PORO中使用一些方法来组织返回的数据,然后将这些数据呈现在我的视图中。目前,我收到了NameError. undefined local variable or method 'temperature' for ForecastsController
。我对此并不陌生,因此不胜感激!我的代码在下面。
app / 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
app / facades / forecasts_facade.rb
class ForecastsFacade
def initialize(temperature, weather_code, description, wind, humidity)
@temperature = temperature
@weather_code = weather_code
@description = description
@wind = wind
@humidity = humidity
end
def temperature
@temperature = @forecast.dig('main', 'temp').to_i - 273
end
def weather_code
@weather_code = @forecast.dig('weather', 0, 'id').to_i
end
def description
@description = @forecast.dig('weather', 0, 'description')
end
def wind
@wind = @forecast.dig('wind', 'speed').to_i
end
def humidity
@humidity = @forecast.dig('main', 'humidity')
end
end
app / controllers / forecasts_controller.rb
class ForecastsController < ApplicationController
TOKEN = Rails.application.credentials.openweather_key
def current_weather
@city = params[:q]
if @city.nil?
@forecast = {}
else
@forecast = OpenWeatherApi.new(@city, TOKEN).my_location_forecast
end
@forecasts_facade = ForecastsFacade.new(temperature, weather_code, description, wind, humidity)
end
end
app / views / forecasts / current_weather.html.erb
<div class="page-wrapper">
<h1 class="title">The weather in GIFs</h1>
<div class="search">
<%= form_tag(current_weather_forecasts_path, method: :get) do %>
<%= text_field_tag :q, nil, placeholder: "Enter a city", class: "search-field" %>
<%= button_tag type: 'submit', class: "search-button" do %>
<i class="fas fa-search"></i>
<% end %>
<% end %>
</div>
<% if @forecasts_facade.forecast.dig('cod').to_i == 404 %>
<p>Please use a valid city name!</p>
<% elsif @forecasts_facade.forecast.dig('cod').to_i == 400 %>
<p>Please type in a city name!</p>
<% elsif @forecasts_facade.forecast == {} %>
<% else %>
<p class="weather-description"><%= "#{@forecasts_facade.city.capitalize}: #{@forecasts_facade.description}" %></p>
<div class="gif-container"><%= image_tag(find_gif_url, class: "gif") %>
<span class="temperature weather-attribute"><%= "#{@forecasts_facade.temperature}°C" %></span>
<span class="wind weather-attribute"><%= "wind:#{(@forecasts_facade.wind * 3.6).to_i}km/h" %></span> <!-- converts to km/hr -->
<span class="humidity weather-attribute"><%= "humidity:#{@forecasts_facade.humidity}%" %></span>
</div>
<% end %>
</div>
app / helpers / forecasts_helper.rb
module ForecastsHelper
GIFS = {
thunder:
{codes: [200, 201, 202, 210, 211, 212, 221, 230, 231, 232],
urls: %w(
https://media.giphy.com/media/26uf5HjasTtxtNCqQ/giphy.gif
https://media.giphy.com/media/vS09bj1KrXwje/giphy.gif
https://media.giphy.com/media/l41YsrmiyeNZtmecw/giphy.gif
)},
light_rain:
{codes: [300, 301, 302, 310, 311, 312, 313, 314, 321, 500, 501, 520, 521],
urls: %w(
https://media.giphy.com/media/xT9GEz2CeU9uaI2KZi/giphy.gif
https://media.giphy.com/media/l0Expn6D0D3g9NExq/giphy.gif
https://media.giphy.com/media/14d8cRr25KPxbG/giphy.gif
)},
def find_gif_url
GIFS.each do |key, value|
if value[:codes].include? @weather_code
return value[:urls].sample
end
end
end
end
答案 0 :(得分:2)
我相信您希望您的控制器看起来更像:
class ForecastsController < ApplicationController
TOKEN = Rails.application.credentials.openweather_key
def current_weather
@city = params[:q]
if @city.nil?
@forecast = {}
else
@forecast = OpenWeatherApi.new(@city, TOKEN).my_location_forecast
end
@forecasts_facade = ForecastsFacade.new(@forecast)
end
end
然后,您的ForecastsFacade
更像:
class ForecastsFacade
attr_accessor *%w(
forecast
).freeze
def initialize(forecast)
@forecast = forecast
end
def temperature
@temperature = forecast.dig('main', 'temp').to_i - 273
end
def weather_code
@weather_code = forecast.dig('weather', 0, 'id').to_i
end
def description
@description = forecast.dig('weather', 0, 'description')
end
def wind
@wind = forecast.dig('wind', 'speed').to_i
end
def humidity
@humidity = forecast.dig('main', 'humidity')
end
def invalid_city?
forecast.dig('cod').to_i == 404
end
def missing_city?
forecast.dig('cod').to_i == 400
end
end
然后,在您看来,做类似这样的事情似乎很奇怪:
@forecasts_facade.forecast.dig('cod').to_i == 404
要点是要在view
中隐藏此详细信息。因此,也许更像是:
<div class="page-wrapper">
<h1 class="title">The weather in GIFs</h1>
<div class="search">
<%= form_tag(current_weather_forecasts_path, method: :get) do %>
<%= text_field_tag :q, nil, placeholder: "Enter a city", class: "search-field" %>
<%= button_tag type: 'submit', class: "search-button" do %>
<i class="fas fa-search"></i>
<% end %>
<% end %>
</div>
<% if @forecasts_facade.invalid_city? %>
<p>Please use a valid city name!</p>
<% elsif @forecasts_facade.missing_city? %>
<p>Please type in a city name!</p>
<% elsif @forecasts_facade.forecast.blank? %>
<% else %>
<p class="weather-description"><%= "#{@forecasts_facade.city.capitalize}: #{@forecasts_facade.description}" %></p>
<div class="gif-container"><%= image_tag(find_gif_url, class: "gif") %>
<span class="temperature weather-attribute"><%= "#{@forecasts_facade.temperature}°C" %></span>
<span class="wind weather-attribute"><%= "wind:#{(@forecasts_facade.wind * 3.6).to_i}km/h" %></span> <!-- converts to km/hr -->
<span class="humidity weather-attribute"><%= "humidity:#{@forecasts_facade.humidity}%" %></span>
</div>
<% end %>
</div>
您似乎没有使用该elsif @forecasts_facade.forecast.blank?
分支。不知道这是怎么回事。