嵌套表单无法保存client_id和user_id

时间:2013-04-20 18:30:16

标签: ruby-on-rails nested-forms

我有用户,用户有很多客户端和联系人。客户端也有许多联系人(联系人同时属于用户和客户端)。

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

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

  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

和create方法:

  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,它仍然表示用户丢失。

3 个答案:

答案 0 :(得分: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])

答案 1 :(得分: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 %>

表格如下:

enter image description here

以下是表单发送的params如何:

{
  "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

答案 2 :(得分:0)

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

# client.rb
validates :user, presence: true

# contact.rb
validates :client, presence: true