从轨道中的相同嵌套表格中创建父母和子女



编辑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参数的表单上添加一个隐藏的字段。

问题是客户端模型中的验证。删除验证将允许从嵌套表格中正确保存记录。

  1. 在客户端模型中删除名称和DEAL_ID验证器

    class Client < ApplicationRecord
      belongs_to :deal, inverse_of: :clients
    end
    
  2. 在控制器中,将build添加到new操作中,因此对用户来说更好:

  3. def new
      @deal = Deal.new
      @client = @deal.clients.build
    end
    

.build并非严格必要,因为从导轨铸造创建的辅助方法将按需创建新的客户条目,但是在使用它的情况下,用户将使用占位符首次登记,如果空白。

  1. 要防止空客户端记录保存,我在交易模型中添加了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
    

,如果有人可以更好地解释我的解决方案的效果,并且有更好的方法可以做到。

最新更新