0

背景:ユーザーとコミュニティは

has_many:through

関係。各コミュニティには、それを識別する「community_type」文字列があります(つまり、「Gender」、「City」など)。

目的:編集フォームで、ユーザーがコミュニティタイプに基づいて:community_idsを編集できるようにします。何かのようなもの:

<%= form_for current_user do |f| %>
<%= f.collection_select(:community_ids, Community.filtered_by("Gender"), :id, :name) %>
<%= f.collection_select(:community_ids, Community.filtered_by("City"), :id, :name) %>
<% end %>

問題は、フォームが:community_idsの最後のフォームフィールド値(この場合は「City」)のみを受け入れることであり、それらすべてを1つの大きな:community_ids配列としてマージするのではありません。

解決:

興味のある人のために、私はモデルコードを以下の答えからこれにリファクタリングすることになりました:

  %W[ community1 community2 community3 community4 ].each do |name|
    define_method "#{name}" do
      self.communities.filtered_by("#{name}").map(&:name)
    end
    define_method "#{name}_ids" do
      self.communities.filtered_by("#{name}").map(&:id)
    end
    define_method "#{name}_ids=" do |val|
      self.community_ids += val
    end
  end
4

2 に答える 2

1

tsherifの(私の元の回答よりも優れている)回答を完了するために更新されました。

view.rb

<%= form_for current_user do |f| %>
  <%= f.collection_select(:community_gender_ids, Community.filtered_by("Gender"), :id, :name, {}, id: 'community-gender-options') %>
  <%= f.collection_select(:community_city_ids, Community.filtered_by("City"), :id, :name, {}, id: 'community-city-options') %>
<% end %>

model.rb

def community_gender_ids=(cg_ids)
  self.community_ids ||= []
  self.community_ids += cg_ids
end

def community_city_ids=(cc_ids)
  self.community_ids ||= []
  self.community_ids += cc_ids
end

def community_gender_ids
  self.communities.select(:id).where(:community_type => 'gender').map(&:id)
end

def community_city_ids
  self.communities.select(:id).where(:community_type => 'city').map(&:id)
end

または、CoffeeScript / Javascriptを記述して、selectタグにバインドし、IDを非表示の値に追加して、フォームとともにサーバーに送信することもできます。

于 2012-04-21T21:10:07.487 に答える
1

関係に選択ボックスを使用している理由はありますhas_manyか?チェックボックスの方が適切なようです。選択ボックスを使用する場合は、を使用できないと思います。FormHelper#select私の知る限り、単一の値を期待しており、あなたcommunity_idsは配列であるためです。これが、指定した値の1つだけを選択する理由です。

[]選択ボックス(または任意のフィールド)の場合、パラメーターが値の配列であることをRailsに通知するパラメーター名に追加することにより、フィールド間で値を組み合わせることができます。これを行うには、regularselect_tagを使用してフィールドを作成し、パラメーター名を次のように設定します。

<%= form_for current_user do |f| %>
  <%= select_tag("user[community_ids][]", options_for_select(Community.filtered_by("Gender").map{|c| [c.name, c.id]}, :selected => current_user.communities.filtered_by("Gender").first.id) %>
  <%= select_tag("user[community_ids][]", options_for_select(Community.filtered_by("City").map{|c| [c.name, c.id]}, :selected => current_user.communities.filtered_by("City").first.id) %>
<% end %>

個別のパラメーターを送信するというライアンのアプローチを採用することもできますが、欠点の1つは、モデルが存在するコミュニティのタイプを十分に認識している必要があり、コミュニティのタイプごとUserにモデルに個別のロジックを記述する必要があることです。Userこれにより、リソースのモジュール性が低下します。ただし、そのようにする場合は、の代わりに疑似属性を使用して、 :から自動的に更新されるbefore_saveようにすることをお勧めします。community_idsparams

class User < ActiveRecord::Base
  ...
  def community_gender_ids=(cg_ids)
    self.community_ids ||= []
    self.community_ids += cg_ids
  end

  def community_city_ids=(cc_ids)
    self.community_ids ||= []
    self.community_ids += cc_ids
  end
  ...
end

そして、あなたのselect_tag呼び出しは次のようになります。

<%= form_for current_user do |f| %>
  <%= select_tag("user[community_gender_ids][]", options_for_select(Community.filtered_by("Gender").map{|c| [c.name, c.id]}, :selected => current_user.communities.filtered_by("Gender").first.id) %>
  <%= select_tag("user[community_city_ids][]", options_for_select(Community.filtered_by("City").map{|c| [c.name, c.id]}, :selected => current_user.communities.filtered_by("City").first.id) %>
<% end %>
于 2012-04-21T21:26:44.090 に答える