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

时间:2016-01-30 23:18:40

标签: ruby-on-rails forms associations params fields-for

我有三个模型,companiestransactionssubtransactions。每个 has_many 的下一个。我需要构建一个保存到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 %>

我的TransactionsController:

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

2 个答案:

答案 0 :(得分:3)

这样做的方法是通过各种模型传递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

这将使您能够使用以下内容:

#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

则...

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

这将允许您通过主对象保存各种嵌套属性。这是正确的conventional方式。

答案 1 :(得分:1)

模型

class Transaction < ActiveRecord::Base
  has_many :subtransations
  accepts_nested_attributes_for :subtransactions
end

控制器

def new
  @transaction = Transaction.new
  @transaction.subtransactions.build
end

def create
  company = Company.first # Or whatever you need.

  # We merge the company id to the transaction params since 
  # a transaction belongs_to a company.
  @transaction = Transaction.create!(create_params.merge(company_id: company.id))
end

private

def create_params
  params.require(:transaction).permit(
    :total,
    subtransactions_attributes: [:id, :subtotal]
  )
end

视图

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

  <%= f.fields_for :subtransaction do |s| %>
    <div class="field" id="subtotal_amount">
      <%= s.label :subtotal %><br>
      <%= s.text_field :subtotal %>
    </div>
  <% end %>
<% end %>

这将允许仅使用事务记录

创建一个子事务

如果您想创建多个subtransaction记录,则应使用cocoon gem,这样可以轻松设置并节省宝贵的时间。