From the docs:
params = ActionController::Parameters.new({
person: {
name: 'Francesco',
age: 22,
role: 'admin'
}
})
permitted = params.require(:person).permit(:name, :age)
permitted # => {"name"=>"Francesco", "age"=>22}
permitted.class # => ActionController::Parameters
permitted.permitted? # => true
Chainable method calls are wrong here. It’s okay for doing the most basic possible forms, using all the Rails defaults, but for anything else it’s crap. See bullshit like this - and that’s for sanctioned nested_attributes type calls.
Let’s take a simple example:
params = ActionController::Parameters.new(first: true, second: {first_hash: 1, second_hash: 2, third_hash: 3})
How do we get the values of both :first and :second ? If you know in advance what all the possible keys for :second are, you can do this:
params.permit(:first, :second => [:first_hash, :second_hash, :third_hash])
If you don’t know exactly which keys are there, or want to use logic based on what keys are present… well, no. Definitely not.
If you’re doing doing something like tags, lists, or other things that don’t nicely map to one parameter => single-level hash, you’re in for a rough ride. If you only want to allow certain attributes to be edited by certain users, you need a hacky workaround like building up a giant array or hash before calling .permit
. If you want to call params.permit in a before_filter, get lost. If you want to save Javascript logs or something else with a totally arbitrary structure, go die in a fire.
A better model would be to pass a schema to StrongParameters. Imagine if we could call something like this:
def user_params
params.schema(
user: {
email: String,
tags: [Array, String],
happiness_level: Numeric,
preferences: {
remember_me: Boolean,
email_me: Boolean
},
js_analytics: JSON,
js_events: Array,
js_logs: Hash
}
)
end
This would be way nicer - you could specify conversions so you don’t get strings where you expect numbers or booleans. You could specify what sub-attributes to allow on a hash or array, or just use the raw class if you want to sort it out yourself. And, this theoretical schema
method would just return a new Parameters instance with the schema applied - if you wanted to get different attributes earlier or later in the request, just call params.schema
again.
I’ve been developing with Rails for ten years now. If I find this crap difficult, I can’t imagine what people in coding boot camps must think of it.
Update: the rails_param looks like a good alternative.