Вложенные формы Rails создают дубликаты каждый раз при создании новой записи - PullRequest
0 голосов
/ 23 марта 2020

Я пытаюсь смоделировать отношения между рецептами и ингредиентами. Я хочу, чтобы пользователи могли создавать рецепты с неопределенным количеством ингредиентов, а также редактировать рецепты для добавления ингредиентов.

Прямо сейчас, когда пользователь пытается редактировать рецепт, на странице редактирования отображаются поля формы для каждого введенного ингредиента, а также пустая форма. Если пользователь отправит форму, все записи будут продублированы.

Вот мой 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

ингридиент.rb:

class Ingredient < ApplicationRecord
  belongs_to :recipe
end

_form. html .erb, который является частичным для редактирования. html .erb и новый. html .erb:

<%= 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>

  <table>
    <tr>
      <th> Name </th>
      <th> Amount </th>
      <th> UOM </th>
    </tr>

    <% @recipe.ingredients.each do |ingredient| %>
      <tr>
        <td><%= ingredient.name %></td>
        <td><%= ingredient.amount  %></td>
        <td><%= ingredient.uom %></td>
      </tr>

      </table>

    <% end %>

  <h2>Add an Ingredient: </h2>
  <%= form.fields_for :ingredients do |new| %>
    <p>
      <%= new.label :name %><br>
      <%= new.text_field :name %>
    </p>
    <p>
      <%= new.label :amount %><br>
      <%= new.number_field :amount %>
    </p>
    <p>
      <%= new.label :uom %><br>
      <%= new.text_field :uom %>
    </p>
  <% end %>

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

<% 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: [:name, :amount, :uom])
    end
end

ингридиенты_контроллер.rb

class IngredientsController < ApplicationController

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

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

Я видел другие вопросы, похожие на эти, но я не смог найти решение моей проблемы ни от одного из них.

1 Ответ

1 голос
/ 23 марта 2020

Проблема в том, что вы не вносите в белый список вложенный атрибут id:

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

Который действительно легко пропустить, если весь белый список параметров находится в одном направлении слишком длинной строки. Без идентификатора accepts_nested_attributes_for будет обрабатывать каждый га sh, если его атрибуты для новой записи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...