& other fun party conversations
🖕Hello🖕
People do terrible things.Â
Like this:Â
class User < ActiveRecord::Base {
:id => :integer,
:handle => :string,
:admin => :boolean
}
# DO NOT THIS
def create
User.create(params[:user])
end
params = { user: { handle: "BadGuy", admin: true } }
class PeopleController < ActionController::Base
# This will raise an ActiveModel::ForbiddenAttributes exception
# because it's using mass assignment without an explicit permit
# step.
def create
Person.create(params[:person])
end
# This will pass with flying colors as long as there's a person key
# in the parameters, otherwise it'll raise a
# ActionController::ParameterMissing exception, which will get
# caught by ActionController::Base and turned into that 400 Bad
# Request reply.
def update
person = current_account.people.find(params[:id])
person.update_attributes!(person_params)
redirect_to person
end
private
# Using a private method to encapsulate the permissible parameters
# is just a good pattern since you'll be able to reuse the same
# permit list between create and update. Also, you can specialize
# this method with per-user checking of permissible attributes.
def person_params
params.require(:person).permit(:name, :age)
end
end
pls stop
STAHP
srsly guise
This specifies a required parameter.
params =
{ wrong_key:
{
key1: "thing_one",
key2: "thing_two"
}
}
def object_params
params.require(:object)
.permit(:key1, :key2, :_destroy)
end
# ActionController::ParameterMissing: param is
# missing or the value is empty: objects
{}
Just what it says on the tin.
This is all you need most of the time.
params =
{ object:
{ key1: "thing_one",
key2: "thing_two",
key0: "not_permitted"
}
}
def object_params
params.require(:object)
.permit(:key1, :key2, :_destroy)
end
# Unpermitted parameter: key0
{
"key1" => "thing_one",
"key2" => "thing_two"
}
You'll get back:Â
We can permit any scalar value, so arrays are ok.
params =
{
object:
{
key1: [ "thing_one", "thing_two" ]
}
}
def object_params
params.require(:object).permit(key1: [])
end
We can redefine our method.
def object_params
params.require(:object).permit(key1: [])
end
# Result
{
"key1" => ["thing_one", "thing_two"]
}
This breaks our current definition with a NoMethodError.
params =
{
objects:
[
{ key1: "one_one", key2: "one_two" },
{ key1: "two_one", key2: "two_two" }
]
}
# NoMethodError: undefined method 'permit'
# for #Array:0x00007f2e59a70b50
def object_params
params.require(:objects).map do |object|
object.permit(:key1, :key2)
end
end
OR
def object_params
@params.permit(objects: [:key1, :key2])
end
It's getting weird...
def object_params
params.require(:objects).map do |object|
object.permit(:key1, :key2)
end
end
OR
def object_params
params.permit(objects: [:key1, :key2])
end
[
{
"key1" => "one_one",
"key2" => "one_two"
},
{
"key1" => "two_one",
"key2" => "two_two"
}
]
OR
{
"objects" => [
{
"key1" => "one_one",
"key2" => "one_two"
},
{
"key1" => "two_one",
"key2" => "two_two"
}
]
}
We can do that.
params =
{
object:
{
key1: "one",
key2: "two",
nested_object_attributes:
{
nested_attr_one: "nested_one",
nested_attr_two: "nested_two"
}
}
}
def object_params
params.require(:object)
.permit(:key1, :key2,
nested_object_params: [ :nested_attr_one, :nested_attr_two, :_destroy ])
end
Things can get messier.
params =
{
objects:
[{
key1: "one_one",
key2: "one_two",
nested_object_attributes:
[{
nested_attr_one: "nested_one",
nested_attr_two: "nested_two"
},
{
nested_attr_one: "nested_one2",
nested_attr_two: "nested_two2"
}]
},
{
key1: "two_one",
key2: "two_two",
nested_object_attributes:
[{
nested_attr_one: "nested_one3",
nested_attr_two: "nested_two3"
}]
}]
}
def object_params
@params.require(:objects).map do |object|
object.permit(:key1, :key2,
nested_object_attributes: [:nested_attr_one, :nested_attr_two, :_destroy])
end
end
[
[0] {
"key1" => "one",
"key2" => "two",
"nested_object_attributes" => [
[0] {
"nested_attr_one" => "nested_one",
"nested_attr_two" => "nested_two"
},
[1] {
"nested_attr_one" => "nested_one2",
"nested_attr_two" => "nested_two2"
}
]
},
[1] {
"key1" => "two_one",
"key2" => "two_two",
"nested_object_attributes" => [
[0] {
"nested_attr_one" => "nested_one3",
"nested_attr_two" => "nested_two3"
}
]
}
]
A whole lot messier...
params =
{
objects:
[{
key1: "one_one",
key2: "one_two",
nested_objects:
[{
nested_attr_one: "nested_one",
nested_attr_two: "nested_two"
},
{
nested_attr_one: "other_nested_one",
nested_attr_two: "other_nested_two"
}]
},
{
key1: "two_one",
key2: "two_two",
nested_objects:
[{
nested_attr_one: "lone_nested_one",
nested_attr_two: "lone_nested_two"
}]
}]
}
buckle up
def object_params
@params.require(:objects).map do |object|
nested_attributes = object.extract!(:nested_objects)
object.permit(:key1, :key2)
.merge(nested_object_attributes: nested_object_params(nested_attributes))
end
end
def nested_object_params(nested_attributes)
attributes.require(:nested_objects).map do |nested_object|
nested_object.permit(:nested_attr_one, :nested_attr_two, :_destroy)
end
end
I promise this works, but I'm not showing my work here.
Enjoy this kitten instead.
You think this is funny?
params =
{
objects:
[{
key1: "one",
key2: "two",
nested_objects:
[]
},
{
key1: "two_one",
key2: "two_two",
nested_objects:
[{
nested_attr_one: "lone_nested_one",
nested_attr_two: "lone_nested_two"
}]
},
{
key1: "three_one",
key2: "three_two",
nested_objects: nil
}]
}
just...
why?
def object_params
@params.require(:objects).map do |object|
nested_attributes = object.extract!(:nested_objects)
object.permit(:key1, :key2)
.merge(nested_object_attributes: nested_object_params(nested_attributes))
end
end
def nested_object_params(nested_attributes)
(attributes || []).map do|nested_object|
nested_object.permit(:nested_attr_one, :nested_attr_two)
end
end
def object_params
@params.require(:objects).permit!
end