具有嵌套 fields_for 的表单,可保存到多个记录

Mat*_*ias 2 forms parameters ruby-on-rails associations fields-for

我有三个模型, companiestransactionssubtransactions。每个都有很多下一个。我需要构建一个保存transactionssubtransactions.

我正在努力寻找表单的最佳方法以及保存到数据库的适当方法。理想情况下,如果所有记录都通过验证,则立即保存记录。

我的简化形式:

<%= form_for(@transaction) do |f| %>
  <div class="field" id="transaction_amount">
    <%= f.label :total %><br>
    <%= f.text_field :total %>
  </div>

    <% 1.upto(5) do |i| %>
          <%= fields_for("subtransaction[#{i}]") do |s| %>
              <div class="field" id="subtotal_amount">
                <%= s.label :subtotal, "Subtotal #{i}" %><br>
                <%= s.text_field :subtotal %>
              </div>
          <% end %>
    <% end %>  
<% end %>
Run Code Online (Sandbox Code Playgroud)

我的交易控制器:

def new
    @transaction = company.transactions.build if logged_in?
end

def create
    @transaction = company.transactions.build(transaction_params)

    params[:subtransaction].each do |i|
        # build and save
    end

    if @transaction.save ## @subtransaction.save
        flash[:success] = "Success!"
        redirect_to success_url
      else
         render :new
      end
end
Run Code Online (Sandbox Code Playgroud)

Ric*_*eck 5

做到这一点的方法是nested通过各种模型传递属性:

#app/models/company.rb
class Company < ActiveRecord::Base
   has_many :transactions
   accepts_nested_attributes_for :transactions
end

#app/models/transaction.rb
class Transaction < ActiveRecord::Base
   has_many :sub_transactions
   accepts_nested_attributes_for :sub_transactions
end
Run Code Online (Sandbox Code Playgroud)

这将使您能够使用以下功能:

#app/controllers/transactions_controller.rb
class TransactionsController < ApplicationController
   def new
      @transaction = company.transactions.new
      5.times do
        @transaction.sub_transactions.build
      end
   end

   def create
      @transaction = company.transactions.new transaction_params
      @transaction.save
   end

   private

   def transaction_params
      params.require(:transaction).permit(sub_transactions_attributes: [:subtotal])
   end
end
Run Code Online (Sandbox Code Playgroud)

然后...

#app/views/transactions/new.html.erb
<%= form_for @transaction do |f| %>
   <%= f.fields_for :sub_transactions do |s| %>
      <%= s.text_field :subtotal %>
   <% end %>
   <%= f.submit %>
<% end %>
Run Code Online (Sandbox Code Playgroud)

这将允许您通过主对象保存各种嵌套属性。这是正确的、传统的做法。