中心的な問題:ネストされたフォームからの一括割り当て中に、キーによって属性コレクションをどのようにマージしますか。
詳細:次のモデルを使用しています。
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
そのため、場所ごとに 1 つのコンテナー タイプしか持たないという制約があります。次のビューは、場所と関連するコンテナーをレンダリングします。
管理者/コンテナ/_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 -%>
管理者/コンテナ/_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
-実際には、それを使用してコードと複雑さを増加させるのではなく、削減したかったのです。