2

I'm a newbie and this is for the Rails tutorial by Richard Schneeman. This is all that is in my index.html.erb file in my view/products folder.

<% first_product = Product.first %>
<% lots_of_products = Product.includes(:user).all %>
<ul>
  <% lots_of_products.each do |product| %>
    <li>
      Product Name: "<%= product.name %>"" costs $<%= product.price %>
      Sold by <%= product.user.name %>
    </li>
  <% end %>
</ul>

The issue is with <%= product.user.name %>, which gives the error:

NoMethodError in Products#index undefined method `name' for nil:NilClass.

My controller files are vanilla and my routes.rb has:

ControllerExercise::Application.routes.draw do
  get '/products' => 'products#index'
  resources :users
end

This is in the models:

class Product < ActiveRecord::Base
  belongs_to :user
  attr_accessible :name, :price
end

class User < ActiveRecord::Base
  has_many :products
  attr_accessible :job_title, :name
end

Any and all help is greatly appreciated.

atw
  • 5,428
  • 10
  • 39
  • 63
ltrainpr
  • 3,115
  • 3
  • 29
  • 40

4 Answers4

13

You can also try

product.user.try(:name)
Aditya Kapoor
  • 1,542
  • 10
  • 13
  • Thank you very much. Your answer works as well. It's a shame I can't vote your answer up. I don't have the 15 pts of reputation. – ltrainpr Apr 22 '13 at 20:51
8

In your database i suspect some of your product data does not contain sold_by_id or user_id. So its getting product.user nil as no user is associated with the product. Instead of

<%= product.user.name %>

use

<%= product.user.name if product.user %>

to skip this exception.

So your index.html.erb becomes

<% lots_of_products = Product.includes(:user).all %>
<ul>
  <% lots_of_products.each do |product| %>
<li>
  Product Name: <%= product.name %> costs $<%= product.price %>
  Sold by <%= product.user.name if product.user %>
</li>
<% end %>
</ul>
user2284458
  • 106
  • 2
  • Thank you very much! So frustrating to be working on something for an hour or two just to find out it was right there in front of me the whole time. – ltrainpr Apr 22 '13 at 18:53
0

I also came up against this and used a simple if else statement, because I still wanted to show something even if the username didn't exist

<!-- SHOW USERNAME IF IT EXISTS -->

<% if product.user %>
   <p><strong><%= product.user.name %></strong></p>
<% else %>
   <p><strong>Anonymous</strong></p>
<% end %>
0

A great workaround to this is ruby's safe access operator &.

see http://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/

It was invented by Matz (ruby's founder) for this very situation. In your case it would look like

product.user&.name

It returns nil if the name attribute is not defined. Keep in mind its only available in ruby 2.3.0 and higher.

sakurashinken
  • 3,940
  • 8
  • 34
  • 67