How to add functionality for favoriting a recipe

It’s week 6 in the program, which means that we got to spend the week working on projects. This time we were working in groups of three to build a web app using Ruby on Rails. We were given a set of criteria to meet for the project (a certain number of models, spec tests, etc.), but we were allowed to choose any topic for the app. My group decided to make an app where users can submit recipes, write stories about those recipes, and comment on existing stories and recipes. We decided that one of the features we wanted to implement was the ability for a user to favorite a recipe.

The first step towards this was to create a join table with columns for reader_id (a user can be either a reader, author, or both) and recipe_id. Then, the associations between a User, Recipe, and FavoriteRecipe was established in the models. A FavoriteRecipe belongs to a recipe and belongs to a reader. The :class_name and :foreign_key need to be explicitly stated to identify that a reader is part of the User class and the foreign key for it in the join table is reader_id.

In the User model, what’s interesting to note is the way the associations were set up:

fav_recipes doesn’t refer to any existing models, but instead is the name selected for the attribute that points to the array containing all of the recipes a user has favorited. So that our program knows how fav_recipes relates to the rest of the app, the

source: :recipe

at the end of the line tells the User model that fav_recipes is associated to the Recipe model.

A new route was added for favoriting a recipe, yielding a URL in the format of ‘recipes/#{}/favorite’.

Since it’s an update, we use a PUT or PATCH request. When adding a new route you have the option to add the route to a collection:

on: :collection

or individual members of a collection:

on: :member

For favoriting a recipe, we only want to apply it to individual recipes that a user selects, therefore the latter is a more appropriate choice. We still keep the

resources :recipes

in routes to provide the seven RESTful routes used by the application.

In the RecipesController, a new method, #favorite, is created to add in the favoriting functionality.

A new key called ‘:type’ is added to the params hash. If the value is equal to “favorite”, then the recipe object is shoveled into the logged in user’s fav_recipes array. If the value is “unfavorite”, then the recipe is removed from the fav_recipes array. In both cases, the user is redirected back to the previous page and a fallback_location is added in case the redirect_back fails.

In the show.html.erb page for a recipe, if a user is logged in (i.e. a current_user exists), links for adding or removing a recipe from their favoites are shown on the page.

It links to the favorite_recipe_path for the recipe object with the params[:type] value set equal to “favorite” or “unfavorite” using a PUT method.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.