Rails 5 has_many through: association creates 2 records for intermediate model

Rails 5 has_many through: association creates 2 records for intermediary model

我正在尝试通过以下方式设置 Rails 5 has_many:三个模型的关联类型。目标是让用户可以填写一个表单来编辑或创建所有三个模型(和关联)。

项目是 "intermediary" 模型。

这是我的模型:

class Client < ApplicationRecord
    has_many :projects
    has_many :programmers, through: :projects

    accepts_nested_attributes_for :projects, reject_if: :all_blank, allow_destroy: true
    accepts_nested_attributes_for :programmers, reject_if: :all_blank, allow_destroy: true
end

class Project < ApplicationRecord
  belongs_to :client, optional: true
  belongs_to :programmer, optional: true 
end

class Programmer < ApplicationRecord
  has_many :projects
  has_many :clients, through: :projects
end

Postgres 架构:

create_table "clients", force: :cascade do |t|
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.string   "name"
end

create_table "programmers", force: :cascade do |t|
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.string   "name"
end

create_table "projects", force: :cascade do |t|
  t.datetime "created_at",    null: false
  t.datetime "updated_at",    null: false
  t.string   "name"
  t.integer  "client_id"
  t.integer  "programmer_id"
  t.index ["client_id"], name: "index_projects_on_client_id", using: :btree
  t.index ["programmer_id"], name: "index_projects_on_programmer_id", using: :btree
end

add_foreign_key "projects", "clients"
add_foreign_key "projects", "programmers"

客户端控制器(仅 new/create 和参数部分)

def new
  @client = Client.new
  @client.projects.build
  @client.programmers.build
end

def create
  @client = Client.new(client_params)

  respond_to do |format|
    if @client.save
      format.html { redirect_to @client, notice: 'Client was successfully created.' }
      format.json { render :show, status: :created, location: @client }
    else
      format.html { render :new }
      format.json { render json: @client.errors, status: :unprocessable_entity }
    end
  end
end

private

  def client_params
    params.require(:client).permit(:id, :name, projects_attributes: [:id, :name], programmers_attributes: [:id, :name])
 end

最后,表格:

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

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

  <label>Client name</label>
  <%= f.text_field :name %>
  <br />

  <%= f.fields_for :projects do |projectfields| %>
    <label>Project name</label>
    <%= projectfields.text_field :name %>
  <% end %>
  <br />

  <%= f.fields_for :programmers do |programmerfields| %>
    <label>Programmer name</label>
    <%= programmerfields.text_field :name %>
  <% end %>

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

控制台日志:

Started POST "/clients" for ::1 at 2016-11-09 09:14:31 -0800
Processing by ClientsController#create as HTML
  Parameters: {"utf8"=>"✓",     "authenticity_token"=>"6QouF/zC+ivHAlbEvnhuBob80/AGt2QFmn0xa569+wJ8iWRmDOnz229OJq6PxaYRnzjNoDf8j71Jf2FpY3FMZw==", "client"=>{"name"=>"aaa", "projects_attributes"=>{"0"=>{"name"=>"bbb"}}, "programmers_attributes"=>{"0"=>{"name"=>"ccc"}}}, "commit"=>"Create Client"}
(0.2ms)  BEGIN
SQL (0.5ms)  INSERT INTO "clients" ("created_at", "updated_at", "name") VALUES (, , ) RETURNING "id"  [["created_at", 2016-11-09 17:14:31 UTC], ["updated_at", 2016-11-09 17:14:31 UTC], ["name", "aaa"]]
SQL (0.6ms)  INSERT INTO "projects" ("created_at", "updated_at", "name", "client_id") VALUES (, , , ) RETURNING "id"  [["created_at", 2016-11-09 17:14:31 UTC], ["updated_at", 2016-11-09 17:14:31 UTC], ["name", "bbb"], ["client_id", 1]]
SQL (0.4ms)  INSERT INTO "programmers" ("created_at", "updated_at", "name") VALUES (, , ) RETURNING "id"  [["created_at", 2016-11-09 17:14:31 UTC], ["updated_at", 2016-11-09 17:14:31 UTC], ["name", "ccc"]]
SQL (0.4ms)  INSERT INTO "projects" ("created_at", "updated_at", "client_id", "programmer_id") VALUES (, , , ) RETURNING "id"  [["created_at", 2016-11-09 17:14:31 UTC], ["updated_at", 2016-11-09 17:14:31 UTC], ["client_id", 1], ["programmer_id", 1]]
(5.5ms)  COMMIT
Redirected to http://localhost:3000/clients/1
Completed 302 Found in 19ms (ActiveRecord: 7.5ms)

所以基本上是为所有三个模型创建条目,除了为项目创建了 2 个数据库条目,如下所示:

我盯着这个看得太久了,我想我一定漏掉了一些明显的东西。有任何想法吗?感谢您的帮助。

试一试,看看是否有效:

<%= form_for @client do |f| %>

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

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

  <label>Client name</label>
  <%= f.text_field :name %>
  <br />

  <%= f.fields_for @client.projects do |projectfields| %>
    <label>Project name</label>
    <%= projectfields.text_field :name %>
  <% end %>
  <br />

  <%= f.fields_for @client.programmers do |programmerfields| %>
    <label>Programmer name</label>
    <%= programmerfields.text_field :name %>
  <% end %>

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