编辑3:只是为了澄清,目标和问题是从同一形式创建2个新记录,其中一个是父母,一个是孩子。孩子需要父ID,但父级是由孩子的形式创建的。
编辑2:我认为我越来越近。请参阅结束时的日志文件,该交易已成功保存,看来客户端条目开始提交但不保存。代码将在下面更新以进行更改。
我遵循Railscast#196的嵌套表单,只要已经创建了记录,我就可以成功地从嵌套表单中编辑,添加和删除。现在,我正在尝试使用嵌套表单来创建新记录。我认为我在那里的99%,但是我缺少了我看不见的东西。我只需要弄清楚如何将父母的id
传递给孩子。
除了铁轨广播外,我还使用了此答案来设置inverse_of
关系并调用保存订单(虽然使用create
而不是save
(。我很确定问题是以表格或控制器为单位(但在下面也列出了模型(
嵌套形式(我试图简化以使阅读更易于阅读(
编辑2:删除隐藏字段
<%= form_for(@deal) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="deal-<%= @deal.id %>" >
<div class="form-group">
<%= f.label :headline %>
<%= f.text_field :headline, required: true, placeholder: "Headline" %>
</div>
<div class="form-group" id="clients">
<%= f.fields_for :clients do |client_form| %>
<div class="field">
<%= client_form.label :client %><br />
<%= client_form.text_field :name, placeholder: "Client name" %>
</div>
<% end %>
<%= link_to_add_fields "Add client", f, :clients %>
</div>
<div class="form-group">
<%= f.label :matter %>
<%= f.text_field :matter, placeholder: "Matter", rows: "4" %>
</div>
<div class="form-group">
<%= f.label :summary %>
<%= f.text_area :summary, placeholder: "Deal summary", rows: "4" %>
</div>
<div class="form-group">
<div class="action-area">
<%= f.submit "Add deal" %>
</div>
</div>
</div>
<% end %>
控制器
编辑2:Include deal_id param&amp;更改保存电话
class DealsController < ApplicationController
before_action :require_login
def new
@deal = Deal.new
@client = @deal.clients
end
def create
@deal = current_user.deals.create(deal_params)
if @deal.save
flash[:success] = "Your deal was created!"
redirect_to root_url
else
render 'deals/new'
end
end
private
def deal_params
params.require(:deal).permit(:headline, :matter, :summary, clients_attributes: [:id, :deal_id, :name, :_destroy])
end
end
编辑2:不再触发浏览器中的错误,flash消息被触发
编辑2:这是提交上的控制台输出(保存记录,可以查看它只是没有客户端(
Started POST "/deals" for ::1 at 2017-04-26 00:13:08 +0200
Processing by DealsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"hbvpS6KsZOorR3u4LgNoG5WHgerok6j3yYzO+dFUHs9thsxRi+rbUkm88nb7A5WvlmWZEcvaDvCKywufP3340w==", "deal"=>{"headline"=>"headline", "client"=>{"name"=>"aaa"}, "matter"=>"", "summary"=>""}, "commit"=>"Add deal"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 1], ["LIMIT", 1]]
Unpermitted parameter: client
(0.1ms) begin transaction
SQL (0.5ms) INSERT INTO "deals" ("headline", "matter", "summary", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?) [["headline", "headline"], ["matter", ""], ["summary", ""], ["user_id", 1], ["created_at", 2017-04-25 22:13:08 UTC], ["updated_at", 2017-04-25 22:13:08 UTC]]
(3.8ms) commit transaction
(0.1ms) begin transaction
(0.1ms) commit transaction
Redirected to http://localhost:3000/
Completed 302 Found in 16ms (ActiveRecord: 4.6ms)
Models for reference
用户
class User < ApplicationRecord
has_many :deals
end
交易
class Deal < ApplicationRecord
belongs_to :user
has_many :clients, inverse_of: :deal
validates :headline, presence: true
accepts_nested_attributes_for :clients, allow_destroy: true
end
客户
class Client < ApplicationRecord
belongs_to :deal, inverse_of: :clients
validates :name, presence: true
validates :deal_id, presence: true
end
您缺少params上的deal_id
def deal_params
params.require(:deal).permit(:headline, :matter, :summary, clients_attributes: [:id, :deal_id, :name, :_destroy])
end
以及创建交易,您可以做类似的东西
def create
@deal = Deal.new(deal_params)
if @deal.save
...
,只需在用户_ID参数的表单上添加一个隐藏的字段。
问题是客户端模型中的验证。删除验证将允许从嵌套表格中正确保存记录。
-
在客户端模型中删除名称和DEAL_ID验证器
class Client < ApplicationRecord belongs_to :deal, inverse_of: :clients end
-
在控制器中,将
build
添加到new
操作中,因此对用户来说更好: -
def new @deal = Deal.new @client = @deal.clients.build end
.build
并非严格必要,因为从导轨铸造创建的辅助方法将按需创建新的客户条目,但是在使用它的情况下,用户将使用占位符首次登记,如果空白。
要防止空客户端记录保存,我在交易模型中添加了
reject_if: proc
class Deal < ApplicationRecord belongs_to :user has_many :clients, inverse_of: :deal validates :headline, presence: true accepts_nested_attributes_for :clients, allow_destroy: true, reject_if: proc { |attributes| attributes['name'].blank? } end
,如果有人可以更好地解释我的解决方案的效果,并且有更好的方法可以做到。