Accepts_nested_attributes 和 validates_uniqueness_of
中心问题:在嵌套表单的批量分配过程中,如何通过键合并属性集合。
详细信息:我使用以下模型:
class Location < ActiveRecord::Base
has_many :containers,
:dependent => :destroy,
:order => "container_type ASC"
validates_associated :containers
accepts_nested_attributes_for :containers,
:allow_destroy => true,
:reject_if => proc {|attributes| attributes["container_count"].blank? }
end
class Container < ActiveRecord::Base
belongs_to :location, :touch => true
validates_presence_of :container_type
validates_uniqueness_of :container_type, :scope => :location_id
validates_numericality_of :container_count,
:greater_than => 0,
:only_integer => true
end
因此存在每个位置只能有一种集装箱类型的限制。以下视图呈现位置和关联的容器:
admin/containers/_index.html.erb
<% remote_form_for [:admin, setup_containers(@location)] do |f| -%>
<% f.fields_for :containers do |container_form| -%>
<%= render "admin/containers/form", :object => container_form %>
<% end -%>
<%= f.submit "Speichern" %>
<% end -%>
admin/containers/_form.html.erb
<% div_for form.object do -%>
<span class="label">
<%- if form.object.new_record? -%>
<%= form.select :container_type, { "Type1" => 1, "Type2" => 2, ... } %>
<%- else -%>
<%= form.label :container_count, "#{form.object.name}-Container" %>
<%= form.hidden_field :container_type %>
<%- end -%>
</span>
<span class="count"><%= form.text_field :container_count %></span>
<%- unless form.object.new_record? -%>
<span class="option"><%= form.check_box :_destroy %> Löschen?</span>
<%- end -%>
<% end -%>
module Admin::ContainersHelper 本质上
def setup_containers(location)
return location if location.containers.any? {|l| l.new_record? }
returning location do |l|
all_container_types = [1, 2, ...]
used_container_types = l.containers.try(:collect, &:container_type) || []
next_container_type = (all_container_types - used_container_types).first
l.containers.build :container_type => next_container_type if next_container_type
end
end
,助手将一个新容器添加到集合中,除非所有类型都已关联或集合中已存在新容器。该容器被预初始化为第一个尚未定义的容器类型。到目前为止,效果非常好。添加容器有效。删除容器有效。
问题是:我想实现选择和添加集合中已有的容器类型应该总结它们的计数(相反,它会违反唯一约束)。我不确定在不实现/重新发明完整的 accepts_nested_attributes_for
魔法的情况下最好的方法是什么 - 实际上我想通过使用它来减少 - 而不是增加 - 代码和复杂性。
The central problem: How do you merge attribute collections by a key during mass assignment from a nested form.
The details: I am using the following models:
class Location < ActiveRecord::Base
has_many :containers,
:dependent => :destroy,
:order => "container_type ASC"
validates_associated :containers
accepts_nested_attributes_for :containers,
:allow_destroy => true,
:reject_if => proc {|attributes| attributes["container_count"].blank? }
end
class Container < ActiveRecord::Base
belongs_to :location, :touch => true
validates_presence_of :container_type
validates_uniqueness_of :container_type, :scope => :location_id
validates_numericality_of :container_count,
:greater_than => 0,
:only_integer => true
end
So there is a constraint of having only one container type per location. The following views render the location and associated containers:
admin/containers/_index.html.erb
<% remote_form_for [:admin, setup_containers(@location)] do |f| -%>
<% f.fields_for :containers do |container_form| -%>
<%= render "admin/containers/form", :object => container_form %>
<% end -%>
<%= f.submit "Speichern" %>
<% end -%>
admin/containers/_form.html.erb
<% div_for form.object do -%>
<span class="label">
<%- if form.object.new_record? -%>
<%= form.select :container_type, { "Type1" => 1, "Type2" => 2, ... } %>
<%- else -%>
<%= form.label :container_count, "#{form.object.name}-Container" %>
<%= form.hidden_field :container_type %>
<%- end -%>
</span>
<span class="count"><%= form.text_field :container_count %></span>
<%- unless form.object.new_record? -%>
<span class="option"><%= form.check_box :_destroy %> Löschen?</span>
<%- end -%>
<% end -%>
module Admin::ContainersHelper
def setup_containers(location)
return location if location.containers.any? {|l| l.new_record? }
returning location do |l|
all_container_types = [1, 2, ...]
used_container_types = l.containers.try(:collect, &:container_type) || []
next_container_type = (all_container_types - used_container_types).first
l.containers.build :container_type => next_container_type if next_container_type
end
end
Essentially, the helper adds an new container to the collections except all types have already been associated or there is already a new container in the collection. This container is preinitialized to the first not-yet-defined container type. This works out pretty well so far. Adding containers works. Deleting containers works.
The problem is: I want to achieve that choosing and adding a container type which is already in the collection should sum up their counts (instead it would violate the unique constraint). I'm not sure what would be the best way without implementing/reinventing the complete accepts_nested_attributes_for
magic - actually I wanted to reduce - not increase - code and complexity by using that.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论