Rails - Displaying Foreign Key References in a form

13,911

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:

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]
Share:
13,911

Related videos on Youtube

Ricky
Author by

Ricky

Updated on June 04, 2022

Comments

  • Ricky
    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 enter image description here

    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??

  • Ricky
    Ricky almost 11 years
    Thanks @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 saying Can't mass-assign protected attributes: sport_id
  • Ricky
    Ricky almost 11 years
    I 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 is Sport.scoped do? Why is it only required in the edit method? Example, the new 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