Rails - Displaying Foreign Key References in a form - ruby-on-rails

I'm doing a simple exercise with two models. Sport and Teams, defined as
rails g scaffold sport name:integer
rails g scaffold team name:integer fans:integer sport:references
(Note: The reason I'm using scaffold is rapidly prototyping so I can learn/experiment with the parts I'm not familiar with yet)
Problem is that my "sport" (i.e. the foreign key reference) is showing like the following
So it's got that weird #<blahl blah> notation to it...
<%= form_for(#team) do |f| %>
<% if #team.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#team.errors.count, "error") %> prohibited this team from being saved:</h2>
<ul>
<% #team.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :fans %><br />
<%= f.number_field :fans %>
</div>
<div class="field">
<%= f.label :sport %><br />
<%= f.text_field :sport %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I've tried changing the one line to #team.sport.name but it results in an error undefined method 'Ice Hockey' for #<Team:0x3e7e040>... Any ideas how to properly display name from here??

You are using a text_field for referencing an existing object, a select with Sports as options would be more appropriate here.
This is where it has to be changed:
<div class="field">
<%= f.label :sport %><br />
<%= f.text_field :sport %>
</div>
To:
<div class="field">
<%= f.label :sport %><br />
<%= f.select :sport_id, options_for_select(Sport.all.map{|s|[s.name, s.id]}) %>
</div>
The f.select will generate a select box in HTML, the options will me all the sports in your DB.
Some documentation about it:
http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/select
http://guides.rubyonrails.org/form_helpers.html#select-boxes-for-dealing-with-models
A cleaner way would be to set a variable #sports in your controller and call it then in your views:
# in controller
def edit
#sports = Sport.scoped
#...
# in edit view
<div class="field">
<%= f.label :sport %><br />
<%= f.select :sport_id, options_for_select(#sports.map{ |s| [s.name, s.id] }) %>
</div>
Additionnal information: If you want to "pre-select" an option for the select, you have to pass it as the second argument of the options_for_select helper:
options_for_select(#sports.map{ |s| [s.name, s.id] }, params[:sport_id])
# this will select by default the option that matches the value of params[:sport_id]

Related

Rails - add an array of another class on a form

I apologise if the question is quite simple, I'm fairly new to Rails. I'm building a meal planner application, and am trying to have it so that a user can create a meal, and add items to that meal. E.g. a meal of 'fish & chips' would include the items 'fish' and 'chips'. As I understand it, I think I need a way of creating an array of items on the meal creation form - but how do I do that?
Relevant parts of meal.rb:
has_many :items
accepts_nested_attributes_for :items
and item.rb
belongs_to :meal
What do I need to add to the meal form partial for it to accept an array of items? I apologise, I have no idea where to start! Alternatively, if there is a simpler way of doing it, please let me know. But I don't want to have a list of 'item_1_id', 'item_2_id' etc on the meal!! Thanks!!
<%= form_for(#meal) do |f| %>
<% if #meal.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#meal.errors.count, "error") %> prohibited this meal from being saved:</h2>
<ul>
<% #meal.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :category %><br />
<%= f.text_field :category %>
</div>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :child_id %><br />
<%= f.number_field :child_id %>
</div>
<div class="field">
<%= f.label :time %><br />
<%= f.date_select :time %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
There is a great railscast episode that covers this. Also, you would want to use javascript to have a "add item" link. This example below, will always have one new item available.
You would want to do something like this
view
<%= f.fields_for :items do |builder| %>
<fieldset>
</fieldset>
<% end %>
controller
#meal.items.build
http://railscasts.com/episodes/196-nested-model-form-part-1
http://railscasts.com/episodes/197-nested-model-form-part-2

Passing User_ID through new_item form

I have a simple app that allows users to create 'items'. On the _form, the only data that it asks for is 'content' and 'user_id', which is currently a number picker that assigns user_id to the item for ownership. But what I want to do is have the form assume that the user_id is the current user's ID (using Devise). That way other people can't assign 'items' to other users. Make sense? Here's the form.
_form.html.erb
<%= form_for(#item) do |f| %>
<% if #item.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#item.errors.count, "error") %> prohibited this item from being saved:</h2>
<ul>
<% #item.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_field :content %>
</div>
<div class="field">
<%= f.label :user_id %><br />
<%= f.number_field :user_id %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
You should be working with associations from the model.
example your Items model should have belongs_to :user
then your would just use the :user method not the user_id attribute.
But you really could make this much more simpler.
install simple_forms gem it will make your life easier.
gem "simple_form"
then
<%= simple_form_for(#item) do |f| %>
<%= f.input :content %>
<%= f.association :user %>
<%= f.button :submit %>
<% end %>

checkbox in form associated with Model in Ruby on rails

I have a Model "Startup" and I have a other Model "Categorie". The two tables are associated.
I'd like call the data of Categoria through to form of Startup, this categories displayed with a checkbox. Inside the form Startup Form I have the categorie_id. This is the code
<%= form_for(#startup) do |f| %>
<% if #startup.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#startup.errors.count, "error") %> prohibited this startup from being saved:</h2>
<ul>
<% #startup.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.collection_select :round_id, Round.order(:name), :id, :name, include_blank: true %>
</div>
<div class="field">
<%= f.label :category %><br />
<%= f.text_field :category_id %>
</div>
<div class="field">
<%= f.collection_select :country_id, Country.order(:name), :id, :name, include_blank: true %>
</div>
<div class="actions">
<%= f.submit %> </div> <% end %>
How to display the data of Categories within form with a checkboxs ?
Any idea.
pdt: My english is really bad.
If a Startup can have only one Category, you can do like this in your view:
<div class="field">
<%= f.label :category %><br />
<%= f.collection_select :category_id, Category.all, :id , :name %>
</div>
This will output a dropdown menu with all the categories. Make sure that the Category model has the attribute name.
As you said, a Startup belongs to one Category, so using radiobuttons (checkboxes are here for multiple relation, means you could choose multiple categories):
<div class="field">
<% Category.all.each do |category| %>
<%= f.radio_button :category_id, category.id %>
<%= f.label :category_id, category.name %>
<% end %>
</div>
You may have to add <br /> tags, and html options to make it looks better.
As MrYoshiji says, you can use:
It will display the category name on the screen, and the value sent will be the id.
You can find more details here : http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select
I advise you to use the simple_form gem to generate your form. It's a very simple gem to use and customize ! look at it ;)

Rails - Use the same form with new/edit using fields_for

I have 5 models,
Person
person_car
car (has many tires)
person_car_tire
tire (belongs to car)
so I have this view
_form.html.erb
<%= form_for(#person) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div>
<% Car.all.each do |c|%>
<div class="field">
<%= f.fields_for(:person_cars) do |ff|%>
Car Name: <%= ff.check_box :car_id %>|<%= c.car_name%>
<% c.tires.each do |b|%>
<div class="field">
<%= ff.fields_for(:person_car_tires) do |fff|%>
Tire: <%#= fff.check_box :tire_id%>|<%= b.tire_name%>
<%end%>
</div>
<%end%>
<%end%>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And when I save it works perfectly, the problem comes when I want to edit using this form because it duplicates data of each car 4 times in the view. I've been searching and fields for allows extra options so I made:
<%= form_for(#person) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div>
<% #person.cars.each do |c|%>
<div class="field">
<%= f.fields_for(:person_cars, c) do |ff|%>
Actividad: <%= ff.check_box :car_id %> | <%= c.car.name%>
<% c.person_car_tires.each do |t|%>
<div class="field">
<%= ff.fields_for(:person_car_tires, t) do |fff|%>
Tarea: <%#= fff.check_box :tire_id%>|<%#= t.tire.name%>
<%end%>
</div>
<%end%>
<%end%>
</div>
<%end%>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
and it now works, but only show the cars and tires that I've selected on the new action. not all as I wanted (because if I use the first form it duplicates checkboxes in the view).
How can I use the same form for both actions?
Hope someone can help me.
You can use the same _form partial for both new and edit. You just need to pass local variables set to different values to this form. Basically, whatever differs, abstract it away as a parameter (local variable) to this function-like partial.

ruby on rails app - html5 option tag dynamically generated with sqlite3 table records

I am attempting to create a security model with sqlite3.
This code is inside of the _form.html.erb file inside of ../views/users/
I have a user model & a user_level model ( admin, user, etc ).
rails generate scaffold user_level desc:string
rails generate scaffold user email:string password:string user_level:references
When creating/editing a 'user', i want to be able to select a 'user_level' value from the html5 tag.
I am getting a undefined methoddesc' for nil:NilClass` error when i try to view the page.
<%= form_for(#user) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.text_field :password %>
</div>
<div class="field">
<%= f.label :user_level %><br />
<select id="select_user_level">
<%= #user_level.desc do |desc| %>
<option value = "1"><%= desc %></option>
<% end %>
</select>
<%= f.text_field :user_level %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<%= f.collection_select :user_level, User::USER_LEVEL, :to_s :humanize %>
Then in the Model you should add an Array containing all possible user levels like this:
USER_LEVEL = ["admin", "mod", "user"]
Then it should work and you dont need #user_level anymore

Resources