Rails has_many关联仅允许添加新关系

时间:2019-02-27 12:36:24

标签: ruby-on-rails

我正在寻找一种允许某人从选项列表(从相关模型)中进行选择的方法。列表很简单:

= f.association :selected_companies, as: :check_boxes, collection: Company.order(:name)

以正确的方式设置模型后,我现在可以从列表中选择和取消选择公司。

现在,我正在尝试对此进行改进,以便用户只能选择新公司,而不能删除已经选择的公司。在Rails中有实现此目的的简便方法吗?

因此需要澄清:

  1. 用户可以选择一个或多个选项
  2. 用户保存表单(为每个所选选项创建新记录)
  3. 用户返回页面,无法取消选择已选择的记录,但是可以检查其他记录并再次单击“保存”。

1 个答案:

答案 0 :(得分:1)

Rails中的关联checkboxes and select helpers通过使用_ids=设置程序和_ids吸气器auto-generated by has_many and has_and_belongs_to_many associations来工作。 SimpleForm只是将它们包装起来有点方便和时尚。

_ids=设置器将使用一个数组,并将自动在联接表中添加或删除行。

@user = User.create!(name: "Bob", selected_company_ids: [1,2,3])
# This removes the assocation with 3 and adds an association to 4
@user.update!(selected_company_ids: [1,2,4])

如果您只允许用户添加到关联中,则需要将输入与现有ID合并:

ids = (@user.selected_company_ids + [1,2,4]).uniq
@user.update!(selected_company_ids: ids)
@user.selected_company_ids == [1,2,3,4] # true

在控制器中,您可以通过以下方式实现:

class UsersController < ApplicationController
  # ...
  def update
     @user = User.eager_load(:selected_companies).find(params[:id])
     ids = (user_params[:selected_company_ids].map(&:to_i) + @user.selected_company_ids).uniq
     if @user.update(user_params.merge(selected_company_ids: ids))
       redirect_to @user
     else
       render :edit
     end
  end

  # ...

  def user_params
    params.require(:user)
          .permit(:name, selected_company_ids: [])
  end
end

要禁用现有输入,请使用collection_check_boxes帮助器:

= f.collection_check_boxes(:selected_company_ids, Company.order(:name), :id, :name) do |b|
  = b.label
  = b.check_box(disabled: b.object.selected_company_ids.include?(b.value))
end

AFAIK SimpleForm不会占用每个呈现输入的自定义功能,因此需要更复杂的解决方案,例如创建自己的表单构建器。