I am creating an application involving one of my passions, movies. I would like my users to be able to select their favorite movies. When running the code from my project, I received the following error message.
Undefined Method: 'favorites' for nil:NilClass
<h1>My Favorites</h1>
<%= @favorites = @user.favorites.to_a %>
<table class = "favorites-table">
<thead>
I was testing out favorites functionality through my work in the console, so I played around with the above code in my favorites.html.erb file.
The only problem with that is I set up the associations and proved I could access that method through rails console.
u = User.first
u.favorites => nil
u.favorites.to_a << Movie.first
This worked in ActiveRecord but not in rails server.
Here are my associations (Movie, User and Favorite)
class Movie < ActiveRecord::Base
belongs_to :user
has_many :favorite_movies
has_many :favorited_by, through: :favorite_movies, source: :user
end
class User < ActiveRecord::Base
has_many :favorites, foreign_key: "user_id", dependent: :destroy
has_many :favorite_movies, through: :favorites, source: :movies
end
class Favorite < ActiveRecord::Base
belongs_to :user
validates :movie_id, presence: true
validates :user_id, presence: true
end
I created these associations through reading the Rails Tutorial chapter 11, but I'm not sure if it works for favorites, and I may have made a couple mistakes.
Here are my important migrations (Movies, Users, Favorites)
class CreateMovies < ActiveRecord::Migration
def change
create_table :movies do |t|
t.string :title
t.string :director
t.string :genre
t.integer :movie_id # Potential land-mine
t.integer :release_date
t.integer :reviewed
t.integer :stars
t.timestamps
end
end
end
My User Migration file
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.integer :user_id # Potential land-mine. Users already have separate ID column (primary key)
t.string :name
t.string :password
t.string :email
t.timestamps
end
end
end
class CreateFavorites < ActiveRecord::Migration
def change
create_table :favorites do |t|
t.integer :user_id
t.integer :movie_id
t.timestamps
end
add_index :favorites, :user_id
add_index :favorites, :movie_id
add_index :favorites, [:user_id, :movie_id], unique: true
end
end
Here are my routes
resources :movies do
put :favorite, on: :member
end
resources :users
I have a Favorites method defined in my Users controller but I have nothing inside it. Here is my controller
class UsersController < ApplicationController
before_action :signed_in_user, only: [:edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
def index
@users = User.all
end
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
flash[:success] = "Congratulations #{@user.name}! You have successfully created an account"
redirect_to @user
else
render 'new'
end
end
def update
end
def destroy
end
def favorites
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation) # Potential Land-mine
end
def signed_in_user
unless signed_in?
store_location
redirect_to signin_url notice: "Please sign in."
end
end
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
end
I think the problem might lie with my use of ids. I have two ids for both users and movies (user_id, id, movie_id, id).
I have read various documentation, some similar questions on Stack Overflow and the Rails Tutorial to come up with my code, but I'm really confused. I'm not sure what I'm doing wrong, and I would like to better understand associations.
Any help is greatly appreciated.
Your @user
value is nil because you haven't defined it in your controller for the related method.
Fix
In the controller,add this line @user = User.find(params[:id])
to favorites
method as below
def favorites
@user = User.find(params[:id])
end