我正在使用Rails 3并且有一个表单,它使用fields_for合并来自多个相关记录的字段。我的模型与关系如下:
class Company < ActiveRecord::Base
has_many: locations, dependent: :destroy
has_many :addresses, through: :locations
has_many :contacts
accepts_nested_attributes_for :locations, :addresses, :contacts
end
class Address < ActiveRecord::Base
has_many :locations
has_many :companies, through: :locations
accepts_nested_attributes_for :locations, :companies
end
class Contact < ActiveRecord::Base
belongs_to :company
accepts_nested_attributes_for :company
end
class Location < ActiveRecord::Base
belongs_to :company
belongs_to :address
accepts_nested_attributes_for :company, :address
end
我的控制器目前看起来像这样:
class CompaniesController < ApplicationController
def new
@company = Company.new
@location = @company.locations.build
@address = @company.addresses.build
@contact = @company.contacts.build
end
def create
@company = Company.new(params[:company])
if @company.save
#handle a successful save
flash[:success] = "Company Created Successfully"
redirect_to @company
else
render 'new'
end
end
end
提交表单时出现此错误:无法批量分配受保护的属性:addresses_attributes,locations_attributes,contacts_attributes
我尝试将控制器中的create方法更改为以下内容:
def create
@company = Company.new(params[:company_name])
@company.addresses.build(params[:address])
@company.locations.build(params[:location])
@company.contacts.build(params[:contact])
if @company.save
#handle a successful save
flash[:success] = "Company Created Successfully"
redirect_to @company
else
render 'new'
end
end
此create方法的结果是服务器日志,其中显示:
> Processing by CompaniesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"SVDIk5IzY7foo9DULhzY+RWgh/HAA9NqRp6FafWwFDg=", "company"=>{"company_name"=>"New Co", "
addresses_attributes"=>{"0"=>{"address_line_1"=>"231 Main", "address_line_2"=>"", "address_line_3"=>"", "city"=>"Dallas", "state"=>"AL",
"country"=>"USA", "zipcode"=>"74343"}}, "locations_attributes"=>{"0"=>{"location_type"=>"11", "location_name"=>"DFW"}}, "contacts_attribu
tes"=>{"0"=>{"first_name"=>"Joe", "last_name"=>"User", "title"=>"CEO"}}}, "commit"=>"Save Info"}
SQL (24.9ms) BEGIN TRANSACTION
Address Exists (27.6ms) EXEC sp_executesql N'SELECT TOP (1) 1 AS one FROM [addresses] WHERE ([addresses].[address_line_1] IS NULL AND
[addresses].[address_line_2] IS NULL AND [addresses].[address_line_3] IS NULL AND [addresses].[address_line_4] IS NULL AND [addresses].[a
ddress_line_5] IS NULL AND [addresses].[city] IS NULL AND [addresses].[state] IS NULL AND [addresses].[county] IS NULL AND [addresses].[c
ountry] IS NULL AND [addresses].[zipcode] IS NULL)'
SQL (50.8ms) IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION
CACHE (0.0ms) SELECT @@TRANCOUNT
Rendered companies/new.html.erb within layouts/application (9.4ms)
Rendered layouts/_shim.html.erb (0.0ms)
User Load (32.1ms) EXEC sp_executesql N'SELECT TOP (1) [users].* FROM [users] WHERE [users].[remember_token] = N''TZlKZ6Sx06p3mMS9kUJY
GA'''
请注意,尽管填充了address_attributes,但查询的params [:address]对于所有字段都为null。 (*注意我在地址模型中有一个验证器,以确保每个地址都是唯一的。地址表中目前没有记录)。
如何在提交时为每个模型正确构建和存储记录?谢谢!
更新:我没有在公司模型attr_accessible块中列出的addresses_attributes,locations_attributes和contacts_attributes。添加这些属性似乎解决了从控制器和
中的表单中加载子属性的问题@company = Company.new(params[:company])
现在填充地址,位置和联系人,但是当我打电话
时if @company.save
事务仍然使用以下服务器日志回滚
于2013-12-11 11:12:03 -0600开始发布“/ companies”for 127.0.0.1 SQL(25.3ms)BEGIN TRANSACTION SQL(50.4ms)IF @@ TRANCOUNT&gt; 0 ROLLBACK TRANSACTION CACHE(0.0ms)SELECT @@ TRANCOUNT
不确定为什么事务似乎在保存时回滚。我正在使用sql server 2008和tinytds,如果这有帮助。
答案 0 :(得分:0)
嵌套属性允许您通过父级保存关联记录的属性。这里父母是公司记录,嵌套是位置,地址和联系人。只有在公司模型中才需要accepts_nested_attributes_for。在嵌套的地址,联系人和位置模型中不需要accepted_nested_attributes,而不是父项。
答案 1 :(得分:0)
好的,我的代码存在多个问题。我已经彻底淘汰了所有这些并希望发布最终的工作解决方案,以防其他人通过关联和嵌套表单处理has_many。
我的最终模型看起来像这样(使用Rails 3.2.13):
Company.rb
class Company < ActiveRecord::Base
attr_accessible :locations_attributes, :contacts_attributes, :company_name
has_many :locations, dependent: :destroy
has_many :addresses, through: :locations
has_many :contacts
accepts_nested_attributes_for :locations, :reject_if => :all_blank, :allow_destroy => true
accepts_nested_attributes_for :addresses
accepts_nested_attributes_for :contacts
end
Location.rb
class Location < ActiveRecord::Base
attr_accessible :address_attributes, :address, :created_by, :is_active, :location_name, :location_type, :region_id, :updated_by, :website
belongs_to :company
belongs_to :address
accepts_nested_attributes_for :address, :reject_if => :all_blank
end
Address.rb
class Address < ActiveRecord::Base
attr_accessible :address_line_1, :address_line_2, :address_line_3, :address_line_4, :address_line_5, :city, :country, :county, :created_by, :province, :state, :updated_by, :zipcode
has_many :locations, dependent: :destroy
has_many :companies, through: :location
accepts_nested_attributes_for :locations
end
companies_controller.rb
class CompaniesController < ApplicationController
def new
@company = Company.new
@location= @company.locations.build
@address = @company.addresses.build
@contact = @company.contacts.build
end
def show
@company = Company.find(params[:id])
end
def create
@company = Company.new(params[:company])
if @company.save
#handle a successful save
flash[:success] = "Company Created Successfully"
redirect_to @company
else
render 'new'
end
end
end
new.html.erb
<% provide(:title, 'Create Company')%>
<h1>Create Company</h1>
<div class="container">
<%= form_for(@company) do |f| %>
<% if @company.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@company.errors.count, "error") %> prohibited this company from being saved:</h2>
<ul>
<% @company.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="row">
<%= f.label :company_name, "Company Name" %>
<%= f.text_field :company_name %>
<hr>
</div>
<div class="row">
<div class="col-md-6"><h3>Primary Location</h3><hr></div>
<div class="col-md-6"><h3>Location Information</h3><hr></div>
</div>
<%= f.fields_for(:locations) do |lf| %>
<%= lf.fields_for(:address_attributes) do |af| %>
<%= f.fields_for(:contacts) do |cf| %>
<div class="row" >
<div class="col-md-6"><%= af.label "Address 1"%><%= af.text_field :address_line_1 %></div>
<div class="col-md-6"><%= lf.label "Location Type" %> <%= lf.select(:location_type, options_for_select([["Headquarters",11], ["Office", 12]])) %></div>
</div>
<div class="row" >
<div class="col-md-6"><%= af.label "Address 2"%><%= af.text_field :address_line_2 %></div>
<div class="col-md-6"><%= lf.label "Location Name" %> <%= lf.text_field :location_name %></div>
</div>
<div class="row" >
<div class="col-md-6"><%= af.label "Address 3"%><%= af.text_field :address_line_3 %></div>
<div class="col-md-6"><h3>Other Location Information</h3><hr></div>
</div>
<div class="row" >
<div class="col-md-6"><%= af.label "City"%><%= af.text_field :city %></div>
<div class="col-md-3"><button type="button" class="btn btn-primary btn-small btn-block">Services Offered</button></div>
</div>
<div class="row" >
<div class="col-md-6"><%= af.label "State"%><%= af.select(:state, options_for_select([["Alabama","AL"], ["Alaska","AK"]])) %></div>
<div class="col-md-3"><button type="button" class="btn btn-primary btn-small btn-block">Materials Accepted</button></div>
</div>
<div class="row" >
<div class="col-md-6"><%= af.label "Country"%><%= af.select(:country, options_for_select([["United States","USA"], ["United Kingdom","UK"]])) %></div>
<div class="col-md-3"><button type="button" class="btn btn-primary btn-small btn-block">Location Certifications</button></div>
</div>
<div class="row" >
<div class="col-md-6"><%= af.label "Zipcode"%><%= af.text_field :zipcode %></div>
</div>
<div class="row" >
<div class="col-md-12"><h3>Tell us about you</h3></div>
<hr>
</div>
<div class="row">
<div class="col-md-6"><%= cf.label "First Name"%><%= cf.text_field :first_name %></div>
</div>
<div class="row">
<div class="col-md-6"><%= cf.label "Last Name"%><%= cf.text_field :last_name %></div>
</div>
<div class="row">
<div class="col-md-6"><%= cf.label "Title"%><%= cf.text_field :title %></div>
</div>
<div class="row">
<div class="col-md-2"><%= f.submit "Save Info", class: "btn btn-small btn-primary" %></div>
</div>
<% end %>
<% end %>
<% end%>
<% end %>
需要注意的是accepts_nested_attributes_for语句如何链接关联,需要在每个模型attr_accessible语句中添加适当的model_attributes,以及表单如何使用:addresses_attributes在locations_form(lf)中嵌套地址格式(af) 。
此外,我必须从Location.rb中删除外键(company_id,address_id)验证,因为它们导致事务在创建地址或公司记录之前回滚(创建位置的先决条件)