0

我有用户,用户有很多客户和联系人。客户也有许多联系人(一个联系人属于用户和客户)。

在我的客户视图中,我想创建一个新客户并在同一个表单上允许用户为该客户创建第一个联系人。最初,我认为使用嵌套属性可以解决问题,但我遇到了一些问题。当我在clients_controller#create 中保存@client 时,我无法保存,因为user_id 不能为空且client_id 不能为Contact 的空白。这是我到目前为止所拥有的:

客户端控制器索引(新客户端表单所在的位置):

  def index
    @clients = current_user.clients
    @client = Client.new
    @contact = @client.contacts.build

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @clients }
    end
  end

和创建方法:

  def create
    @client = current_user.clients.new(params[:client])

    respond_to do |format|
      if @client.save

和形式:

  = form_for(@client) do |f|
          = f.fields_for(:contacts) do |contact|

但是当我去保存它时,它需要一个 client_id 和 user_id ......但我不能真正使用嵌套属性来设置它们。我怎样才能做到这一点?有更好的方法吗?这是我的参数:

{"name"=>"asdf", "contacts_attributes"=>{"0"=>{"name"=>"asdf", "email"=>"asdf@gmail.com"}}}

我只是尝试将缺失值直接添加到contacts_attributes,但由于@client 尚未保存,我无法将client.id 分配给联系人:

params[:client][:contacts_attributes]["0"].merge!(:user_id => current_user.id)
params[:client][:contacts_attributes]["0"].merge!(:client_id => @client.id)

即使设置了 user_id ......它仍然说用户丢失。

4

3 回答 3

0

你添加accepts_nested_attributes_for到你的模型中了吗?你需要这样的东西:

class Client < ActiveRecord::Base
  has_many :contacts
  accepts_nested_attributes_for :contacts
end

此外,您应该build在创建操作中使用:

@client = current_user.clients.build(params[:client])
于 2013-04-20T19:01:29.307 回答
0

这是适用于您的示例的设置:

app/models/user.rb

class User < ActiveRecord::Base
  attr_accessible :name, :clients_attributes

  has_many :clients

  accepts_nested_attributes_for :clients
end

app/models/client.rb

class Client < ActiveRecord::Base
  attr_accessible :company, :contacts_attributes

  belongs_to :user
  has_many :contacts

  accepts_nested_attributes_for :contacts
end

app/models/contact.rb

class Contact < ActiveRecord::Base
  attr_accessible :email

  belongs_to :client
end

app/controllers/users_controller.rb

class UsersController < ApplicationController
  # ...

  def new
    @user    = User.new
    @client  = @user.clients.build
    @concact = @client.contacts.build

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @user }
    end
  end

  # ...
end

实际形式:

<% # app/views/users/new.erb %>

<%= form_for(@user) do |f| %>
  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>

  <div class="field">
    <%= f.fields_for :clients do |client_form| %>
      <h5>Client</h5>
      <%= client_form.label :company, "Company name" %>
      <%= client_form.text_field :company %>

      <div class="field">
        <h5>Contact</h5>
        <%= client_form.fields_for :contacts do |contact_form| %>
          <%= contact_form.label :email %>
          <%= contact_form.text_field :email %>
        <% end %>
      </div>
    <% end %>
  </div>

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

表格如下所示:

在此处输入图像描述

表单发送的参数如下所示:

{
  "utf8"=>"✓",
  "authenticity_token" => "bG6Lv62ekvK7OS86Hg/RMQe9S0sUw0iB4PCiYnsnsE8=",
  "user" => {
    "name" => "My new user",
    "clients_attributes" => {
      "0" => {
        "company" => "Client's Company Name LLC",
        "contacts_attributes" => {
          "0" => {
            "email" => "emailbox@client.com"
          }
        }
      }
    }
  },
  "commit" => "Create User"
}

更新

要在之后添加更多公司/联系人,请将UsersController#edit操作更改为:

class UsersController < ApplicationController
  # ...

  def edit
    @client  = current_user.clients.build
    @concact = @client.contacts.build

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @user }
    end
  end

  # ...
end
于 2013-04-20T19:19:54.550 回答
0

以下验证可能会导致此问题,因为在为其运行验证时父 id 尚未分配给子对象。解决方法是删除这些验证或将它们设置为仅在更新时运行。这样,您就失去了对 create 方法的这些验证,但它可以工作。

# client.rb
validates :user, presence: true

# contact.rb
validates :client, presence: true
于 2015-06-09T15:02:12.123 回答