如何创建提交到多个模型并创建正确关联的表单

时间:2018-06-05 02:02:12

标签: ruby-on-rails ruby activerecord

我希望有一个新食谱的表单,在提交时会创建一个新配方及其相关成分和每种成分的数量。

我已经进行了相当广泛的搜索,并花了几天时间试图解决这个问题。任何帮助将非常感激。

我有这些相关的模型:

class Recipe < ApplicationRecord
  belongs_to :user
  has_many :items
  has_many :ingredients, through: :items
  accepts_nested_attributes_for :ingredients, reject_if: :all_blank, 
allow_destroy: true

  validates :name, presence: true
end

class Ingredient < ApplicationRecord
  has_many :items
  has_many :recipes, through: :items
  has_many :quantities
  accepts_nested_attributes_for :quantities, reject_if: :all_blank, 
allow_destroy: true
end

class Quantity < ApplicationRecord
  belongs_to :ingredient
end

以下是观点:

recipes / _form

<%= form_for(@recipe) do |f| %>
  <% 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 |message| %>
        <li><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="form-group">
    <%= f.label :name %>
    <%= f.text_field :name, class: "form-control" %></div>

  <div class="form-group">
    <%= f.label :instructions %>
    <%= f.text_field :instructions, class: "form-control" %></div>

    <h3>Ingredients</h3>
     <div id='ingredients'>
       <%= f.fields_for @ingredient do |ingredient| %>
         <%= render 'ingredient_fields', :f => ingredient %>
       <% end %>
       <br>

       <div class='links'>
         <br><%= link_to_add_association 'add ingredient', f, :ingredients, class: "btn btn-default add_button" %>
       </div>
     </div>
     <br>

  <div class="actions">
    <%= f.submit class: "btn btn-primary" %>
  </div>
<% end %>

配方/ _ingredient_fields

<div class='nested-fields'>
    <%= f.label :name %>
    <%= f.text_field :name, class: "form-input form-control" %>

    <%= f.fields_for @ingredient.quantities.build do |quantity| %>
      <%= render 'quantity_fields', :f => quantity %>
    <% end %>

    <%= link_to_remove_association "remove ingredient", f, class: "form-button btn btn-default" %>
    <br>
</div>

配方/ _quantity_fields

<div class="nested-fields">
  <%= f.label :amount %>
  <%= f.text_field :amount, class: "form-input form-control" %>
</div>

recipes_controller

class RecipesController < ApplicationController
 before_action :set_recipe, only: [:show, :edit, :update, :destroy]
  before_action :require_logged_in, except: [:index]

  def index
    if params[:user_id]
      @recipes = User.find(params[:user_id]).recipes
    else
      @recipes = Recipe.all
    end
  end

  def new
    @recipe = Recipe.new
    @ingredient = Ingredient.new
    @ingredient.quantities.build
  end

  def create
    byebug
    @recipe = Recipe.new(recipe_params)
    @recipe.user = current_user

    respond_to do |format|
      if @recipe.save
        format.html { redirect_to recipe_path(@recipe), notice: 'Recipe was successfully created.' }
      else
        format.html { render :new }
      end
    end
  end

  def show
  end

  def edit
  end

  def update
    respond_to do |format|
      if @recipe.update(recipe_params.reject{|k,v| v.blank?})
        format.html { redirect_to @recipe, notice: 'User was successfully updated.' }
      else
        format.html { render :edit, notice: 'Update unsuccessful' }
      end
    end
  end

  def destroy
    @recipe.destroy
    redirect_to recipes_path, notice:  "Recipe deleted."
  end

private

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

  def recipe_params
    params.require(:recipe).permit(
      :name,
      :instructions,
      ingredients_attributes: [:id, :name, :_destroy, quantities: [:id, :amount]]
      #items_attributes: [:quantity]

    )
  end

end

我尝试过这么多不同的方式。这正是我目前的代码所在。我大多尝试使用这种语法 <%= f.fields_for :ingredients %>

如果我能说得更清楚,或者更好地回答任何问题,我很乐意帮忙。提前致谢。

0 个答案:

没有答案