Ruby on Rails devise-roles示例应用权限与文档不符的疑问
Hey there, let's break down the clear mismatch you've spotted between the project's README and the actual UsersController code—it's a classic case where the implementation doesn't align with the documented behavior.
What's the Core Conflict?
The README lays out two key expectations:
- Regular users can view and edit their own personal profiles
- Regular users cannot modify their own role
But when we look at the controller code, two big issues pop up:
- Regular users can't reach the update action at all: The
before_action :admin_only, :except => :showlocks every action exceptshowto admins. So regular users are blocked from even accessing theupdatemethod to edit their profile—this directly contradicts the README's claim. - Admins can only modify roles: The
secure_paramsmethod only permits the:roleattribute. Even if an admin tries to update a user's other profile details (like email, name, etc.), those changes get ignored. This doesn't fit with the idea of "editing personal profiles" for anyone, let alone regular users.
How to Fix This to Match the README
Here are the key adjustments to make the code behave as the documentation describes:
1. Adjust Access Control for the Update Action
Instead of locking all non-show actions to admins, we need to let regular users update their own profiles. Let's tweak the before_action rules and add a custom check:
class UsersController < ApplicationController before_action :authenticate_user! before_action :admin_or_current_user, only: [:update] before_action :admin_only, except: [:show, :update] def show @user = User.find(params[:id]) unless current_user.admin? || @user == current_user redirect_to root_path, alert: "Access denied." end end def update @user = User.find(params[:id]) if @user.update_attributes(secure_params) redirect_to @user, notice: "Profile updated." else render :edit # Or redirect back with errors end end private def admin_only unless current_user.admin? redirect_to root_path, alert: "Access denied." end end def admin_or_current_user @user = User.find(params[:id]) unless current_user.admin? || current_user == @user redirect_to root_path, alert: "Access denied." end end # ... rest of the code ... end
2. Update secure_params to Allow Proper Profile Edits
We need to split permitted attributes based on user role: regular users can edit their own non-role fields, while admins can manage roles too:
def secure_params if current_user.admin? # Admins can edit all relevant fields including role params.require(:user).permit(:role, :name, :email, :password, :password_confirmation) else # Regular users can only edit their own profile, not their role params.require(:user).permit(:name, :email, :password, :password_confirmation) end end
3. Optional: Add a Dedicated Profile Edit Flow (Cleaner Approach)
For better code organization, you could add a separate edit_profile/update_profile set of actions specifically for regular users to manage their own info, keeping admin-focused user management separate. But the changes above will fix the core mismatch.
Why the Original Code Fails the README's Promise
- The original
before_actionrule completely blocks regular users from accessing the update action. - The overly restrictive
secure_paramsmeans even admins can't manage full user profiles—only roles.
With these fixes, regular users will be able to edit their own profile fields (without touching their role), admins can manage all user attributes including roles, and the code will finally match the README's description.
内容的提问来源于stack exchange,提问作者Matis

