Rieles 4 - Parámetros fuertes - Objetos anidados

144

Tengo una pregunta bastante simple. Pero no he encontrado una solución hasta ahora.

Así que aquí está la cadena JSON que envío al servidor:

{
  "name" : "abc",
  "groundtruth" : {
    "type" : "Point",
    "coordinates" : [ 2.4, 6 ]
  }
}

Usando el nuevo método de permiso, tengo:

params.require(:measurement).permit(:name, :groundtruth)

Esto no arroja errores, pero la entrada de la base de datos creada contiene en nulllugar del valor de verdad.

Si acabo de configurar:

params.require(:measurement).permit!

Todo se guarda como se esperaba, pero por supuesto, esto mata la seguridad proporcionada por parámetros fuertes.

He encontrado soluciones, cómo permitir matrices, pero no un solo ejemplo con objetos anidados. Esto debe ser posible de alguna manera, ya que debería ser un caso de uso bastante común. ¿Entonces, cómo funciona?

Benjamin M
fuente
echa un vistazo a este stackoverflow.com/questions/14483963/…
Rajarshi Das
1
@vinodadhikary Fue correcto ... Creo que el OP está confundido. Por extraño que parezca cuando desea permitir atributos anidados, debe especificar los atributos del objeto anidado dentro de la matriz. Por otro lado, si desea anidar varios objetos, entonces lo envuelve dentro de un hash ... vea api.rubyonrails.org/classes/ActionController/… y github.com/rails/rails/blob/master/actionpack/lib/…
j03w
@ j03w, gracias por el enlace a la fuente. Está claro ahora. Debería agregar una respuesta aquí para este hallazgo, ya que creo que ayudará a muchas otras personas.
vee

Respuestas:

181

Por extraño que parezca cuando desea permitir atributos anidados, debe especificar los atributos del objeto anidado dentro de una matriz. En tu caso sería

Actualice según lo sugerido por @RafaelOliveira

params.require(:measurement)
      .permit(:name, :groundtruth => [:type, :coordinates => []])

Por otro lado, si quieres anidar varios objetos, entonces lo envuelves dentro de un hash ... como este

params.require(:foo).permit(:bar, {:baz => [:x, :y]})


Los rieles en realidad tienen bastante buena documentación sobre esto: http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit

Para mayor claridad, usted podría mirar a la implementación de permity strong_parametersen sí: https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/strong_parameters.rb#L246-L247

j03w
fuente
55
ambos casos son iguales en esta respuesta, en realidad, es solo que las llaves son opcionales alrededor de {: groundtruth => [...]}; Es un hash, pero el intérprete puede determinar dónde comienza y termina el hash sin llaves explícitas.
voz
Las matrices anidadas de atributos no permiten atributos anidados. Los atributos anidados y attr_accessor se enumeran en mi aplicación como "Parámetros no permitidos". Todavía estoy buscando una solución segura.
Katarzyna
En el caso de varios objetos anidados, también debe permitir que la identificación funcione. Más información aquí: stackoverflow.com/questions/18308714/…
Fabrice Carrega
1
Esto solo permite UN conjunto de atributos anidados. Esto no funcionará en el caso de uno a muchos.
AKWF
23

Encontré esta sugerencia útil en mi caso:

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

Mira este enlace del comentario de Xavier en github.

Este enfoque incluye en la lista blanca el objeto de parámetros completos [: medición] [: verdad].

Usando los atributos de preguntas originales:

  def product_params
    params.require(:measurement).permit(:name, :groundtruth).tap do |whitelisted|
      whitelisted[:groundtruth] = params[:measurement][:groundtruth]
    end
  end
M.ElSaka
fuente
44
Solo una nota al margen, Esto todavía se mostrará en el registro como parámetros no permitidos, pero el modelo los aceptará de todos modos.
Weston Ganger el
55
No estoy seguro de Rails 4, pero en mi proyecto Rails 5 tengo que llamar permit!para incluirlo en la lista blanca o, de lo contrario, permanecerá sin permiso después de tocarlo. En este caso seríaparams[:measurement][:groundtruth].permit!
nayiaw
@nayiaw también recibo el mensaje no permitido, ¡pero agregar permit!aumenta este NoMethodError (undefined method permiso de error ! ' para # <Array: 0x007f80cb71ea00>): `
wuliwong
El permit!método @wuliwong no está disponible en Array. Deberá tener acceso a la instancia de clase respectiva para tener acceso permit!(ha pasado un tiempo, así que he olvidado el nombre de la clase, pero es algo así como ActionController::Parametersbasado en esta página ).
nayiaw
8

Permitir un objeto anidado:

params.permit( {:school => [:id , :name]}, 
               {:student => [:id, 
                            :name, 
                            :address, 
                            :city]},
                {:records => [:marks, :subject]})
Codiee
fuente
0

Si es Rails 5, debido a la nueva notación hash: params.permit(:name, groundtruth: [:type, coordinates:[]])funcionará bien.

usuario8164115
fuente