我无法理解这个问题。我有一个模型(发票),belongs_to
另一个模型(客户)和客户has_many
发票。
因此,没有客户就无法创建发票。我希望能够使用相同的表格同时创建一个发票的客户。
现在我已经拥有它,所以你可以手动打入invoice_id
并且一切正常但但对于实际使用该应用程序的人来说这并不理想。
我已经阅读了这篇文章,但我仍然不明白,也不确定这是否仍适用于Rails 5: https://stackoverflow.com/a/3809360/7467341
上述答案仍然是正确的方法吗?有人可以澄清,也许可以给我一些代码试试吗?谢谢!
<%= 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 %>
答案 0 :(得分:1)
您可能希望使用:cocoon来创建动态嵌套表单
答案 1 :(得分:1)
有很多不同的库可以帮助解决这类问题。但我会尝试建议一个只适用于Rails的解决方案。
因此,我试图分析你的情况,我猜我们需要解决两个问题。第一个是为现有客户添加发票,第二个是在创建发票的同时创建新客户。在我看来,最直接的做法是在表单中添加两个单独的字段。第一个字段是Select下拉列表,您可以从现有Customers中进行选择,第二个字段是Textfield,如果Select字段中没有匹配项,则输入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 %>
并且不要忘记允许来自Controller Invoice.create(params.permit(:customer_name, :customer_address, ...))
的其他参数属性。
当然有一些事情可以提高效率,但我希望这可以展示Rails提供的一些开箱即用的功能来解决这样的情况,我认为它很好如果你对Rails有些新意,请专注于此。
答案 2 :(得分:1)
在这种情况下,您可以使用嵌套属性。
在customer.rb
文件中,添加此accepts_nested_attributes_for :invoices
。
在白名单参数中,添加invoices_attribues: [invoice_fields]
以及客户字段。
Check this link用于理解fields_for和嵌套属性。 Check this link了解嵌套属性的工作原理。
答案 3 :(得分:0)
这是您尝试在那里执行的嵌套表单: