嵌套表单有很多:通过连接模型,其中连接模型具有附加属性

时间:2017-07-03 15:52:08

标签: ruby-on-rails ruby-on-rails-5

我有两个通过连接模型连接的模型。连接模型存储了一个额外的属性value,这是一个布尔A Role有很多PermissionsRolePermissionRolePermission存储Role }可以执行Permission指示的操作。

Role每个RolePermission都应该有PermissionPermission条记录(其中约有10条)。

但是,我在创建表单时遇到了麻烦。我希望每个value都有一个复选框,用于指示RolePermission的{​​{1}}属性的布尔值。

模型

class Role < ApplicationRecord
    has_many :role_permissions, dependent: :destroy
    has_many :permissions, through: :role_permissions

    accepts_nested_attributes_for :role_permissions
end

class RolePermission < ApplicationRecord
    belongs_to :role
    belongs_to :permission
end

class Permission < ApplicationRecord
    has_many :role_permissions
    has_many :roles, through: :role_permissions
end

表格列

Roles
    name: string
    description: string

Permissions
    name: string
    description: string

RolePermissions
    role: references
    permission: references
    value: boolean

视图/角色/ _form.html.erb

<%= form_for [@chronicle, @role], url: url do |f| %>

    ...

    <%= f.fields_for :role_permissions, Permission.all do |ff| %>
      ???
      <%= ff.label :name %>
      <%= ff.check_box :value %>
      ???
    <% end %>

    <%= f.submit text, class: 'btn btn-primary btn-block' %>
<% end %>

控制器/ roles_controller.rb

class RolesController < ApplicationController
    ...

    def create
      @chronicle = Chronicle.find(params[:chronicle_id])
      @role = @chronicle.roles.build(role_params)
      ???
      @role_permissions = @role.role_permissions.build
      ???

      if @chronicle.save
        flash[:success] = 'Role successfully created.'
        redirect_to chronicle_role_url(@chronicle, @role)
      else
        render 'new'
      end
    end

    private
        def role_params
          params.require(:role).permit(:name, :description, role_permission_attributes: [] )
        end
    end
end

2 个答案:

答案 0 :(得分:1)

我仍然相信没有Role_permission模型的概念。每个角色都应拥有自己的权限(has_many),,但在每个角色都已创建权限时,将重复使用权限名称和说明。

这就是我所做的。

我在角色控制器的私有部分创建了一个带有名称和描述值的哈希值

# roles_controller.rb
def permission_values
  {
    "Can edit" => "This is not good if you want to party", 
    "Can show" => "Yes, yes, yes. Go ahead",
    "Can hike" => "Oh my! A hike-role?",
    "And so on" => "What do we have here?"
  }     
end

然后当我创建角色和权限时,我使用.build和permission_values。

无法使用seeds.rb执行此操作,因为必须在分配权限之前创建角色

#roles_controller.rb
def new
@role = Role.new
  permission_values.each do |titel, desc| 
    @role.permissions.build(name: titel, description: desc)
  end
end

在表单中,我使用.object.hidden_field来显示和创建值。

# _form.html.erb
...
<%= f.fields_for :permissions do |ff|%>
<h4><%= ff.object.name %></h4>
<%= ff.hidden_field :name %>
<p><%= ff.object.description %></p>
<%= ff.hidden_field :description %>
<%= ff.check_box :permitted %>
<% end %>

你有它!

现在每个用户都将显示相同的权限,但是他们可以在需要时检查是否允许并将其与其角色一起保存。 在节目中,类似于:

# show.html.erb
# I would make a helper-method
# And some index-symbol-power!
<%= "Hey! I'm permitted to do this!" if @role.permissions.find_by_name("Can 
edit").permitted? %>

注意:

请记住role_params中permission_attributes中的:id,因此权限在编辑时不会重复。

=============================================== =========================

答案 1 :(得分:0)

RolePermission模型是否必要?

如果我误解了某些内容,请告诉我。为什么不在Permission模型上放置一个布尔属性?

表格列:

Roles
name: string
description: string

Permissions
referenced: role
name: string
description: string
permitted: boolean

现在你可以在field_for中有一个复选框字段,没有任何问题

#In form_for [@chronicle, @role], url: url do |f|  
...
<%= f.fields_for :permissions do |ff| %>
 <%= ff.label :permitted %>
 <%= ff.check_box :permitted %>
 ... <!-- description and name -->
   

和你的控制器

请记住不要在视图中调用Permission.all,而是在RolesController中的new动作中使用.build。

def new
#Find @chronicle
@role = Role.new
10.times { @role.permissions.build }
end

def create 
# If you set up your accepts_nested_attributes_for :permissions 
# (delete the rest of role_permission stuff) in role.rb, 
# and update your role_params with the permission_attributes everything should 
be 
# working fine. Find your role and save it. 
end

然后你可以这样做:

if role.permissions.first.permitted? 
# DO SOMETHING CRAZY
end