Ruby on rails 使用Rails 5在一个表单中创建记录和从属记录

Ruby on rails 使用Rails 5在一个表单中创建记录和从属记录,ruby-on-rails,Ruby On Rails,我很难理解这个问题。我有一个属于另一个模型客户的模型发票,一个客户有很多发票 因此,没有客户就无法创建发票。我希望能够创建一个客户与发票在同一时间与相同的形式 现在我有了它,这样你就可以手动输入一个发票id,一切都很好,但这对于实际使用该应用程序的人来说并不理想,原因很明显 我已经阅读了这篇文章,但我仍然不理解,也不确定这是否仍然适用于Rails 5: 上述答案仍然是正确的方法吗?有人能澄清一下,也许能给我一些代码试试吗?谢谢 <%= form_for(invoice) do |f| %

我很难理解这个问题。我有一个属于另一个模型客户的模型发票,一个客户有很多发票

因此,没有客户就无法创建发票。我希望能够创建一个客户与发票在同一时间与相同的形式

现在我有了它,这样你就可以手动输入一个发票id,一切都很好,但这对于实际使用该应用程序的人来说并不理想,原因很明显

我已经阅读了这篇文章,但我仍然不理解,也不确定这是否仍然适用于Rails 5:

上述答案仍然是正确的方法吗?有人能澄清一下,也许能给我一些代码试试吗?谢谢

<%= form_for(invoice) do |f| %>
    <% if invoice.errors.any? %>
        <div id="error_explanation">
            <h2><%= pluralize(invoice.errors.count, "error") %>
                prohibited this invoice from being saved:</h2>

            <ul>
                <% invoice.errors.full_messages.each do |message| %>
                    <li><%= message %></li>
                <% end %>
            </ul>
        </div>
    <% end %>


    <h2>Customer Info</h2>
    <hr>
    <div class="field">
        <%= f.label :customer_id %>
        <%= f.number_field :customer_id %>
    </div>

    <!-- My customer model has more fields that I want to go here (name, address, and phone_number) -->

    [...] other regular invoice fields here...

    <div class="actions">
        <%= f.submit %>
    </div>
<% end %>

您可能想使用:创建动态嵌套表单

这是您尝试在其中执行的嵌套表单:

,9.2嵌套形式 ,
有很多不同的库可以在这种情况下提供帮助。但我将尝试提出一种仅适用于Rails的解决方案

因此,为了分析你的情况,我猜我们需要解决两种情况。第一个用于为现有客户添加发票,第二个用于在创建发票的同时创建新客户。在我看来,最直接的方法是在表单中添加两个单独的字段。第一个字段是选择下拉列表,您可以从现有客户中进行选择,第二个字段是文本字段,如果选择字段中没有匹配项,您可以在其中输入客户的名称

逻辑是首先检查下拉列表中是否选择了任何内容,在这种情况下,textfield中的任何文本都将被忽略。但是如果没有从下拉列表中选择任何内容,那么它将基于文本字段创建Customer

以下是我如何实现这一目标的建议:

class Invoice < ActiveRecord::Base

  belongs_to :customer

  validate :customer_id, presence: true

  # A dynamic attribute that is NOT represented by a database column in the Invoice model, but only used for the form
  attr_accessor :customer_name, :customer_address #, plus your other fields

  before_validation on: :create do
    if customer_id.nil? && customer_name.present?
      # Use create! (with !) so that an error is raised if the customer 
      # could not be created which will abort the entire save transaction
      self.customer = Customer.create!(name: customer_name, address: customer_address)
      # Add your other customer attributes above as well
    end
  end

end
然后以你的形式

<%= form_for(invoice) do |f| %>

    <h2>Customer Info</h2>
    <hr>
    <div class="field">
        <%= f.label :customer_id, "Choose existing Customer" %>
        <%= f.select :customer_id, options_from_collection_for_select(Customer.all, :id, :name, invoice.customer_id) %>
    </div>

    <div class="field">
        <%= f.label :customer_name, "... or create a new Customer" %>
        <%= f.text_field :customer_name %>
    </div>

    <div class="field">
        <%= f.label :customer_address, "New customer address" %>
        <%= f.text_field :customer_address %>
    </div>
    <!-- Repeat for all your other Customer attributes -->

    [...] other regular invoice fields here...

    <div class="actions">
        <%= f.submit %>
    </div>
<% end %>
并且不要忘记允许控制器Invoice.createparams.permit中的附加参数属性:customer\u name,:customer\u address


当然,在这方面有一些事情可以提高效率,但我希望这可以展示Rails提供的一些开箱即用的特性,以解决类似的情况,我认为如果您对Rails有些陌生,最好关注这一点。

在这种情况下可以使用嵌套属性。 在customer.rb文件中,添加以下内容:发票

在白名单参数中,添加发票\属性:[发票\字段]以及客户字段

用于理解字段和嵌套属性。
了解嵌套属性是如何工作的。

这是最有意义的,也是我一直在寻找的。非常感谢。我必须解决老客户的选择问题,因为如果有任何大量数据,这显然是疯狂的。我不得不调整你的代码,在下拉列表中添加一个空格,否则它将始终自动选择一个旧客户,而不会使用:include\u blank=>true在选项的末尾\u from\u collection\u对于\u selectRight,我本应该考虑:include\u blank,但我忘了。不管怎样,很高兴你让它工作了。我感谢你的解释。比链接到一篇文章或一些宝石更有帮助。现在我明白了如何解决这个问题,我对未来充满信心,可以自信地开始寻找有助于解决此类问题的一个宝石。谢谢