I have the following models:
class League < ApplicationRecord
has_many :games
end
class Game < ApplicationRecord
belongs_to :league
end
In my user's show.html.erb
I'm trying to display a user's games and the league associated with the game via this snippet game.league.title
and this is the view:
<div class="hidden text-center" id="tab-settings">
<% current_user.games.each do |game| %>
<ul>
<li class="w-1/2 mb-4 text-left border-2 rounded-md border-coolGray-900">
<p class=""><%= game.start_time&.strftime("%a %b %d, %Y %l:%M%P") %> - <%= game.end_time&.strftime("%l:%M%P") %></p>
<p class="mb-2"><%= game.league.title %> - <%= game.home_team %> vs <%= game.away_team %></p>
</li>
</ul>
<% end %>
</div>
game.league.title
returns undefined method "title" for nil:NilClass
error; however, when I go into the console, game.league.title
querys perfectly.
Following the advice given here, I tried the following in the view:
<p class="mb-2"><%= game.league.try(:title) %> etc...</p>
and it works perfectly.
Why does game.league.try(:title)
work but game.league.title
return an error?
You have bad data. If you want to be able to call game.league
without potential nil errors you need the games.league_id
column to be defined as NOT NULL
. Game.where(league_id: nil)
will give you a list of the records with nulls.
Since Rails 5 belongs_to
applies a presence validation to the column by default. This however doesn't prevent null values from sneaking in anyways if you use any of the methods that circumvent validations. Or if the records were created outside of Rails or even in an older version of Rails.
If you want league to be nullable you can use the safe navigation operator:
<p class="mb-2"><%= game.league&.title %> etc...</p>
Object#try
is an ActiveSupport method that predates the safe navigation operator which was introduced in Ruby 2.3. While it does have its uses the operator generally should be preferred.
You can also use Module#delegate:
class Game
# ...
delegate :title, to: :game, allow_nil: true, prefix: true
end
<p class="mb-2"><%= game.league_title %> etc...</p>