infinity
infinity

Reputation: 719

Rails Nil Method Issue

I've been borrowing some code from an old ruby on rails 3 app of mine for a new rails 4 app. The code works on the old site, but on the new one it doesn't.

Here's my routes.rb:

scope ':username' do
  resources :recipes
end
get "/:username" => "recipes#index"

Here's my controller index:

def index
   @user = User.find_by_username params[:username]
   @recipes = Recipe.all
end

and my view:

<% @recipes.each do |recipe| %>
  <tr>
    <td><%= recipe.name %></td>
    <td><%= link_to recipe.name, recipe_path(username: @user.username, id: recipe.id) %></td>
    <td><%= link_to 'Edit', edit_recipe_path(recipe) %></td>
    <td><%= link_to 'Destroy', recipe, method: :delete, data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>

but the error pops up:

undefined method `username' for nil:NilClass

but the current user username is set to test so its not nil, and the error shouldn't be popping up.

Thanks for all help!

Upvotes: 0

Views: 110

Answers (2)

Joe Half Face
Joe Half Face

Reputation: 2333

get "/:username"

Here - :username is in position of id

@user = User.find_by_username params[:username]

Here you are trying to find it by params.

Link should look like this http://localhost:3000/user_name/user_name?username=user_name

to find some user, and it is obviously not what you want to achieve.

get "/:id" => "recipes#index"

 @user = User.find(params[:id])

Upvotes: 0

Jim Pedid
Jim Pedid

Reputation: 2780

When you have variables that could be potentially be nil, you should handle the case where they are nil, unless you explicitly wish for it to fail in these circumstances.

The dynamic find_by methods return nil when no records are found. Hence, as alfonso pointed out, you are getting a null value for @user.

In this particular instance, I would question how you are using the username param; if recipes are associated with recipes, then I would set up a has_many :recipes in my user model, and belongs_to :user in my recipe model.

Since the user is the 'parent' here, I would opt to create a recipes action in the UsersController. It seems more logical to me to put the recipes that belong to a user in the user's controller, and access the recipes as a collection from the user.

Alternatively, if you are trying to show recipes associated with a user, I would put the action in the RecipesController, and get the user that belongs to a recipe by using the #user method set up from the belongs_to relationship in the database.

In either case, you'll want to guarantee that the users and/or any recipes are defined before trying to render a page. You might want to display a 501 error or something similar if a user doesn't exist that's trying to be accessed, etc.

If you insist that there should always be a user for a recipe, then you should add that type of validation to the recipes model, so that adding a recipe without a user is disallowed:

validates :user, :presence => true

Sorry if I went a little off tangent.

Upvotes: 1

Related Questions