2013-04-20 85 views
0

我有用户,用户有很多客户端和联系人。客户也有很多联系人(联系人属于用户和客户)。嵌套表格无法保存client_id和user_id

在我的客户端视图中,我想创建一个新的客户端,并在同一个表单上允许用户为该客户端创建第一个联系人。最初,我认为使用嵌套属性可以做到这一点,但我遇到了一些问题。当我在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 

和创建方法:

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 ...但我不能真正设置使用嵌套的a ttributes。我怎么能做到这一点?有没有更好的方法来做到这一点?这里是我的PARAMS:

{"name"=>"asdf", "contacts_attributes"=>{"0"=>{"name"=>"asdf", "email"=>"[email protected]"}}} 

我只是尝试添加缺少的值直接进入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,它仍然表示用户缺失。

回答

0

Did you add accepts_nested_attributes_for to your model?你需要的东西是这样的:

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

此外,你应该在你创建操作使用build

@client = current_user.clients.build(params[:client]) 
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" => "[email protected]" 
      } 
     } 
     } 
    } 
    }, 
    "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 
+0

如果我不想通过用户模型执行此操作,该怎么办?我不是每次都创建一个新用户......只有一个新的客户和联系人。 – 2013-04-20 19:31:06

+0

马修,我已经更新了答案。这是否有用? – gmile 2013-04-20 19:40:51

+0

嗯..通过@user模型绝对必要吗?这对我来说似乎是错误的,因为联系与客户关系更密切(我认为?)。有没有用户的方式?特别是因为视图和路线现在都在客户端。 – 2013-04-21 00:51:22

0

以下验证s可能会导致这个问题,因为在验证运行时,父id没有被分配给子对象。解决方法是删除这些验证或将它们设置为仅在更新时运行。这样你就失去了这些创建方法的验证,但它的工作原理。

# client.rb 
validates :user, presence: true 

# contact.rb 
validates :client, presence: true