我有用户,用户有很多客户端和联系人。客户端也有许多联系人(联系人同时属于用户和客户端)。
在我的客户端视图中,我想创建一个新客户端,并在同一表单上允许用户为该客户端创建第一个联系人。最初,我认为使用嵌套属性可以解决问题,但我遇到了一些问题。当我在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,它仍然表示用户丢失。
答案 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 %>
表格如下:
以下是表单发送的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