In my last post, I detailed the steps to create a dynamically controlled form component in a React app to create a recipe app. However, that is only half of what we need to save that information to the server. In this post, I’ll go over how to build out a controller in Ruby on Rails that accepts information from a dynamically controlled form.
Creating a recipe
In the controller, write a create method. This create method will be used to create a new recipe.
def create
new_recipe_params = {
title: params[:title],
summary: params[:summary],
user_id: params[:user_id]
}
recipe = Recipe.create(new_recipe_params)
create_ingredients(params[:ingredients], recipe.id)
create_steps(params[:steps], recipe.id)
render json: { recipe: RecipeSerializer.new(recipe)}
end
The parameters of a new recipe are as follows:
- Title
- Summary
- User_id
- Ingredients
- Steps
As you can see,the method takes in the title, summary, and user_id data and uses helper methods for the ingredients and steps. Also note that there is a private method that handles the form permissions:
private
def recipe_params
params.require(:recipe).permit(:title, :summary, :user_id, :steps=> [], :ingredients=>[])
end
The ingredients are stored in an array from the form on the front end. In order to add them to the recipe, the create_ingredient method goes through that array and creates an ingredient for each element using the name and amount information. Then, the shovel operator adds the new ingredient to to ingredients attribute on recipe.
def create_ingredients(array, id)
recipe = Recipe.find(id)
array.each do |ingredient|
new_ingredient = Ingredient.create({recipe_id: id, name: ingredient[:name], amount: ingredient[:amount]})
recipe.ingredients << new_ingredient
end
end
The create_steps method uses similar logic.
def create_steps(array, id)
recipe = Recipe.find(id)
array.each do |step|
new_step = Step.create({recipe_id: id, step_summary: step[:step_summary]})
recipe.steps << new_step
end
end
Showing a recipe
A show method allows us to view the newly created recipe.
def show
@recipe = Recipe.find(params[:id])
if @recipe
render json: {recipe: @recipe, ingredients: @recipe.ingredients, steps:@recipe.steps }
else
render json: { error: "That recipe does not exist...yet"}, status: :not_acceptable
end
end
This works for creating and showing a recipe, but what about editing a recipe?
Editing a recipe
The edit route finds the recipe.
def edit
@recipe = Recipe.find(params[:id])
render json: @recipe
end
Like the create method, the update method also needs helper methods for the ingredients and steps attributes.
def update
@recipe = Recipe.find(params[:id])
edit_ingredients(params[:ingredients], @recipe.id)
edit_steps(params[:steps], @recipe.id)
@recipe.update(recipe_params)
render json: @recipe
end
The edit_ingredients method is similar to the create method. First, find the ingredient and then apply the updates to the ingredients that were updated. Again, the updated ingredients are shoveled into recipe.
def edit_ingredients(array, id)
recipe = Recipe.find(id)
if recipe.ingredients
array.each do |ingredient|
if ingredient[:id]
updated_ingredient = Ingredient.update({recipe_id: id, name: ingredient[:name], amount: ingredient[:amount]})
else
updated_ingredient = Ingredient.create({recipe_id: id, name: ingredient[:name], amount: ingredient[:amount]})
recipe.ingredients << updated_ingredient
end
end
end
end
Again, the edit_steps method follows the same pattern as the edit_ingredients method.
def edit_steps(array, id)
recipe = Recipe.find(id)
if recipe.steps
array.each do |step|
if step[:id]
updated_step = Step.update({recipe_id: id, step_summary: step[:step_summary]})
else
updated_step = Step.create({recipe_id: id, step_summary: step[:step_summary]})
recipe.steps << updated_step
end
end
end
end
Delete a recipe
In contrast, the destroy method is relatively simple.
def destroy
@recipe = Recipe.find(params[:id])
if @recipe
@recipe.destroy
render json: {message: "Recipe successfully deleted"}
else
render json: {message: "Failed to destroy recipe"}
end
end
Conclusion
In order to add information from a dynamically controlled form, use helper methods in your controller to take in information. The edit method will also use helper methods for dynamic information. After implementing the controller logic, a new recipe will be saved to the backend.
Top comments (2)
is there any source code there ?
Here's the repo: github.com/kailanak1/recipe-blog