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
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.
It seems like you are not hitting your home controller after you hit submit. Make sure you are routing correctly with
root to: 'pages#home'
and add this to your form
<%= form_tag(root_path, method: 'get') do %>
Related
hi so I'm trying to do 2 things, one of them is to basically redirect to a model's ID number so input is "1" and redirects to
localhost:3000/model/1
and the second part is actually doing a search. each model has a text field string for license_no and I want to be able to search and return results
currently, I am not sure how I would combine these into 1 search form if thats possible or if it would require 2 separate search forms
i have a search form with only the license_no field but it always returns no results found...
apologize that the model name isn't in singular, the guide I was using to learn RoR had it that way and everything worked, but I have so many references to renters in my project that it would be a while to find all of them
index.html.erb
<%= form_tag search_renters_path, method: get do |f| %>
<%= text_field_tag :license, nil, placeholder: "License Number" %>
<%= submit_tag 'Search', class: "btn-large" %>
<% end %>
models/renters.rb
class Renters < ActiveRecord::Base
validates_presence_of :license_no
def self.search(params)
renters = Renters.where("license_no LIKE?", "%#{params[:license]}%")
end
end
controller.rb
def search
#renter = Renters.search([params])
end
search.html.erb - snippet
<% if #renter.blank? %>
no results
<% else %>
#show results
<% end %>
editted code
models/renters.rb
def self.search(params)
license_query = "%#{params[:license]}%"
id_query = "%#{params[:id]}%"
renters = Renters.where("license_no LIKE ?", license_query) if params[:license].present?
renters = Renters.where("id LIKE ?", id_query) if params[:id].present?
end
controller
def search
#renter = Renters.search(params)
end
search form
<%= form_tag search_renters_path, method: :get do |f| %>
<%= text_field_tag :license, nil, placeholder: "Driver's License" %>
<%= text_field_tag :id, nil, placeholder: "ID number" %>
<% end %>
I'm trying to use the if present? statements to allow a user to decide whether to input ID No or License No. you don't need to input both just one. currently, if I search for a license no, it returns no results. but when I search for an ID, it returns the relevant result
you can do something like this if you are getting value on params[:licence] from your form submit on your controller action search
controller.rb
def search
#renter = Renters.search(params[:licence])
end
app/models/renters.rb
class Renters < ActiveRecord::Base
def self.search(query)
like_query = "%#{query}%"
renters = Renters.where("id LIKE ? OR license_no LIKE ?", like_query, like_query)
end
end
I have created a controller called insert. Which is defined like this
class InsertController < ApplicationController
def create
end
def show
render plain: params[:insert].inspect
end
end
My create.html.erb file is defined like this
<%= form_for :insert, url: '/insert/show' do |f| %>
<%= f.text_field :fname, placeholder: "Enter First Name" %><br />
<%= f.text_field :lname, placeholder: "Enter Last Name" %><br />
<%= f.submit "Login"%>
<% end %>
routes.rb is as follows
Rails.application.routes.draw do
get '' => 'greeter#hello'
get 'new' => 'insert#create'
post 'insert/show' => 'insert#show'
end
When I am entering the form below
I am having this output
Till now no issues. But I want to render the output like this
What is the way to access those hash key-value pair?
I have seen examples where they are first storing these data to database and then from database they are fetching these. Is it possible to show these value like my intended output?
You can create show.html.erb file
<%= debug(params) %>
And change your show action to just empty method
def show
end
debug method will display params hash with more human readable way.
I'm just trying to get some practice in with rails and have started my first project. I am creating a simple project where personal trainers can register profiles and look for work at gyms.
However when trying to navigate to the new personal trainer page this error pops up:
undefined method `pts_path' for #<#<Class:0x5d14ef8>:0x5690b68>
My personal trainer controller looks like this:
class PersonaltrainersController < ApplicationController
def index
#PT = Pt.all
end
def new
#PT = Pt.new
end
def show
end
def create
end
def contact
end
def edit
end
end
Under the routes file I have:
Rails.application.routes.draw do
resources :personaltrainers
root 'personaltrainers#index'
end
My simple_form looks like:
<%= simple_form_for #PT do |form| %>
<%= form.input :name %>
<%= form.input :age %>
<%= form.input :sex %>
<%= form.input :experience %>
<% end %>
personaltrainers_path GET /personaltrainers(.:format) personaltrainers#index
POST /personaltrainers(.:format) personaltrainers#create
new_personaltrainer_path GET /personaltrainers/new(.:format) personaltrainers#new
edit_personaltrainer_path GET /personaltrainers/:id/edit(.:format) personaltrainers#edit
personaltrainer_path GET /personaltrainers/:id(.:format) personaltrainers#show
PATCH /personaltrainers/:id(.:format) personaltrainers#update
PUT /personaltrainers/:id(.:format) personaltrainers#update
DELETE /personaltrainers/:id(.:format) personaltrainers#destroy
root_path GET / personaltrainers#index
Any help would be greatly appreciated.
Change your form code to:
<%= simple_form_for #PT, url: personaltrainers_path do |form| %>
<%= form.input :name %>
<%= form.input :age %>
<%= form.input :sex %>
<%= form.input :experience %>
<% end %>
undefined method pts_path' raised when simple_form_for trying to make a url from the model(pts it is a pluralized form of the pt model), but your routes have another resource name personaltrainers. All that you need, it's pass explicit url to the form helper, in this case it should be personaltrainers_path according your routes file.
You index and new method should be:
def index
#PT = Personaltrainer.all
end
def new
#PT = Personaltrainer.new
end
Btw, we (ruby devs) have a convention to use small case variable names, underscore in case of more_than_one_word. We use ALL_CAPS for constants.
I am new to Rails, and just working my way through my first solo project, but I seem to be running into a syntax error with a constant not being initialized (Ive gotten several of these, but each seems to have a different cause.....not quite sure how i keep getting the same error with different causes :)):
uninitialized constant DatastringsController::Datastrings
DatastringsController:
class DatastringsController < ApplicationController
def new
end
def create
#datastrings = Datastrings.new(datastrings_params) #ERROR returned on this line
#datastrings.save
redirect_to #datastrings
end
def show
#datastrings = Datastrings.find(params[:id])
end
private
def datastrings_params
params.require(:datastrings).permit(:title, :text)
end
end
I believe my form is correct:
<%= form_for :datastrings, url: datastrings_path do |f| %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :text %><br>
<%= f.text_area :text %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
The main problem you have is here:
<%= form_for :datastrings, url: datastrings_path do |f| %>
form_for really should be populated with an ActiveRecord object, as this allows Rails to build the relative paths it requires correctly.
Although I don't know why this is the case, your current setup is basically trying to render DatastringsController::Datastrings -- primarily because you've not set up your form_for correctly
--
Fix
If you want to create a datastring object, I'd follow convention and do this:
#config/routes.rb
resources :datastrings
#app/controllers/datastrings_controller.rb
Class DatastringsController < ApplicationController
def new
#datastring = Datastring.new
end
def create
#datastring = Datastring.new(datastring_params)
#datastring.save
end
private
def datastring_params
params.require(:datastring).permit(:title, :text)
end
end
#app/views/datastrings/new.html.erb
<%= form_for #datastring do |f| %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
--
YOU ALSO NEED TO NAME YOUR MODELS IN SINGULAR
Looking at it now, it seems that your main issue is likely that you've named your model as a plural.
The reason this will be bad is that when you load Rails, it will load all your models, and consequently, allow you to call them by referencing their class name. If a model is plural, I don't think it will load it correctly, causing the error you've highlighted
If you name your model to the following, it should be better:
#app/models/datastring.rb
Class Datastring < ActiveRecord::Base
end
I don't think my helper method is being accessed when trying to saving to my database. A new instance of Airport is being created but the data I'm expecting from the API is not there. It should bring in the airport's name based on its IATA code the user entered in a form_for in the view.
In other words, "name" is always nil in my db. Therefore doesn't seem like the API is being tapped at all, and name is never sent to the controller to save, which leads me to believe there is no call to the helper for some reason.
If it is actually being called, why is "name" not being filled?
This is my controller:
class AirportsController < ApplicationController
include AirportsHelper
def new
#airport = Airport.new
end
def create
new_airport = Airport.create(params[:airport])
if new_airport.errors.empty?
create_location(params[:airport][:code]) #should call the create_location method in AirportsHelper
redirect_to airport_path(new_airport.id)
else
flash[:notice] = new_airport.errors.full_messages
redirect_to new_airport_path
end
end
def show
#airport = Airport.find(params[:id])
end
end
And here is my helper file:
module AirportsHelper
def create_location(airport_code)
airport = Airport.find_by_code(airport_code) #looks up db based on arpt code
result = Typhoeus.get("https://api.flightstats.com/flex/airports/rest/v1/json/iata/#{airport}?appId=[APP ID]&appKey=[APP KEY]")
result_hash = JSON.parse(result.body)
result_hash['airports'].each do |airport|
#airport_name = airport['name']
end
Airport.update_attributes(name: #airport_name, airport_id: airport.id)
Location.create(name: #airport_name, airport_id: airport.id)
airport.update_attributes(name: #airport_name)
airport.save
end
end
This is my form (built in a partial):
<%= form_for #airport do |f| %>
<%= f.text_field :city, :placeholder => "City" %> <p>
<%= f.text_field :country, :placeholder => "Country" %> <p>
<%= f.text_field :code, :placeholder => "3-letter code" %> <p>
<%= f.text_area :details, :placeholder => "Airport details" %> <p>
<%= f.submit %>
<% end %>
The model has the correct attributes:
class Airport < ActiveRecord::Base
attr_accessible :city, :code, :country, :details, :name
end
I've heard it isn't good practice to call a helper in a controller but I don't know where to put it so that it's called at the right time.
I'm still getting up to speed with Rails so any debugging help would be appreciated!
You've got a typo in your create_location method, with 'aiports' instead of 'airports'.
Figured it out!
Turns out the helper method was working just fine. So anyone looking for problems with their helper modules, this may be a good reference on what a working one looks like.
The problem was with the JSON call as #PeterAlfvin suggested. It was not taking the correct data.
Here's the correct helper method:
module AirportsHelper
def create_location(airport_code)
airport = Airport.find_by_code(airport_code)
result = Typhoeus.get("https://api.flightstats.com/flex/airports/rest/v1/json/iata/#{airport_code}?appId=[APP ID]&appKey=[APP KEY]")
result_hash = JSON.parse(result.body)
result_hash['airports'].each do |airport|
#airport_name = airport['name']
end
airport.update_attributes(name: #airport_name)
airport.save
end
end
Note the string interpolation change in the API get request.