Search code examples
ruby-on-railsdatabaseactiverecordassociationsfavorites

Active Record Associations Errors


I'm creating a web application that features a database of recipes. I am working on implementing a feature to allow users to add recipes to their favorites list and know this involves Active Record associations. The following is what I tried. Unfortunately, I received the following error message.

Could not find the source association(s) :favorite or :favorites in model FavoriteRecipe. Try 'has_many :favorites, :through => :favorite_recipes, :source => <name>'. Is it one of :recipe or :user?

I've searched RubyonRails guides under ActiveRecord Associations and tried this code, but it raised the above error.

Here is my Recipe model, Recipe.rb

class Recipe < ActiveRecord::Base
  belongs_to :user
  has_many :favorite_recipes
  has_many :favorited_by, through: :favorite_recipes, source: :user
end

Here is my User model, User.rb

class User < ActiveRecord::Base
  has_many :recipes
  has_many :favorite_recipes
  has_many :favorites, through: :favorite_recipes
end

Here is my favorite recipe model, favorite_recipe.rb

class FavoriteRecipe < ActiveRecord::Base
  belongs_to :recipe
  belongs_to :favorite
  belongs_to :user
end

Here is my favorite recipe migration file

class CreateFavoriteRecipes < ActiveRecord::Migration
  def change
    create_table :favorite_recipes do |t|
      t.string :recipe_id
      t.string :integer
      t.string :user_id
      t.string :integer

    t.timestamps
    end
  end
end

Playing around in Rails Console, I tried the following

FavoriteRecipe.table_name
=> "favorite_recipes"

FavoriteRecipe.attribute_names
=>  ["id", "recipe_id", "integer", "user_id", "created_at", "updated_at"] 

FavoriteRecipe.primary_key
=> "id"

FavoriteRecipe.column_names
=> ["id", "recipe_id", "integer", "user_id", "created_at", "updated_at"]

FavoriteRecipe.connected?
=> "true"

Here is my routes.rb file

get "users/new"
  resources :recipes do
    put :favorite, on: :member
  end

  resources :users
  resources :sessions, only: [:new, :create, :destroy]

get 'static_pages/about'
get 'static_pages/contact'
get 'static_pages/help'
match '/signup', to: 'users#new', via: 'get'
match '/signin', to: 'sessions#new', via: 'get'
match '/signout', to: 'sessions#destroy', via: 'delete'

When running rake routes, here is my output

users_new_path           GET     /users/new(.:format)            users#new
favorite_recipe_path       PUT     /recipes/:id/favorite(.:format)   recipes#favorite
recipes_path               GET     /recipes(.:format)                recipes#index
                     POST    /recipes(.:format)                recipes#create
new_recipe_path            GET     /recipes/new(.:format)            recipes#new
edit_recipe_path           GET     /recipes/:id/edit(.:format)       recipes#edit
recipe_path                GET     /recipes/:id(.:format)            recipes#show
                     PATCH   /recipes/:id(.:format)            recipes#update
                     PUT     /recipes/:id(.:format)            recipes#update
                     DELETE  /recipes/:id(.:format)            recipes#destroy
users_path               GET     /users(.:format)                users#index
                     POST    /users(.:format)                users#create
new_user_path            GET     /users/new(.:format)            users#new
edit_user_path           GET     /users/:id/edit(.:format)       users#edit
user_path                GET     /users/:id(.:format)            users#show
                     PATCH   /users/:id(.:format)            users#update
                     PUT     /users/:id(.:format)            users#update
                     DELETE  /users/:id(.:format)            users#destroy
sessions_path            POST    /sessions(.:format)             sessions#create
new_session_path         GET     /sessions/new(.:format)         sessions#new
session_path             DELETE  /sessions/:id(.:format)         sessions#destroy
static_pages_about_path  GET     /static_pages/about(.:format)   static_pages#about
static_pages_contact_pathGET     /static_pages/contact(.:format  static_pages#contact
static_pages_help_path   GET     /static_pages/help(.:format)    static_pages#help
signup_path              GET     /signup(.:format)               users#new
signin_path              GET     /signin(.:format)               sessions#new
signout_path             DELETE  /signout(.:format)              sessions#destroy

When a user clicks on "show", it shows the particular recipe and has a link where you can add it to your favorites list. Here is my recipes/show.html.erb file

<h3>Recipe</h3>
 <ul id = 'view'>
  <li><strong>Title:</strong> <%= @recipe.title %></li>
  <li><strong>Console:</strong> <%= @recipe.console %></li>
  <li><strong>Genre:</strong> <%= @recipe.genre %></li>
  <li><strong>Release Date:</strong> <%= @recipe.released_on %></li>
</ul>

<p>
<%= link_to 'Add to Favorites', favorite_recipe_path(@recipe, type: 'favorite'), method: :put, id: 'favorites' %>
</p>

<p>
  <%= link_to 'Back', recipes_path, id: 'back' %>
</p>

I defined the following method in my recipes_controller.rb file

def favorite
  type = params[:type]
  if type == "favorite"
    current_user.favorites << @recipe
    redirect_to :back, notice: "#{@recipe.name} successfully added to your favorites!"
  elsif type == "unfavorite"
    current_user.favorites.delete(@recipe)
    redirect_to :back, notice: "#{recipe.name} removed from your favorites"
  else
    redirect_to :back, notice: 'No change'
  end
end

My apologies. I am a beginner in Ruby and still don't quite understand Active Record Associations. But any help as always is greatly appreciated.


Solution

  • I'm not sure if this reflects your actual migration, but it is completely wrong:

    class CreateFavoriteGames < ActiveRecord::Migration
      def change
        create_table :favorite_games do |t|
          t.string :game_id
          t.string :integer
          t.string :user_id
          t.string :integer
    
        t.timestamps
        end
      end
    end
    

    Should be:

    class CreateFavoriteGames < ActiveRecord::Migration
      def change
        create_table :favorite_games do |t|
          t.integer :game_id
          t.integer :user_id
          t.integer :favorite_id
    
          t.timestamps
        end
    
        add_index :favorite_games, :game_id
        add_index :favorite_games, :user_id
        add_index :favorite_games, :favorite_id
        add_index :favorite_games, [:game_id, :user_id, :favorite_id], unique: true
      end
    end