Rails Devise attr_accessible problem
-
21-06-2021 - |
题
Im trying to add devise authorization to my rails 3 app. Its all going well except Im also trying to follow this tutorial to dynamically set attr_accessible for role_ids only for admin users (I dont want regular users changing their role, but an admin should be able to do so)... the problem is, the railscast tutorial approach assumes I have access to change the controller behavior when in fact devise is handling all that under the hood.
Please Help
解决方案
You can subclass the Devise controllers, you just have to generate the views and move them to the correct place. Check out "Configuring views" and "Configuring controllers" in the Devise readme.
I ended up adding role_ids to attr_accessible, then subclassing the RegistrationsController and adding a before_filter to remove that param for non-admins.
class Users::RegistrationsController < Devise::RegistrationsController
before_filter :remove_admin_params, :only => [:create, :update]
protected
# disable setting the role_ids value unless an admin is doing the edit.
def remove_admin_params
params[:user].delete(:role_ids) unless current_user.try(:admin?)
end
end
Just make sure to add the registration views to /app/views/users/registrations/
.
其他提示
The best way I found to handle this is from RailsCast 237. It is more verbose than Arrel's answer, but it does not force you to add role (or other fields) to attr_accessible.
Add the following method in an initializer:
class ActiveRecord::Base
attr_accessible
attr_accessor :accessible
private
def mass_assignment_authorizer(role = :default)
if accessible == :all
self.class.protected_attributes # hack
else
# super returns a whitelist object
super + (accessible || [])
end
end
end
Then in your controller, you can do:
user.accessible = :role if can? :set_role, resource
This call, unfortunately, has to be made after the user (or whatever) object has been instantiated. That means that you would have to subclass the controller, and call this after the resource instantiation in update and create.
This is for Rails 3.2. In earlier versions I believe the method mass_assignment_authorizer does not take a parameter. The attr_accessible with no values sets a fail-safe application wide denial for mass assignment. This can also be done in the application.rb file with
config.active_record.whitelist_attributes = true