#237 Dynamic attr_accessible
It is important to use attr_accessible for security with mass assignment, but what if you need it to be dynamic based on user permissions? See how in this episode.
- Download:
- source code
- mp4
- m4v
- webm
- ogv
Great Ryan. That's a good solution for a common problem.
Thank you!
I'm implementing this to day.
Keep up the good work.
Cool.. this should also work with required_nested_attribute_for, right?
Hi Ryan, thanks. Could you imagine a way of integrating dynamic attributes with cancan "ability.rb" file? I'm not sure if that would be a good idea to try "unifying" boths...
Great cast Ryan. Does anyone have some examples combining this with declarative_authorization?
... or instead of doing all that, you can just use the guard_protected_attributes option in http://apidock.com/rails/v3.0.0/ActiveRecord/Base/attributes%3D:
@article.send('attributes=', params[:article], !admin?)
@article.save
Nice
On a similar note, everyone should add an initializer with this code:
class ActiveRecord::Base
attr_accessible nil
end
To force all models to use attr_accessible.
You can also set
config.active_record.whitelist_attributes = true
in config.Another option (that is slightly more general and should work with all ActiveModel based libraries) is http://github.com/thefrontiergroup/scoped_attr_accessible - it provides the ability to scope attr_accessible and attr_protected based on arbitrary objects / scoping.
Awesome ryan you actually did an episode about it im sooo happy to see what great use you found for it.
Does this work for rails 2?
great, thanks.
will really love to see how this can be done in rails 2 too..
Thanks for all your great work!
For the similar functionality on Rails 2 you can use plugin: http://github.com/dmitry/attr_accessible_block
You actually can use it on Rails 3, but I haven't tried it yet.
It is realy nice.
This is much better than my filter params method I was using.
The only problem I ran into was that delayed job stopped working. This was because it couldn't mass assign payload_object. The simple fix was to remove the attr_accessible call in the initializer.
Obviously this means that models aren't protected automatically, but I always put attr_accessible in all my models so its not a major problem.
I want to quote Ryan From the comments in another cast
" - However I hope to, at some point, have more time to dedicate to Railscasts and make it my full time job."
I think railscasts is very valuable. I use it all the time as a reference guide.
I think it would be a great thing for the rails community if Ryan can have railscasts a his full time job.
Does anybody agree?
Can we all pull together and come up with suggestions on how railscasts can be free and Ryan can get a full time job income?
Maybe big rails companies can, under a voluntary contract pay Ryan some money every month?
I guess they all benefit a great deal from these casts?
People could use the Donate button in the meantime.
Has a Railscasts ever saved you some time? Expense it!
I completely agree with you Andreas
these casts are the best rails resource i know of!
And even if Ryan will charge subscription per month for them know I will still use them.
as an example there is the lynda.com site that charge 25$ per month.. this is a reasonably price, Railscasts can still be free for the once a week show, but charge money for the rest of the episodes in the other days.. I know for sure that i will use it. And with the right help from the sponsors i think it can be done.. if Ryan would agree of course :)
Nice video. I'd love to see a video on cells which are basically rails components and apotomo, a js framework built on top of it.
The video is really very useful,that's really what i need.It explains how Dynamic attr_accessible works.
I agree,
Ryan you make the best casts i have ever seen. They have the perfect balance of information and pacing.
I have no idea how you do it, it seems like it must be natural!
I wish you all the best in whatever you do.
Ben
@Andreas Lyngstad
I also use rails cast as a reference guide, and it worries me that i no longer see sponsors in the latest cast.
I panic when i dont see a rails cast as its usual time. :S
Another similar plugin for Rails 2.x: http://github.com/SciMed/mass_assignment_fu
Thank you for all (^_^). Railscasts.com is amazing!
why not just overriding in the model like this:
def mass_assignment_authorizer
super + [:important] if current_user.admin?
end
sorry, I meant:
def mass_assignment_authorizer
current_user.admin? ? super + [:important] : super
end
@Tilo because current_user is not available in your model... at least it shouldn't ;)
Thanks for the cast. Does anyone else have to problem with playing the iPhone version on iPhone? Since few episodes ago, I cannot play those anymore (format not supported).
I suggest to recycle your rails server to reload the config initializer ... Thankx Ryan
Hi Ryan,
This again is a remarkable screencast! We really can't praise your importance for the Rails community enough. This screencast has been an eye-opener for me, to say the least.
One question though: I can't seem to figure out how to set attr_accessible dynamically for fields from a related-model?
I have a form for a model x that uses 'accepts_nested_attributes_for' model y. Model x has_many model ys.
If I find the answer myself, I'll post it here!
Kind regards, Kristof
Thanks for the nice RailsCast. Slightly changed your code to work with AR attribute type as well:
https://gist.github.com/919326
Not sure why, but I can't get this to work unless I accept an argument in the mass_assignment_authorizer method located in the initializer. If I do it like the below everything works.
def mass_assignment_authorizer(a=nil)
Perhaps this has changed in Rails 3.1.0.rc4..
irb(main):011:0> Rails.version
=> "3.1.0.rc4"
Thanks for this post Ryan.
Mark
Cool video but it's very hard to understand for a beginner like myself.
Anyone have a tutorial somewhere of a dumbed down version of this?
:)
This is a massive complement to Ryan, but his tutorials really are the simplest to describe the functionality that he is trying to implement in the most elegant way. If you need more dumbed down perhaps you should a: not implement the feature, or do it in a less elegant way with before_save functions on particular attributes (which would work in most cases).
@hounddog - same problem here.
@hounddog @jowls
The
mass_assignment_authorizer
method now takes arole
parameter in Rails 3.1.You can see for yourself here.
Here is the error running under 3.1.0. Can not figure out why. Any suggestions? thanks.
=========================error===
wrong number of arguments (1 for 0)
Rails.root: D:/rails_proj/emclab-failed
Application Trace | Framework Trace | Full Trace
config/initializers/accessible_attributes.rb:7:in
mass_assignment_authorizer'
create'app/controllers/categories_controller.rb:20:in
I got my errors to go away by changing the mass_assignment authorizer to look like this:
I'm not sure if it's right, though.
I am running into the same issue with rails 3.1.3. See below:
@rosobas pointed this out but as people are still having issues, this is what the initializer should look work with rails 3.1 >
mass_assignment_authorizer now takes a role parameter...
In Rails 3.1 there is a nicer way to handle conditional attr_accessible calls. See this blog entry.
The argument over Rails' default permissions for mass assignment was reignited after GitHub was hacked on March 4, 2012.
A Russian GitHub user, Egor Homakov, was arguing for more restrictive defaults, but he was rebuffed over a three day period. To make his point, he exploited this weakness on GitHub, where some model attributes were not protected in the code that handles public key submissions, in order to submit this commit to the rails master branch.
As a result, several commits were made to make whitelisting of model attributes the default behavior of rails generators. We will see if these modifications actually make it to the next release of Rails.
Can you elaborate on why using attr_accessible as: :admin is a better approach than Ryan's approach?
Thanks for great post.
How to integrate this when using cancan's load_resource instance?
Thanks for great post.
How to integrate this when using cancan's load_resource instance?
Great post ! Thx !
Yeah, I'm a little confused about the best method to go about this as well — I guess since update_attributes is deprecated in Master we should be checking attributes via assign and the saving if successful?
I've used this method http://apidock.com/rails/ActiveRecord/AttributeAssignment/assign_attributes