【问题标题】:Rails fields_for checkbox to create new recordRails fields_for 复选框创建新记录
【发布时间】:2018-12-05 22:55:17
【问题描述】:

我目前正在制作一个表单来编辑用户的信息,表单的一部分是检查他们拥有的角色。

角色存储在自己的表中,该表具有角色类型和用户 ID。

我要做的是为 3 种类型的角色打上复选框,用户可以检查他们应该拥有哪些角色。

表单基本上应该是这样的:

问题是我不知道如何使用表单生成器进行设置。我在用户上设置了accepts_nested_attributes_for :roles,但我不确定这将如何与fields_for 一起使用。

有什么想法吗?

【问题讨论】:

    标签: ruby-on-rails forms


    【解决方案1】:

    您不需要嵌套属性来简单地将关联分配给记录。

    首先你想改变你的表和关联来创建一个规范化表:

    class User < ApplicationRecord
      has_many :user_roles, dependent: :destroy
      has_many :roles, through: :user_roles
    end
    
    # remove user_id from the roles table
    class Role < ApplicationRecord
      validates_uniqueness_of :name
      has_many :user_roles, dependent: :destroy
      has_many :users, through: :user_roles
    end
    
    # rails g model user_role user:references role:references
    class UserRole < ApplicationRecord
      validates_uniqueness_of :role_id, scope: :user_id
      belongs_to :user
      belongs_to :role
    end
    

    这意味着角色的定义name 仅在roles 表中定义一次,而不是为应用于用户的每个角色重复。要将角色分配给用户,您只需在连接表中添加角色 ID 和用户 ID,这样可以更有效地建立索引。

    由于我们不需要为每个用户角色设置重复的名称列,我们可以使用role_ids= 来设置带有复选框的用户角色。

    <%= form_for(@user) do |f| %>
      <%= f.collection_check_boxes(:role_ids, Role.all, :id, :name) %>
      ...
    <% end %>
    

    class UsersController < ApplicationController
    
      # ...
    
      def create
        @user = User.new(user_params)
        # ...
      end
    
      # ...
    
      private
        def user_params
          params.require(:user)
                .permit(:foo, :bar, role_ids: [])
        end
    end
    

    【讨论】:

    • 我希望能够做到这一点,但我们的角色没有标准化,我没有时间对已经建立的角色设置进行更改
    • 我认为您高估了变更的复杂性与坚持有缺陷的解决方案的成本。
    • 在这种情况下,围绕接受嵌套属性设计一个 hack 需要相当长的时间,而且您必须让复选框为每个嵌套记录填写文本输入,或者创建一些控制器中的一种 hack 来更改参数。
    【解决方案2】:

    https://guides.rubyonrails.org/form_helpers.html#nested-forms

    给出的例子是:

    <%= form_for @person do |f| %>
      Addresses:
      <ul>
        <%= f.fields_for :addresses do |addresses_form| %>
          <li>
            <%= addresses_form.label :kind %>
            <%= addresses_form.text_field :kind %>
    
            <%= addresses_form.label :street %>
            <%= addresses_form.text_field :street %>
            ...
          </li>
        <% end %>
      </ul>
    <% end %>
    

    我假设你已经设置好了模型:

    <%= form_for @user do |f| %>
      <%= f.input :first_name %>
      <%= f.input :last_name %>
      Role:
      <ul>
        <%= f.fields_for :roles do |role_f| %>
          <li>
            <%= role_f.check_box :it %>
            <%= role_f.check_box :accounting %>
            <%= role_f.check_box :sales%>
          </li>
        <% end %>
      </ul>
    <% end %>
    

    从那里您可以看到参数如何通过并根据需要创建角色

    【讨论】:

    • 我猜角色有包含类型的字符串列,而不是一堆布尔列,这将是一个非常愚蠢的设计。
    • 这将允许您在一条记录上创建多个角色,但无论哪种方式都感谢您的愉快评论
    • 仍然是一个糟糕的设计 - 想象一下根据用户的角色来查询用户。
    • 这将涉及添加 1 行代码来创建范围。我不确定哪个部分对您来说具有挑战性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 2018-08-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多