Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails - Displaying Foreign Key References in a form

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

like image 476
Ricky Avatar asked May 31 '13 02:05

Ricky


People also ask

How do I add a foreign key reference in rails?

Now, if you use the special generator syntax for migrations, Rails 4.2 will automatically create the correct migration with foreign key constraints included. rails g migration AddUserToUploads user:references produces add_reference :uploads, :user, index: true, foreign_key: true in the appropriate migration. Use ...

Is references the same as foreign key?

The only and most important difference between the two keywords 'FOREIGN KEY" and "REFERENCES" keywords is though both of them make the data to be child data of the parent table, the "FOREIGN KEY" is used to create a table level constraint whereas REFERENCES keyword can be used to create column level constraint only.

Do you need foreign keys in Rails?

Foreign keys ensure consistency between related database tables. The current database review process always encourages you to add foreign keys when creating tables that reference records from other tables. Starting with Rails version 4, Rails includes migration helpers to add foreign key constraints to database tables.

Can a foreign key reference another foreign key?

A foreign key can reference any field defined as unique. If that unique field is itself defined as a foreign key, it makes no difference. A foreign key is just to enforce referential integrity.


1 Answers

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]
like image 91
MrYoshiji Avatar answered Oct 21 '22 17:10

MrYoshiji