我有一个编辑视图,允许我更新特定用户的角色.我已经包含了下面的代码,但是,为了给你一个想法,当我取消选中页面上的框时,我的控制器中的put语句正确地发现角色关联是错误的,可以在日志中进一步查看.
但是,稍后在日志中,您可以看到角色重新关联回“true”,我不确定为什么会出现这种情况!
用户/ 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,@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`,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 %>
我们将为角色传递一些嵌套属性:
>名称(适用于新角色)
> _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 [“_ keep”]!=“1”}这意味着如果取消选中该复选框,我们就不会创建一个角色,而如果我们传递_delete = true则会删除该角色的allow_destroy .
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