In my main project, I have sworn off the use of attr_accessible. It is not that I don’t believe in security. I do. The reason is simple: using attr_accessible makes it hard to use the block forms of new and create with any sort of confidence.
For example, if I use this in my Goal model:
attr_accessible :title, :description
Then it would intercept:
goal = Goal.new(
:title => “Sample Title”,
:description => “Sample Description”,
:uid => “GA-Sample”
)
…and convert goal.uid to nil! This will happen in test code, controller code, model code, anywhere! It seems clear to me that attr_accessible is going too far. I can appreciate how it can prevent a hacker from taking advantage of a situation where you use:
goal = Goal.new(params[:goal])
And that is a good thing. But I don’t want attr_accessible “protecting” me from using the block forms of new and create all the time, especially in tests and models. It seems to me that it should only bust out the security blanket when in controller logic.
This is my main gripe: if I use attr_accessible, I have do mental jumping jacks to remember what attributes I can pass into new and create. If I get it wrong, Rails silently ignores them and oh joy, my cup will soon overfloweth with a veritable cornucopia of hard-to-find errors. If I’m lucky. Thank you sir! — I’ll have another. With friends like that, who needs enemies. No longer and good riddance.
Now, I don’t know about you, but I really like using the block form of new and create. It’s handy and DRY. The alternative is resorting to:
goal = Goal.new
goal.title = “Sample Title”
goal.description = “Sample Description”
goal.uid = “GA-Sample”
That’s just a little ugly and repetitive, not acceptable for a programmer that aspires to laziness.
Could there be a better way that lets us use the block forms of new and create while keeping the benefits of attr_accessible (and attr_protected for that matter)?
A Better API?
Here is a proposed API that I think would preserve the intention of attr_accessible without having it get in your way:
attr_accessible :title, :description
…
goal = Goal.new_from_params
goal = Goal.create_from_params
Want to call new or create straight from a params hash? Then you would use these methods, which will protect you from stray parameters. But if you want to use the block forms of new and create, you still can, because, in this dreamed up API, attr_accessible won’t get in your way.
In conclusion, I can appreciate how ‘attr_accessible’ intends to make Web applications more secure. I just find that it goes too far, that’s why I suggest this alternative.
(The blog post was inspired by a rant I wrote many months ago at the bottom of some code. I just rediscovered it and found that it still resonated with me. Hopefully the attr_accessible fanboys out there are not too offended.)
Merb’s Style
June 10, 2008 Update: Checkout the merb_param_protection plugin to see a way to handle parameter protection in Merb. Yehuda Katz said that that parameter filtering makes more sense at the controller level instead of the model level. With the plugin, when writing controller code, you can use the regular block forms to instantiate a model, since the controller will filter parameters automatically.
One Comment
+1
Post a Comment