Search code examples
ruby-on-railsrubyapiwunderground

Ruby on Rails: Getting Form Input to Model


I'm still learning more about Rails and I'm starting to play around with APIs, but I can't seem to figure out how to get an input from a form to the Model.

I want to take the User input (in the form of a zip code) and have it spit out the weather info at that user location.

Form on home.html.erb

<%= form_tag(root_path) do %>
  <%= label_tag :zip, "ENTER YOUR ZIPCODE TO FIND YOUR WEATHER"  %><br>
  <%= text_field_tag :zip,'', placeholder: "e.g. 91765 " %>
  <%= submit_tag "show me the weather!" %>
<% end %>

Controller pages_controller.rb

class PagesController < ApplicationController

  def home
    @weather_lookup = WeatherLookup.new(params[:zip])
  end
end

Model weather_lookup.rb

class WeatherLookup
  attr_accessor :temperature, :weather_condition, :city, :state, :zip

  def initialize(zip)
    self.zip = zip
    zip = 91765 if zip.blank?
    weather_hash = fetch_weather(zip)
    weather_values(weather_hash)
  end

  def fetch_weather(zip)
    p zip
    HTTParty.get("http://api.wunderground.com/api/API-KEY-HERE/geolookup/conditions/q/#{zip}.json")
  end

  def weather_values(weather_hash)
    self.temperature = weather_hash.parsed_response['current_observation']['temp_f']
    self.weather_condition = weather_hash.parsed_response['current_observation']['weather']
    self.city = weather_hash.parsed_response['location']['city']
    self.state = weather_hash.parsed_response['location']['state']
  end
end

I'm not exactly sure how to get the input from the form to the model. This is literally just to show the weather. I'm not trying to save anything in a database


Solution

  • The form helper defaults to "POST" if you don't provide a method. From the looks of your controller, "GET" is what you want. Here's some documentation to provide additional context. The updated form:

    <%= form_tag(root_path, method: "get") do %>
        <%= label_tag :zip, "ENTER YOUR ZIPCODE TO FIND YOUR WEATHER"  %><br>
        <%= text_field_tag :zip,'', placeholder: "e.g. 91765 " %>
        <%= submit_tag "show me the weather!" %>
    <% end %>
    

    Next, if you try to instantiate your @weather_lookup variable without params[:zip], Rails will throw an error. Adding a conditional to your controller will solve this:

    class PagesController < ApplicationController
    
      def home
        if params[:zip]
          @weather_lookup = WeatherLookup.new(params[:zip])
        end
      end
    
    end
    

    Be sure your routes are set up. Something defining root should exist in routes.rb. For example:

      root "pages#home" 
    

    I believe you also have to parse the JSON into a hash inside your model. Adding that to the weather_values method:

      def weather_values(weather_json)
        weather_hash = JSON.parse weather_json
        self.temperature = weather_hash.parsed_response['current_observation']['temp_f']
        self.weather_condition = weather_hash.parsed_response['current_observation']['weather']
        self.city = weather_hash.parsed_response['location']['city']
        self.state = weather_hash.parsed_response['location']['state']
      end
    

    Finally, be sure you're referencing @weather_lookup somewhere in your view, else the data won't show. A simple, unformatted example:

    <%= @weather_lookup %>
    

    Assuming the logic works in your model, the JSON should render after you submit a ZIP code via the form. I don't have an API key else I would have tested this myself.