Documentation unclear #110

denisemauldin opened this Issue Feb 28, 2013 · 3 comments

2 participants


It's not clear what the intention of #require is. Are all parameters that are 'required' to be in the parameters list for a model supposed to be in the #require? I read :

   params.require(:person).permit(:name, :age)

to mean that in the params hash, there MUST be a :person key and there may also be a name and age key. ie:

params = { :person => 'person', :name => 'John', :age => "23" }

Whereas it seems that the code means that there must be a person key and inside of that there may be a name and age key. ie:

 params => { :person => { :name => "John", :age => "23" } }

It would be useful to clarify the documentation as to what 'require' and 'permit' mean. I thought that because I have a validation for name being required, that I needed to have name as a required parameter, not as a permitted parameter. Alternately, I thought I could force name to be required by adding it in the require (and have another way of doing a validation). ie: This would work:

params => { :person => 'blah', :name => "John" }

and this would fail (because :name was also required):

params => { :person => "blah", :age => "23" }

It's also unclear from the documentation that #permit only works after a require and why it works that way.


I agree this is unclear; furthermore, once you realise how the require -> permit chain is expected to be used, it still leaves unanswered questions, e.g.

  • Are name and age both required nested parameters, or would { :person => { :name => "John" } } be accepted?
  • If the latter, how do I make them required nested parameters?
  • How would I make name required but age optional (but still permitted via the whitelist) ?
  • Is it enough to call these methods on params, or does the result have to be used in resulting calls to the model's #create / #update actions? It seems the answer is the latter, but this is not explicitly mentioned, and it's extra confusing given that in the case where multiple parameters are required, all but the penultimate return value are discarded.

Just found another apparently undocumented ambiguity:

  • .permit(nested: []) allows { nested: [ 'anything', 'goes', 'here' ] }, whereas
  • .permit(nested: [ :foo ]) allows { nested: { foo: 'bar' } }

And another weakness: explains that in order to allow a nested hash with arbitrary keys, you need to jump through ugly hoops:

def product_params
  params.require(:product).permit(:data).tap do |whitelisted|
    whitelisted[:data] = params[:product][:data]

(Actually that's not quite what it says, but I already submitted rails/rails#12151 to fix the existing typo.)

However this recommended code is hard to understand, and also emits a highly misleading error message: Unpermitted parameters: data. Furthermore, it's not clear why this is better than simply writing:


Even if the recommended code is deliberately more complicated than it needs to be in order to suggest a way of doing more complicated validations, it still seems unnecessary. For example, if you wanted to filter certain parts of params[:product][:data] (e.g. via regular expressions), you could do something like:

def product_params
  params.require(:product).fetch(:data, {}).inject({}) do |whitelisted, (k, v)|
    whitelisted[k] = v if k =~ allowed_key_regexp

since presumably there is no hard requirement to return an ActionController::Parameters object when a vanilla Hash will suffice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment