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