Rails - Displaying Foreign Key References in a form
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 videos on Youtube
Ricky
Updated on June 04, 2022Comments
-
Ricky almost 2 years
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 errorundefined method 'Ice Hockey' for #<Team:0x3e7e040>
... Any ideas how to properly display name from here?? -
Ricky almost 11 yearsThanks @MrYoshiji. I'm trying your first suggestion to start, and the values correctly appear in the select box. However, I'm getting a
ActiveModel::MassAssignmentSecurity::Error
when trying to save, it's sayingCan't mass-assign protected attributes: sport_id
-
Ricky almost 11 yearsI got it working by adding
:sport_id
to my attr_accessors for the teams_controller. Was this the correct way to do it? Also, I tried the 2nd method, and it works, but I don't understand why. What isSport.scoped
do? Why is it only required in theedit
method? Example, thenew
method also shares the same_form.html.erb
view yet, yet I do not make a call to@sports = Sport.scoped
in there but it still works... Thanks for any insight