Rails 4 + Rolify Gem:用户角色没有通过UI更新

我有一个编辑视图,允许我更新特定用户的角色。 然而,我已经包含了下面的代码,只是为了给你一个想法,当我取消选中页面上的框时,我的控制器中的puts语句正确地认为角色关联是错误的,并且可以在日志中进一步查看。

但是,稍后在日志中,您可以看到角色正在重新关联到“真实”,我不确定为什么会出现这种情况!

如果复选框未选中,我希望将这些角色从用户中删除。

在这里输入图像描述

用户/ edit.html.erb:

 <fieldset>
   <%= form_for @user, :url => {action: "update"}, :html => { :class => 'user-role' } do |f| %>

     <h1 class="h1-heading">User Roles</h1>
     <p class="user-paragraph"> Check the boxes to grant different roles to <%= @user.first_name %> <%= @user.last_name %>:</p>
       <%= f.label(:admin) do %>
         <%= hidden_field_tag(:admin, 0) %>
         <%= check_box_tag(:admin, 1, @user.has_role?(:admin)) %>
         Administrator
       <% end %>

       <%= f.label(:member) do %>
         <%= hidden_field_tag(:member, 0) %>
         <%= check_box_tag(:member, 1, @user.has_role?(:member)) %>
         Member
       <% end %>
     <%= f.submit class: 'btn btn-primary-dialog pull-right' %>  
   <% end %>
 </fieldset>

users_controller.rb:

def update
    @user = User.find(params[:id])
    @customer = current_user.customer
    @logged_in_user = User.find_by_email(current_user.email)

    if params[:admin] == "1"
      @user.grant(:admin)
    elsif params[:admin] == "0"
      @user.remove_role(:admin)
    end

    if params[:member] == "1"
      @user.grant(:member)
    elsif params[:member] == "0"
      @user.remove_role(:member)
    end

    puts "NEW ROLES"
    puts @user.has_role? :member
    puts @user.has_role? :admin

    if @user.update_attributes(params[:user])
      puts "UPDATING USER"
      puts @user.has_role? :member
      puts @user.has_role? :admin
      redirect_to '/users/show', :flash => { :alert => 'User was successfully updated.' }          
      end
    end
  end

日志:

正如你在下面看到的,它返回'false',然后当更新属性时,再次将角色设置为'true',并且我无法弄清楚在哪里或为什么发生了!

Started PATCH "/users/51" for 127.0.0.1 at 2015-06-26 13:48:58 +1000
Processing by UsersController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"+qNti57HxMa2B/a+c6nS71Qp0p7hf+kTE4b5eiBI4No=", "admin"=>"0", "member"=>"0", "commit"=>"Update User", "id"=>"51"}
  User Load (0.5ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1
  Customer Load (0.3ms)  SELECT `customers`.* FROM `customers` WHERE `customers`.`email` = 'ryan@ryandrake.com' LIMIT 1
  Company Load (0.2ms)  SELECT `companies`.* FROM `companies` WHERE `companies`.`domain` = 'ryandrake.com' LIMIT 1
  CustomerAccess Load (0.3ms)  SELECT `customer_accesses`.* FROM `customer_accesses` WHERE `customer_accesses`.`customer_id` = 1 LIMIT 1
  User Load (0.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 51 LIMIT 1
  CACHE (0.0ms)  SELECT `customers`.* FROM `customers` WHERE `customers`.`email` = 'ryan@ryandrake.com' LIMIT 1
  User Load (0.2ms)  SELECT `users`.* FROM `users` WHERE `users`.`email` = 'ryan@ryandrake.com' LIMIT 1
  Role Load (0.3ms)  SELECT `roles`.* FROM `roles` INNER JOIN `users_roles` ON `roles`.`id` = `users_roles`.`role_id` WHERE `users_roles`.`user_id` = 51 AND `roles`.`name` = 'admin'
   (0.1ms)  BEGIN
   (0.2ms)  DELETE FROM `users_roles` WHERE `users_roles`.`user_id` = 51 AND `users_roles`.`role_id` IN (9)
   (0.9ms)  COMMIT
   (0.3ms)  SELECT COUNT(count_column) FROM (SELECT 1 AS count_column FROM `users` INNER JOIN `users_roles` ON `users`.`id` = `users_roles`.`user_id` WHERE `users_roles`.`role_id` = 9 LIMIT 1) subquery_for_count
  Role Load (0.3ms)  SELECT `roles`.* FROM `roles` INNER JOIN `users_roles` ON `roles`.`id` = `users_roles`.`role_id` WHERE `users_roles`.`user_id` = 51 AND `roles`.`name` = 'member'
   (0.1ms)  BEGIN
   (0.2ms)  DELETE FROM `users_roles` WHERE `users_roles`.`user_id` = 51 AND `users_roles`.`role_id` IN (3)
   (0.4ms)  COMMIT
   (0.5ms)  SELECT COUNT(count_column) FROM (SELECT 1 AS count_column FROM `users` INNER JOIN `users_roles` ON `users`.`id` = `users_roles`.`user_id` WHERE `users_roles`.`role_id` = 3 LIMIT 1) subquery_for_count
NEW ROLES
  Role Load (0.7ms)  SELECT `roles`.* FROM `roles` INNER JOIN `users_roles` ON `roles`.`id` = `users_roles`.`role_id` WHERE `users_roles`.`user_id` = 51 AND (((roles.name = 'member') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))
false
  Role Load (0.6ms)  SELECT `roles`.* FROM `roles` INNER JOIN `users_roles` ON `roles`.`id` = `users_roles`.`role_id` WHERE `users_roles`.`user_id` = 51 AND (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))
false
   (0.3ms)  BEGIN
  Customer Load (0.3ms)  SELECT `customers`.* FROM `customers` WHERE `customers`.`email` = 'ryan.drake2@otherlevels.com' LIMIT 1
  ExtraCustomerAccount Load (0.6ms)  SELECT `extra_customer_accounts`.* FROM `extra_customer_accounts` WHERE `extra_customer_accounts`.`email` = 'ryan.drake2@otherlevels.com' LIMIT 1
  Customer Load (0.3ms)  SELECT `customers`.* FROM `customers` WHERE `customers`.`id` = 1 LIMIT 1
  Company Load (0.2ms)  SELECT `companies`.* FROM `companies` WHERE `companies`.`domain` = 'otherlevels.com' LIMIT 1
  Company Load (0.2ms)  SELECT `companies`.* FROM `companies` WHERE `companies`.`name` = 'None' ORDER BY `companies`.`id` ASC LIMIT 1
  Role Load (0.3ms)  SELECT `roles`.* FROM `roles` WHERE `roles`.`name` = 'member' AND `roles`.`resource_type` IS NULL AND `roles`.`resource_id` IS NULL ORDER BY `roles`.`id` ASC LIMIT 1
  Role Exists (0.2ms)  SELECT 1 AS one FROM `roles` INNER JOIN `users_roles` ON `roles`.`id` = `users_roles`.`role_id` WHERE `users_roles`.`user_id` = 51 AND `roles`.`id` = 3 LIMIT 1
   (0.2ms)  SELECT `roles`.id FROM `roles` INNER JOIN `users_roles` ON `roles`.`id` = `users_roles`.`role_id` WHERE `users_roles`.`user_id` = 51
  Role Load (0.2ms)  SELECT `roles`.* FROM `roles` WHERE `roles`.`id` = 3 LIMIT 1
  Role Load (0.3ms)  SELECT `roles`.* FROM `roles` INNER JOIN `users_roles` ON `roles`.`id` = `users_roles`.`role_id` WHERE `users_roles`.`user_id` = 51
   (0.2ms)  INSERT INTO `users_roles` (`user_id`, `role_id`) VALUES (51, 3)
  Role Load (0.6ms)  SELECT `roles`.* FROM `roles` WHERE `roles`.`name` = 'admin' AND `roles`.`resource_type` IS NULL AND `roles`.`resource_id` IS NULL ORDER BY `roles`.`id` ASC LIMIT 1
  Role Load (0.3ms)  SELECT `roles`.* FROM `roles` WHERE `roles`.`id` IN (3, 9)
   (0.2ms)  INSERT INTO `users_roles` (`user_id`, `role_id`) VALUES (51, 9)
   (0.3ms)  COMMIT
UPDATING USER
  Role Load (0.4ms)  SELECT `roles`.* FROM `roles` INNER JOIN `users_roles` ON `roles`.`id` = `users_roles`.`role_id` WHERE `users_roles`.`user_id` = 51 AND (((roles.name = 'member') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))
true
  Role Load (0.3ms)  SELECT `roles`.* FROM `roles` INNER JOIN `users_roles` ON `roles`.`id` = `users_roles`.`role_id` WHERE `users_roles`.`user_id` = 51 AND (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))
true
  Role Load (0.3ms)  SELECT `roles`.* FROM `roles` INNER JOIN `users_roles` ON `roles`.`id` = `users_roles`.`role_id` WHERE `users_roles`.`user_id` = 1 AND (((roles.name = 'otherlevels_admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))
Redirected to http://localhost:3000/users/show
Completed 302 Found in 80ms (ActiveRecord: 15.1ms)

想要指出它没有正确更新参数的地方,会非常感激!


你的主要问题在这里:

@user.update_attributes(params[:user_id])

编辑 - 我原来的解决方案根本不起作用。

与我原来的解决方案不同,这不需要简单的表单。

首先设置我们的表单:

<%= form_for(@user, url: {action: "update"}, html: { class: 'user-role' }) do |f| %>
  <h1 class="h1-heading">User Roles</h1>
  <p class="user-paragraph"> Check the boxes to grant different roles to <%= @user.first_name %> <%= @user.last_name %>:</p>
  <%= f.fields_for(:roles) do |r| %>
    <%= r.hidden_field :name unless r.object.persisted? %>
    <%= r.label :_keep do %>
      <%= r.check_box :_keep, checked: r.object.persisted? %>
      <%= r.object.name %>
    <% end %>
  <% end %>
<% end %>

我们将传递角色的一些嵌套属性:

  • name (用于新角色)
  • _keep一个虚拟属性 - 我们保存角色
  • id (如果角色存在,则由rails自动插入)
  • 然后,我们将用户类修改为accepts_nested_attributes_for :roles

    class User < ActiveRecord::Base
      rolify
      accepts_nested_attributes_for :roles,
        allow_destroy: true,
        reject_if: ->(hash){ hash["_keep"] != "1" }
    end
    

    注意reject_if: ->(hash){ hash["_keep"] != "1" }这意味着如果复选框未被选中,我们不会创建角色,并且allow_destroy会在_delete=true删除角色。

    我们需要将_keep虚拟属性添加到角色:

    class Role < ActiveRecord::Base
      has_and_belongs_to_many :users, :join_table => :users_roles
      belongs_to :resource, :polymorphic => true
      validates :resource_type,
                :inclusion => { :in => Rolify.resource_types },
                :allow_nil => true
      scopify
      attr_accessor :_keep
      AVAILABLE_ROLES = %w{ administrator member }
    end
    

    我们还添加一个AVAILABLE_ROLES常量,以便我们可以获取角色列表。

    class UsersController < ApplicationController
      before_action :set_user, only: [:show, :edit, :update, :destroy]
    
      # ...
    
      # GET /users/1/edit
      def edit
        # Seed checkboxes for roles
        Role::AVAILABLE_ROLES.each do |role|
          # This adds an unsaved role to the user if it does not exist
          @user.roles.build(name: role) unless @user.has_role?(role)
        end
      end
    
      # PATCH/PUT /users/1
      def update
        if @user.update(update_params)
          redirect_to @user, notice: 'User was successfully updated.'
        else
          render :edit
        end
      end
    
      private
        # Use callbacks to share common setup or constraints between actions.
        def set_user
          @user = User.find(params[:id])
        end
    
        # Only allow a trusted parameter "white list" through.
        def user_params
          params.require(:user).permit(:username, :email, roles_attributes: [:name, :id, :_keep, :_destroy])
        end
    
        def update_params
          user_params.tap do |o|
            # Adds the _delete attribute if the keep checkbox is unchecked
            o[:roles_attributes] = o[:roles_attributes].map do |k,h|
               attrs = h.merge(_destroy: (h[:_keep] != "1"))
               # Don't let the user update the name of an existing Role!
               # This would let a malicious user to grant any role.
               h.key?(:id) ? attrs.except(:name) : attrs 
            end
          end
        end
    end
    
    链接地址: http://www.djcxy.com/p/86003.html

    上一篇: Rails 4 + Rolify Gem: User roles aren't being updated via UI

    下一篇: Print NominalDiffTime as hours, minutes and seconds