0

I am making a rails application that allows user to create recipes. On the new recipe page there are input fields for the recipe title, author etc. and then there are input fields for the ingredients. When a new ingredient is created the page redirects to the "Show recipe" page. How could have the page dymnamically generate a new ingredient form below the old one.

ingredients_controller.rb

class IngredientsController < ApplicationController

  def create
    @recipe = Recipe.find(params[:recipe_id])
    @ingredient = @recipe.ingredients.create(ingredient_params)
    redirect_to new_recipe_path(@recipe)
  end

  private
  def ingredient_params
    params.require(:ingredient).permit(:name, :amount, :uom)
  end
end

recipes_controller.rb

class RecipesController < ApplicationController
  def index
    @recipes = Recipe.all
  end

  def show
    @recipe = Recipe.find(params[:id])
  end

  def new
    @recipe = Recipe.new
    @recipe.ingredients.build
  end

  def edit
    @recipe = Recipe.find(params[:id])
    @recipe.ingredients.build
  end

  def create
    @recipe = Recipe.new(recipe_params)
    if @recipe.save
      redirect_to @recipe
    else
      render 'new'
    end
  end

  def update
    @recipe = Recipe.find(params[:id])

    if @recipe.update(recipe_params)
      redirect_to @recipe
    else
      render 'edit'
    end
  end

  def destroy
    @recipe = Recipe.find(params[:id])
    @recipe.destroy

    redirect_to @recipe
  end

  private
  def recipe_params
    params.require(:recipe).permit(:title, :author, :note,
                                   ingredients_attributes: [:id, :name, :amount, :uom])
  end
end

My form is split into two partials, one for the recipe form title _form.html.rb and one called _ingform.html.rb, _ingform.html.rb is rendered inside _form.html.rb and _form.html.rb is rendered in new.html.rb and edit.html.rb.

_form.html.rb

<link rel="stylesheet" type="text/css" href="app/assets/stylesheets/form.css">

<div id = "form">
  <%= form_for(@recipe) do |form| %>
    <% if @recipe.errors.any? %>
      <div id = "error_explanation">
        <h2>
          <%= pluralize(@recipe.errors.count, "error") %>
          prohibited this recipe from being saved:
        </h2>
        <ul>
          <%@recipe.errors.full_messages.each do |msg| %>
            <li><%= msg %></li>
          <% end %>
        </ul>
      </div>
    <% end %>

    <p>
      <%= form.label :title  %><br>
      <%= form.text_field :title %>
    </p>

    <p>
      <%= form.label :author  %><br>
      <%= form.text_field :author %>
    </p>

    <p>
      <%= form.label :note %><br>
      <%= form.text_area :note %>
    </p>

      <%= render 'ingform' %>

      <p>
        <%= form.submit %>
      </p>

  <% end %>
</div>

_ingform.html.rb

<link rel="stylesheet" type="text/css" href="app/assets/stylesheets/ingform.css">
<%= form_for(@recipe) do |form| %>
  <h2>Add an Ingredient: </h2>
  <%= form.fields_for :ingredients do |new| %>
    <p class = "input_field">
      <%= new.label :name, "name" %><br>
      <%= new.text_field :name %>
    </p>
    <p class = "input_field">
      <%= new.label :amount, "amount" %><br>
      <%= new.number_field :amount %>
    </p>
    <p class = "input_field">
      <%= new.label :uom, "UOM" %><br>
      <%= new.text_field :uom %>
    </p>
    <p class = "input_field">
      <%= new.submit %>
    </p> </br>
  <% end %>
<% end  %>

ingredients belong to recipes. recipe.rb

class Recipe < ApplicationRecord
  has_many :ingredients, :dependent => :delete_all
  accepts_nested_attributes_for :ingredients, reject_if: :all_blank
  validates :title, presence: true, length: {minimum: 4}
  validates :author, presence: true
end

thank you

romanf
  • 5
  • 1

1 Answers1

0

This is a common problem - it's all about nesting forms: the easiest option is to ensure that your recipe accepts nested attributes for ingredients. Please watch this following railscast: it is actually quite easy to implement. The only catch is that the form is submitted all at once.

BenKoshy
  • 33,477
  • 14
  • 111
  • 80
  • Thank you for the quick response. That video was extremely helpful, but I can't quite get it to work. When I click the 'add ingredient' link it just refreshes the page. I believe that my coffeescript file is not linked to my _form.html.erb page. How would I do this? – romanf Mar 31 '20 at 20:48
  • Very very hard to debug like this on the internet. One common problem is that: you'll have to ensure that the coffee script loads AFTER turbolinks has loaded: https://stackoverflow.com/a/45916673/4880924 that might solve your problem. very hard to say. – BenKoshy Mar 31 '20 at 21:43