I have a Post model with a :published
attribute (boolean) and a User model with a role
attribute (st
So far it is not possible. But according to this: https://github.com/ryanb/cancan/issues/326 this feature should be in cancan 2.0.
Update: you can see this on CanCan 2.0 branch here: https://github.com/ryanb/cancan/tree/2.0 in section "Resource Attributes"
Check out this post: How do I use CanCan with rails admin to check for ownership
It shows how to make a field not visible based off a users role.
UPDATE I was able to set options in rails admin with this code:
config.model User do
edit do
configure :organization do
visible do
bindings[:view]._current_user.max_role_name != 'admin' ? false : true
end
end
configure :organization_id, :hidden do
visible do
true if bindings[:view]._current_user.max_role_name != 'admin'
end
default_value do
bindings[:view]._current_user.organization_id if bindings[:view]._current_user.max_role_name != 'admin'
end
end
include_all_fields
end
end
This configuration will hide the organization field if the logged in user is not an admin. It will then show an organization_id field ( set to type='hidden' ) and set the default value.
Hope this helps someone.
There is a way, I did something like this in my project. But CanCan is not entirely the answer. What you need to do is make attr_accessible in your model dynamic based on user role, so if you're an admin, then you're allowed to update the published field. If not, then giving the field a new value simply won't take when the model saves.
Railscasts comes to the rescue once again: http://railscasts.com/episodes/237-dynamic-attr-accessible
Following getting the backend part of that implemented, then you can do something about the frontend form by wrapping the publish field in the View with a roles check or something to show or hide the field based on the user. Rough example of my implementation...
<% if current_user.roles.where(:name => ['Administrator','Editor']).present? %>
<%= f.label :display_name %>
<%= f.text_field :display_name %>
<% end %>
Until CanCan 2.0 comes out, I've solved this by creating a subclass of the model with restricted accessibility, something like:
class AuthorPost < Post
attr_protected :published
end
And then give authors access to AuthorPosts: can :manage => AuthorPost
Then in your controller, you can set the resource you want in a before_filter:
before_filter :set_resource
...
private
def set_resource
if current_user and current_user.author?
@resource = AuthorPost
else
@resource = Post
end
params[:post] ||= params[:author_post]
end
One last caveat: you won't be able to use load_and_authorize_resource
in that controller. You'll have to do that manually, as detailed here: https://github.com/ryanb/cancan/wiki/Controller-Authorization-Example
You'll need to replace Project
with @resource
.
I'm on the fence as to whether this is more or less effective than the method described in the railscast. For my purposes, it left the original model totally intact, so my other code wasn't affected--and just allowed me to give some users fewer editable fields.