Rails 4 Strong parameters : permit all attributes?
Asked Answered
D

4

77

I'm building a web app with Rails 4 strong parameters.

When building the admin back office controllers, I wonder what is the best way to permit all the model attributes?

For now, I wrote this:

def user_params 
  params.require(:user).permit(User.fields.keys)
end

Do you think of a better way?

Dibbell answered 25/12, 2012 at 20:49 Comment(7)
Why? I only do this kind of things in my administration backoffice where I trust all the users.Dibbell
just because you trust them (and you shouldn't, but that's a different story), leaving all of your data open to be overwritten is a security hole waiting to be taken advantage ofMolliemollify
An important principle in security is the idea of whitelisting the stuff you explicitly want to be available. By explicitly listing you prevent issues like when you (are a collegue) introduces a new key in your code and expecting it to only be available through the controller if taking explicit actions. Or in other words: stick to the conventions unless you have a very very good reason not to do so. Almost everytime I did in the past, I shot myself into the foor.Atkinson
@Molliemollify at least he's asking if there's a better way to do it.Jessalyn
@AndrewGrimm yes, but he still wants to permit everything by default, which is an insecure thing to do and completely negates the point of strong parameters.Molliemollify
@sevenseacat, what if i only want to do with some of the controllers and don't want to type all those keys?Letsou
@Letsou 'because I can't be bothered typing the keys' is quite possibly the worst reason to bypass a security measure.Molliemollify
N
13

Just in case someone need it for Rails 6, without even a model linked to your controller, you can use:

before_action :accept_all_params

private

def accept_all_params
  params.permit!
end

And done, now you can play with 🔥 as much as you want!

Nanon answered 14/1, 2020 at 21:23 Comment(0)
D
152

You can call the bang version of permit.

params.require(:user).permit!

Strong Params README on Github

Source code for reference:

def permit!
  each_pair do |key, value|
    convert_hashes_to_parameters(key, value)
    self[key].permit! if self[key].respond_to? :permit!
  end

  @permitted = true
  self
end
Dzoba answered 26/12, 2012 at 11:9 Comment(11)
On a side note, I think if there was something like permit :all, it seems more Railish than a bang method to me, that usually means the receiver has been altered more often than marking a method as dangerous.Dzoba
yeah but permit(:all) looks like ActiveRecord's find(:all) which is deprecated.Dibbell
@NicolasBlanco: I don't see how it is a problem that permit(:all) looks like find(:all).Guimpe
@daemonsy: permit(:all) permits the field named :all. To make that style work as you say, Rails would have to make a special case for handling :all -- I think that would be ugly and confusing. You would be up a creek if you have a column named 'all'! I agree that the bang method is a suboptimal choice. I would offer permit_all as a better alternative if I were designing the API.Guimpe
Everytime I see this page, I regret a little for the :all comment. =). permit_all does sound like a better alternative than bang.Dzoba
"bang method means marking the method as dangerous" -- I would assume that's exactly why they used the bang method here.Electrophoresis
@Electrophoresis True but even so I think permit_all! would read better. I'm glad this thing exists anyway.Tail
Like said in my comments on the question itself, this is really something you shouldn't do. You're breaking rails conventions...Atkinson
@daemonsy: That's because you have a distorted view of what bang(!) means in a method name. Granted, for some methods it means "alter in place" rather than make a copy. But that is only one way in which it is used. The actual rule is: a bang method (one ending in "!") is one which does not act in the "standard" or expected way, so it deserves extra attention or caution. That is the reason for the "!".Valine
@LonnyEachus, actually, Matz says that: "the bang version is more dangerous than its non bang counterpart; handle with care" (source: ruby-forum.com/topic/176830#773946)Fabrikoid
actually this method alters state of the object in place, note @permitted = trueHecklau
N
13

Just in case someone need it for Rails 6, without even a model linked to your controller, you can use:

before_action :accept_all_params

private

def accept_all_params
  params.permit!
end

And done, now you can play with 🔥 as much as you want!

Nanon answered 14/1, 2020 at 21:23 Comment(0)
P
1

Skull0inc's answer works, but you might want to remove created_at and updated_at. The intention of strong params is to list only the attributes you want updatable by the controller. Something like...

def user_params
  params.require(:user).permit(User.column_names - ["created_at", "updated_at"])
end
Pentamerous answered 7/3, 2019 at 21:51 Comment(0)
B
0

Would this work?

def user_params 
  params.require(:user).permit(User.column_names)
end
Braga answered 13/9, 2018 at 15:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.