75

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?

ronalchn
  • 12,225
  • 10
  • 51
  • 61
Nicolas Blanco
  • 11,164
  • 7
  • 38
  • 49
  • Why? I only do this kind of things in my administration backoffice where I trust all the users. – Nicolas Blanco Feb 28 '14 at 08:38
  • 1
    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 of – sevenseacat Feb 28 '14 at 09:11
  • 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. – bert bruynooghe May 30 '14 at 07:53
  • 2
    @sevenseacat at least he's asking if there's a better way to do it. – Andrew Grimm Jul 15 '15 at 23:23
  • 1
    @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. – sevenseacat Jul 16 '15 at 03:06
  • @sevenseacat, what if i only want to do with some of the controllers and don't want to type all those keys? – Anwar Oct 20 '15 at 06:06
  • 5
    @Anwar 'because I can't be bothered typing the keys' is quite possibly the worst reason to bypass a security measure. – sevenseacat Oct 21 '15 at 01:54

4 Answers4

150

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
Damon Aw
  • 4,722
  • 4
  • 28
  • 37
  • 7
    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. – Damon Aw Dec 27 '12 at 05:00
  • 1
    yeah but permit(:all) looks like ActiveRecord's find(:all) which is deprecated. – Nicolas Blanco Dec 27 '12 at 10:29
  • 1
    @NicolasBlanco: I don't see how it is a problem that `permit(:all)` looks like `find(:all)`. – David J. Mar 05 '13 at 03:40
  • 11
    @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. – David J. Mar 05 '13 at 03:42
  • 27
    Everytime I see this page, I regret a little for the `:all` comment. =). `permit_all` does sound like a better alternative than bang. – Damon Aw Mar 05 '13 at 10:22
  • 13
    "bang method means marking the method as dangerous" -- I would assume that's exactly why they used the bang method here. – Andrew Mar 13 '13 at 02:46
  • 2
    @Andrew True but even so I think `permit_all!` would read better. I'm glad this thing exists anyway. – mahemoff Jan 16 '14 at 23:30
  • Like said in my comments on the question itself, this is really something you shouldn't do. You're breaking rails conventions... – bert bruynooghe May 30 '14 at 07:57
  • 3
    @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 "!". – Lonny Eachus Aug 11 '14 at 01:26
  • @LonnyEachus, actually, Matz says that: "the bang version is more dangerous than its non bang counterpart; handle with care" (source: https://www.ruby-forum.com/topic/176830#773946) –  May 04 '16 at 11:42
  • actually this method alters state of the object in place, note @permitted = true – Dr.Strangelove Jun 21 '18 at 01:51
12

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!

vvo
  • 2,653
  • 23
  • 30
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
0

Would this work?

def user_params 
  params.require(:user).permit(User.column_names)
end
Skull0inc
  • 51
  • 1
  • 4