Search code examples
ruby-on-railsrubyhttpartyopenweathermap

Why is my API request returning a 400 response using HTTParty?


I'm creating a simple Rails app that fetches data from the Open Weather Map API and returns the current weather data of the city that is searched for in a form field. I would like an API call to look like this for example:

http://api.openweathermap.org/data/2.5/weather?q=berlin&APPID=111111

I've tested this in Postman with my API key it works fine but with my code it returns "cod":"400","message":"Nothing to geocode"

Can anyone see where I am going wrong? Here is my code.

services/open_weather_api.rb

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

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

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

forecasts_controller.rb

class ForecastsController < ApplicationController
  def current_weather
    @forecast = OpenWeatherApi.new(@options).my_location_forecast
  end
end

current_weather.html.erb

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

<%= @forecast %>

routes.rb

Rails.application.routes.draw do
  root 'forecasts#current_weather'
  resources :forecasts do
    collection do
      get :current_weather
    end
  end
end

Solution

  • The error describes itself:

    "cod":"400","message":"Nothing to geocode"
    

    it means that you didn't provide it the city in your query. One possible cause of this error is that you are overriding the default value in your initialize method with the @options variable from the controller in this line:

    class ForecastsController < ApplicationController
      def current_weather
        @forecast = OpenWeatherApi.new(@options).my_location_forecast
      end
    end
    

    From the information you provided, you've not defined the @options variable in your controller or it is nil. So this is overriding the default value of the initialize method in OpenWeatherApi . Since the appid in your case will not change, only the city name will change so you can send it from controller.

    def current_weather
      @city = params[:city] // the city you want to send to API. Change it with your value
      @forecast = OpenWeatherApi.new(@city).my_location_forecast
    end