背景:用户和社区共享
has_many:通过
的关系。每个社区都有一个“community_type”字符串,用于标识它(即“性别”,“城市”等)。
目标:在我的编辑表单中,我想允许用户根据社区类型编辑他的: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” - 而不是将它们全部合并为一个大的: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
答案 0 :(得分: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来绑定到选择标记,并将ID添加到隐藏值,然后使用表单将其提交给服务器。
答案 1 :(得分:1)
您是否有理由使用选择框表示has_many
关系?似乎复选框更合适。如果你想使用选择框,我认为你不能使用FormHelper#select
,因为据我所知,它期望一个值,而你的community_ids
是一个数组。这就是为什么它只选择你给它的一个值。
对于选择框(或任何字段),您可以通过将[]
添加到参数名称来跨字段组合值,该参数名称告诉Rails参数是值数组。您可以使用常规select_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 %>
你也可以采用Ryan发送单独参数的方法,但有一个缺点是你的User
模型必须非常了解存在的社区类型,你必须编写单独的逻辑每种类型社区的User
模型。这将使您的资源更少模块化。但是,如果你这样做,我建议使用伪属性而不是before_save
,以便community_ids
自动更新params
:
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 %>