【问题标题】:Rails 5 has_many through: association creates 2 records for intermediary modelRails 5 has_many through:关联为中间模型创建2条记录
【发布时间】:2017-03-23 14:45:20
【问题描述】:

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

项目是“中介”模型。

这是我的模型:

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"

客户端控制器(只是新的/创建和参数部分)

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 ($1, $2, $3) 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 ($1, $2, $3, $4) 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 ($1, $2, $3) 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 ($1, $2, $3, $4) 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 个数据库条目,看起来像这样:

我已经盯着这个太久了,我想我一定错过了一些明显的东西。有任何想法吗?感谢您的帮助。

【问题讨论】:

    标签: postgresql activerecord associations ruby-on-rails-5 has-many-through


    【解决方案1】:

    试一试,看看它是否有效:

    <%= 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 %>
    

    【讨论】:

    • 我认为这更接近了——经过一番大惊小怪后,看起来关键可能是将 field_for 程序员嵌套在 fields_for 项目块中?
    猜你喜欢
    • 2011-02-20
    • 2014-02-27
    • 1970-01-01
    • 2011-10-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 2012-09-18
    • 1970-01-01
    相关资源
    最近更新 更多