Rails 4 - Parámetros Fuertes - Objetos Anidados

Tengo una pregunta bastante simple. Pero haven't encontrado una solución hasta ahora.

Así que aquí's la cadena JSON que envío al servidor:

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

Usando el nuevo método de permiso, I've got:

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

Esto no arroja errores, pero la entrada de base de datos creada contiene null en lugar del valor groundtruth.

Si acabo de establecer

params.require(:measurement).permit!

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

He encontrado soluciones, como permitir arrays, pero ni un solo ejemplo usando objetos anidados. Esto debe ser posible de alguna manera, ya que debe ser un caso de uso bastante común. Entonces, ¿cómo funciona?

Solución

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

Actualizar como sugiere @RafaelOliveira

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

Por otro lado si quieres anidar varios objetos entonces lo envuelves dentro de un hash... así

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


En realidad, Rails tiene bastante buena documentación al respecto: http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit.

Para más información, puedes consultar la implementación de permit y strong_parameters: https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/strong_parameters.rb#L246-L247

Comentarios (4)

Esta sugerencia me resultó útil en mi caso:

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

Mira este link del comentario de Xavier's en github.

Este enfoque incluye en la lista blanca todo el objeto params[:measurement][:groundtruth].

Usando los atributos de las preguntas originales:

  def product_params
    params.require(:measurement).permit(:name, :groundtruth).tap do |whitelisted|
      whitelisted[:groundtruth] = params[:measurement][:groundtruth]
    end
  end
Comentarios (4)

Permitir un objeto anidado:

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