Search code examples
ruby-on-railsformsstrong-parameters

Rails 4.2.4 params.permit! fails to ignore utf field in form


In an admin-only controller for scaffolded forms where we have no concern about mass-assignment, we implemented strong parameters using just the permit! method (no .require() or .permit() ) which should simply sets the params permitted flag to true, whitelisting anything in the params object.

private
    def foo_params
      params.permit!
    end

and in the controller we have

def create
  @foo = Foo.new(foo_params)

However, in specs and when running the app, the controller's create method throws the exception:

unknown attribute 'utf8' for Foo

The error goes away if we add .require(:MODEL) eg change the foo_params

private
    def foo_params
      params.require(:foo).permit!
    end

Is .require() supposed required to avoid throwing an exception due to some of the magically-added Rails forms attributes like the utf8 attribute?

(If it makes any difference it's an app upgraded from Rails 3.2 to 4.2 that otherwise works fine.)


Solution

  • This issue is caused by the specificity resulting from the .require().

    Basically, when you submit, the params contains the foo params, as well as the rest of the params. One of which is the utf8 check. There are probably others, like the current action and controller, the submit button, CSRF token, etc. It might look like this:

    {
      utf8: '✓',
      controller: 'foos',
      action: 'create',
      foo: {
        name: 'Albert',
        age: '12' 
      }
    }
    

    When you do params.permit!, you are requesting all of the params. This will inevitably contain attributes that do not exist on your model.

    When you use params.require(:foo).permit!, instead, you end up taking this bit only:

    {
      name: 'Albert',
      age: '12' 
    }
    

    This is what you want to pass to your Foo.new() call.