Storing user input value in controller - ruby-on-rails

I have a controller named Welcome with view called index.
In my index view i have created a small form as such.
<%= form_for :location do |f| %>
<%= f.label :Longitude %><br>
<%= f.text_field :integer %>
<br>
<br>
<%= f.label :Latitude %><br>
<%= f.text_field :integer %>
<p>
<%= f.submit %>
</p>
<% end %>
In this form the user can enter some integer value for longitude and latitude. Once the user enters value for longitude and latitude. They click submit. Upon submit i would like to store these values in my controller. So i am using the following method where i have two instance variables taking values from the form.
def index
#long = params[:longitude]
#lat = params[:latitude]
end
In my routes.rb I have
get 'welcome/index'
post 'welcome/index'
Please tell me where i went wrong. Also if someone can suggest a better way of doing this also i would appreciate it i am new to rails and i want to learn the correct way of doing things so i don't create bad habits early on.

The reason it's not working is because your fields are both named :integer, and since they share the same name, the browser will only send one value.
So, with your code, if you filled in the first field with 'a' and the second with 'b', your params would contain something like this:
{ location: { integer: "aaa" } }
Which obviously isn't what you want! If your HTML looked more like this (I've stripped the layout stuff to make things clearer):
<%= form_for :location do |f| %>
<%= f.label :longitude %>
<%= f.text_field :longitude %>
<%= f.label :latitude %>
<%= f.text_field :latitude %>
<%= f.submit %>
<% end %>
Then you could access the params in your controller params[:location][:longitude] and params[:location][:latitude]
A good idea to see the difference between the effect of your form vs this form would be to inspect the html. Take a look at the input name attributes, and label for attributes and see how they match up with the params Rails receives. Also, when you post the form, be sure to look in your server log to see the params! :)

After reading your question, I think you want to see how controllers, views and models work. For learning purpose you can generate scaffold and study the generated code.
For example, generate a model GeoLocation, related controller and views by this:
rails g scaffold GeoLocation longitude:string latitude:string
Now fire up rails server and browse http://localhost:3000/geo_locations/new and save your long, lat. I wrote this answer to give you some guidance.
You can follow these excellent books:
The book of Ruby
The Rails 4 Way

Related

Many-to-many is Rails

I'm doing backend for trello-clone app using Rails. I have board entity which has many column entities which are having many cards entities. I've made board-column part (using blog app example) and it works fine, but I can't understand how to make column-card part of that.
Method create in card controller is like:
def create
#board = Board.find(params[:board_id])
#column = #board.columns.find(params[:column_id])
#card = #column.cards.create(card_params)
end
I've made the form like this for adding cards for each column :
Form code:
<p>
<strong>Name:</strong>
<%= #column.name %>
</p>
<p>
<strong>Color:</strong>
<%= #column.background_color %>
</p>
<h2>Add a card:</h2>
<%= form_with(model: [#board, #column, #column.cards.build], local: true) do |form| %>
<p>
<%= form.label :name %><br>
<%= form.text_field :name %>
</p>
<p>
<%= form.label :description %><br>
<%= form.text_area :description %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
So my question is how to make normal entity adding for the second level of the many-to-many relationship?
Your question is quite ambiguous but I guess you probably are confused about this thing:
Add hidden_field for board_id like:
form.hidden_field :board_id, value: #board.id
Then access it in the controller update/create with something like params[:column][:board_id] (check params to be exact) and relate the column with board id.
You surely are missing this piece but you surely are missing more.
I would suggest using byebug gem and inspecting params hash. It will help you a lot because I think you need to inspect params which are confusing you.
Another way (not good but simpler) to
puts "*"*100
puts params
puts "*"*100
as first line of create action in controller to see how exactly your params are. (Go into console and find whatever is written between 2 lines of asterisks in your server console)
Good Luck!

Ruby on Rails: assign relationship on creation

I'm new to Ruby on Rails. There are two models in my project: room and guest. The association is "room has_many guests" and "guest belongs to room".
I have separated views for manage rooms and guests. Rooms don't require "guests" value on creation. However, I want to create new guests and assign it to certain room at the same time. What will be the proper way to do it? How do I transfer the input from web and match the entities in database.
The code is pretty much the same as "Getting Started with Rails". In the tutorial, they add "comments" in the "article" view and use "comment" as a sub-resource of "article". In my case, I treat the two models equally and want to manage them in separated views.
Update:
I used the collection_select and try to work with my guest_controller.
<%= form_for :guest, url: guests_path do |f| %>
<% if #guest.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#guest.errors.count, "error") %> prohibited this guest from being added:
</h2>
<ul>
<% #guest.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :name %><br>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :phone %><br>
<%= f.text_field :phone %>
</p>
<p>
<%= f.label :room%><br>
<%= f.text_field :room %>
</p>
<p>
<%= f.label :room %><br>
<%= f.collection_select(:room_id, Room.all, :id, :title) %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<%= link_to 'Back', guests_path %>
In my guest_controller, the create method called by the form above is :
def create
#guest = Guest.new(guest_params)
#guest.room = Room.find(params[:room_id])
if #guest.save
redirect_to #guest
else
render 'new'
end
end
However, when I create a new guest, it shows that:
ActiveRecord::RecordNotFound in GuestsController#create
Couldn't find Room with 'id'=
I checked that room_id=4 and Room.find(4) return the proper room.
What's wrong?
If you want to select one room from those that exist, use collection_select form helper, here is a relevant snippet from the docs:
f.collection_select(:city_id, City.all, :id, :name)
This outputs a dropdown list that:
fills in city_id parameter in this context
uses City.all for filling in the options in the list (I will be referring to "each" city as city)
uses city.id as data (that gets sent in the form)
shows city.name for each city in the dropdown list (hopefully, human-readable)
Bear in mind though, that in terms of security it's like "look, you can select this, and this and this!", that does not prevent users from selecting an unlisted option: either by modifying form markup by hand or sending handcrafted queries.
So should you ever be limiting access to specific rooms, and list only Room.unlocked (unlocked assumed a scope), make sure the received room_id refers to a room from that scope as well. Most of these problems are dealt with using either validations or careful association management (Room.unlocked.find_by_id(:room_id) that outputs nil if the room is not in that scope).
UPD: as for the latest problem you're having -- your understanding on how the form contents look in params seems to be wrong. It's quite a common misconception actually.
form_for :guest will construct a separate object/hash in params[:guest], with all the form's fields inside it. So it actually is inside params[:guest][:room_id], but no, don't rush with adding the missing part.
You've already built a #guest object from entire params[:guest], so if the room actually exists, it's inside #guest.room already and can be validated inside the model during save. Have a look at Rails validators.
Take a look at the fields_for tag:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for
It allows just that, to create a guest while creating a room and associating each other.

Submitting default value in text form Ruby on Rails

I'm developing a simple rails app where I want to plot some stock charts. The problem is that when I start my server and load localhost the default value/ticker symbol is not loading which means that I have to type in a ticker in my form for it to work.
I found this thread where I learnt how to write a default value in my form/view, like so:
<%= form_for :find_it do |f| %>
Ticker symbol: <%= f.text_field :string, :value => "JPM" %></br>
<%= f.submit "Find" %>
<% end %>
and that's all fine, but it does not submit the value by default.
So how do I go about fixing this and what is the best practice?
In your input field you have list your attribute as a string, while that is the type, it most likely isn't the actual name of the attribute you wish to save "JPM". So you should change
<%= f.text_field :string, :value => "JPM" %>
to
<%= f.text_field :attribute_name, :value => "JPM" %>
If I copy and paste your form into a Rails app on my machine it does display a text field populated with "JPM", which I believe is correct.
When you hit submit the form will post to a create action with params containing:
"find_it"=>{
"string"=>"JPM"
}
Another thing I noticed is that you have f.text_field :string. This should be the name of your attribute, rather than the type (i'm assuming that you don't have a field called string).

form for helper bad collection

I am useing a form_for helper to collect data on the client side of my application. However something weird is happening. I am not collecting the :name and :description and they are both returning as nil. this is my code:
<%= form_for #type do |f| %>
....
<%= f.text_field :name, :class => "col-xs-4" %>
<%= f.text_field :description, :class => "col-xs-4" %>
<%= f.submit %>
....
Do I need to make a fields_for under the form_for to get this working? It is a bit tricky because I am using #type which in this case is set up to tell the view which kind of attr. they are looking at. For example, this line:
<%= f.label #type %> <label> Description</label>
depending on what view you are on shows ether:
Group Description
or
Tag Description
and because they are both technically the same, I am using the same index for both. I hope I am clear with my issue and thank anyone who understands my problem and solution.
The param name will depend on the object you pass.
If #type contains an instance of Group, then you will get the params under params[:group], and if it is an instance of Tag, the you will get them on params[:tag]
<%= form_for #type do |f| %>
<%= f.label :name, "#{#type.model_name} Description" %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
Note the label definition. The way you are defining it will create 2 labels and the second one will not be linked to any field.
fields_for is normally used when you are creating several objects within the same form, for instance a Project and several tasks associated to it.
Hope this helps.
update:
If #type is a string or symbol it should work too. The tradeoffs using this approach will be that if there are any validation errors when creating the object, those will not be displayed and the fields will not be prefilled with the input that the user gave before submitting the form, forcing the user to enter all the information again and guessing which was the validation error (you can initialize it from the received params, but that complicates the code readability)
The unique thing different in your view would be the label definition.
<%= f.label :name, "#{#type} Description" %>

lat/long Coordinate insertion with form_for in Rails

I'm using Rails 4.4.1, Ruby 2.1.2, RGeo 0.3.20 and activerecord-mysql2spatial-adapter 0.4.3
My problem is probably very simple since I'm new to both Ruby and Rails, but I could not find anything useful in the web so far.
I want to create a form to insert geo-spatial coordinates in my db, but I don't know how to access the :latlon fields x and y. This is my tentative code:
<h1>Inserimento nuova Città</h1>
<%= form_for #city, url: cities_path do |city| %>
<p>
<%= city.label :name, "Nome"%><br>
<%= city.text_field :name %>
</p>
<p>
<%= city.label :latlon, "Coordinate GPS" %><br>
<%= city.number_field :latlon.x %><br>
<%= city.number_field :latlon.y %><br>
</p>
<% end %>
The error I get when I access the localhost:3000/cities/new url is
undefined method `x' for :latlon:Symbol
Anyone knows how do I create a form to insert the latlon.x and latlon.y data in my db?
You can't call city.number_field :latlon.y because here :latlon is just a symbol - it's telling the helper to call the "latlon" method, and to set the name to "city[latlon]".
One way to get around this is to add get and set methods for the individual x/y values. These may exist already, added by the gem, i don't know as i've not used it. But you could add
class City < ActiveRecord::Base
def latlon_x
self.latlon.x
end
def latlon_y
self.latlon.y
end
def latlon_x=(num)
self.latlon.x = num
end
def latlon_y=(num)
self.latlon.y = num
end
Now you could say, in your form,
<%= city.number_field :latlon_x %><br>
<%= city.number_field :latlon_y %><br>
this will use latlon_x to get the value, and will cause latlon_x= to be called when you do #city.update_attributes(params[:city]) in your update action.

Resources