Search code examples
arraysruby-on-rails-4strong-parameters

Rails 4: strong parameters and array of scalars must be listed last on permit?


See the people_controller#person_params method for the code version of the question:

# person.rb
class Person < ActiveRecord::Base
  # Attributes:
  # - names (string)
  # - age (integer)

  # Combine: ["a", "b", "c", ...] => "a,b,c"
  def names=(values)
    self[:names] = values.join(",") if values.present?
  end
end

# people_controller.rb
class PeopleController < ApplicationController
  def create
    @record = Record.new(person_params)
    @record.save!
  end

  def person_params
    params.require(:person).permit(
      # Works fine
      :age,
      names: []

      # Works fine
      { names: [] },
      :age

      # Does not work (SyntaxError)
      names: [],
      :age
    )
  end
end

The question is, why does the names scalar array not work when you list it at the beginning without wrapping it as a hash?

The http://edgeguides.rubyonrails.org/action_controller_overview.html#strong-parameters doc examples don't wrap scalar arrays with a hash, but they aren't very complex examples, either.

Is this expected behavior for strong_parameters?


Solution

  • This is not a strong_params thing, but rather how ruby is reading list of attributes. In Ruby, you can only omit the curly brackets around the hash when it is the last argument for the method, so this call:

    any_method(arg1, arg2, key: value, foo: :bar)
    

    is read as:

    any_method(arg1, arg2, { key: value, foo: :bar })
    

    You cannot omit the brackets if the hash is not a last argument though, hence this:

    any_method(arg1, key: value, arg2)
    

    will raise a syntax error.