Rails Role-User-Management: has_many через настройку контроллера - PullRequest
0 голосов
/ 28 февраля 2019

Я пытаюсь решить проблему с назначением ролей пользователям.У меня есть пользователь и ролевая модель, я добавил модель RoleAssignment для настройки через has_many.Цель состоит в том, чтобы назначить пользователю много ролей, а роль может иметь много пользовательских назначений.

Это работает, когда я тестировал его в консоли rails, но пока не в своем контроллере.Я думаю, что есть проблема с моей частью params.

В контроллере я использовал

params.require(:user).permit(:name, :email, :password,  :password_confirmation, role_assignments_attributes: [:role, :id])

, но обновление не работает

# app/models/role.rb
class Role < ApplicationRecord
    has_many :role_assignments
    has_many :users, :through => :role_assignments
    validates :name, :presence => true
    validates :description, :presence => true
end

# app/models/role_assignment.rb
class RoleAssignment < ApplicationRecord
    belongs_to :user
    belongs_to :role
end

# app/models/user.rb
class User < ApplicationRecord
    has_many :role_assignments
    has_many :roles, :through => :role_assignments
    accepts_nested_attributes_for :role_assignments

    def has_role?(role_sym)
        roles.any? { |r| r.name.underscore.to_sym == role_sym }
    end
end

UsersController:

class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]

  def edit
  end

  def update
    respond_to do |format|
      if @user.update(user_params) 
        format.html { redirect_to edit_user_path(@user.public_uid), notice: 'User was successfully updated.' }
        format.json { render :show, status: :ok, location: @user }
      else
        format.html { render :edit }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end
  end

  private
    def user_params
      #params.fetch(:user, {})
      params.require(:user).permit(:name, :email, :password,  :password_confirmation, role_assignments_attributes: [:role, :id])
    end
end

users / editview:

<% for role in Role.all %>
<div>
  <%= check_box_tag "user[role_assignments_attributes][]", role.id, @user.roles.include?(role) %>
  <%=h role.name %>
</div>
<% end %>

И вот я попробовал это в консоли rails (успешно)

> 2.4.1 :003 > u.roles << Role.find([1,2])   Role Load (0.6ms)  SELECT "roles".* FROM "roles" WHERE "roles"."id" IN (?, ?)  [["id", 1],
> ["id", 2]]    (0.1ms)  begin transaction   RoleAssignment Create
> (0.4ms)  INSERT INTO "role_assignments" ("user_id", "role_id",
> "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["user_id", 1],
> ["role_id", 1], ["created_at", "2019-02-27 21:51:47.918815"],
> ["updated_at", "2019-02-27 21:51:47.918815"]]   RoleAssignment Create
> (0.2ms)  INSERT INTO "role_assignments" ("user_id", "role_id",
> "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["user_id", 1],
> ["role_id", 2], ["created_at", "2019-02-27 21:51:47.921373"],
> ["updated_at", "2019-02-27 21:51:47.921373"]]    (4.2ms)  commit
> transaction   Role Load (0.2ms)  SELECT  "roles".* FROM "roles" INNER
> JOIN "role_assignments" ON "roles"."id" = "role_assignments"."role_id"
> WHERE "role_assignments"."user_id" = ? LIMIT ?  [["user_id", 1],
> ["LIMIT", 11]]  => #<ActiveRecord::Associations::CollectionProxy
> [#<Role id: 1, name: "Administrator", created_at: "2019-02-27
> 18:26:04", updated_at: "2019-02-27 18:35:26", description:
> "Administrator">, #<Role id: 2, name: "Support", created_at:
> "2019-02-27 18:26:26", updated_at: "2019-02-27 18:35:40", description:
> "Support">]> 
> 2.4.1 :005 > u.save

1 Ответ

0 голосов
/ 28 февраля 2019

Это проще, чем вы пытаетесь сделать.Нет необходимости в nested_attributes, просто используйте метод role_ids.Удалите строку accepts_nested_attributes_for из модели пользователя, измените сильные параметры и сформируйте бит

def user_params
  params.require(:user).permit(:name, :email, :password,  :password_confirmation, role_ids: [])
end

# I suppose you have some kind of @user form in edit view
<% form_for @user do |f| %>
  <%= f.collection_check_boxes(:role_ids, Role.all, :id, :name) %>
<% end %>
...