新手问题 has_and_belongs_to_many 的插入跟更新问题 [已解决]

sixther · 2016年04月14日 · 最后由 imconfused 回复于 2016年04月16日 · 2659 次阅读

各位好,我有 hosts 跟 groups 两个表,这两个表的关系是 has_and_belongs_to_many,然后我想在修改一个 host 的所属 groups 的时候界面如下: 然后得到的

params[:host][:groups]  ["","3","4"]    #3,4为groupid

问题一,为什么 multiple 类型的 select 框 post 过来的数据会多一个“”呢 问题二: 我使用 params 的数据再更新 host 的逻辑如下,主要分两步,更新除过 groups 以外的字段,update 关联表。 但是感觉怪怪的,所以想问下各位大大这种需求的普遍做法是怎么做的。

def update
    @host=Host.find(params[:id])
    params[:host][:groups].shift    #去掉那个“”
    if @host.update(host_params) and @host.groups=params[:host][:groups].collect {|g| Group.find(g)}
        redirect_to @host
    else
        render 'edit'
    end
end
  1. 看下你的 select 有 :prompt 属性(Create a prompt option with blank value and the text asking user to select something)没
  2. 处理得当的话,是可以直接调用 @host.update(host_params),你这里的做法貌似没有保存 groups

#1 楼 @qinfanpeng 😅,多谢哈 1,我查了下,:prompt 是给 select 框显示一个提示符,而且还属于 select 中的一个元素。 2,我那种方法是可以直接保存关联关系到 groups_hosts 表中的。 然后我尝试给 select 传递的参数不是 id,而是 Group 实例,如下:

#controller
@group_list=Group.all.collect { |g| Array.new << g.groupname << g }
#view
 <%= f.select(:groups, @group_list, {}, {:class => 'form-control',:multiple => true}) %>

但这这时候 params[:host][:groups] 获取到的却是 String 类型的,还是没法保存 😅

试试下面这样

#controller
@groups = Group.all
#view
 <%= f.select(:group_ids, options_from_collection_for_select(@groups, "id", "groupname") , {:class => 'form-control',:multiple => true}) %>

#3 楼 @qinfanpeng 搞定了:

<%= f.select(:group_ids, options_from_collection_for_select(@groups, "id", "groupname") , {include_hidden: false}, {:class => 'form-control',:multiple => true}) %>

options_from_collection_for_select(@groups, "id", "groupname") 这个确实可以直接从 model 对象生成想要的数组,然后 option 里的 include_hidden: false 则可以去掉多出的一个“”

http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-options_from_collection_for_select

Note: The client either sends only the hidden field (representing the deselected multiple select box), or both fields. This means that the resulting array always contains a blank string.

In case if you don't want the helper to generate this hidden field you can specify include_hidden: false option.

更新的话,可以先试 params 获取到表单数据,然后 update 即可。

def update
    @host=Host.find(params[:id])
    if @host.update(host_params)
        redirect_to @host
    else
        render 'edit'
    end
end
private
    def host_params
        params.require(:host).permit(:public_ip, :privite_ip, :server, group_ids: [])   #获取数组的方式需要特别对待
    end

多那个空的是为了当你全部不选的时候不能 update 数据

需要 登录 后方可回复, 如果你还没有账号请 注册新账号