Rails 4 - Parâmetros Fortes - Objetos Aninhados


144

Eu tenho uma pergunta bem simples. Mas ainda não encontrei uma solução.

Então, aqui está a string JSON que eu envio ao servidor:

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

Usando o novo método de permissão, eu tenho:

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

Isso não gera erros, mas a entrada do banco de dados criada contém, em nullvez do valor de groundtruth.

Se eu apenas definir:

params.require(:measurement).permit!

Tudo é salvo como esperado, mas é claro que isso mata a segurança fornecida por parâmetros fortes.

Encontrei soluções, como permitir matrizes, mas não um único exemplo usando objetos aninhados. Isso deve ser possível de alguma forma, pois deve ser um caso de uso bastante comum. Então, como isso funciona?



1
@vinodadhikary Estava correto… acho que o OP está confuso. Por mais estranho que pareça quando você deseja permitir atributos aninhados, você especifica os atributos do objeto aninhado na matriz. Por outro lado, se você deseja aninhar vários objetos, envolva-o em um hash ... consulte api.rubyonrails.org/classes/ActionController/… e github.com/rails/rails/blob/master/actionpack/lib/…
j03w 26/08/13

@ j03w, Obrigado pelo link para a fonte. Está claro agora. Você deve adicionar uma resposta aqui para esse achado, pois acho que ajudará muitas outras pessoas.
vee

Respostas:


181

Por mais estranho que pareça quando você deseja permitir atributos aninhados, você especifica os atributos do objeto aninhado em uma matriz. No seu caso, seria

Atualizar como sugerido por @RafaelOliveira

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

Por outro lado, se você deseja aninhar vários objetos, envolva-o em um hash ... assim

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


Os Rails realmente têm uma documentação muito boa sobre isso: http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit

Para esclarecimentos adicionais, você pode examinar a implementação permite strong_parametersela própria: https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/strong_parameters.rb#L246-L247


5
os dois casos são os mesmos nesta resposta; na verdade, apenas os colchetes são opcionais em torno de {: groundtruth => [...]}; É um hash, mas o intérprete é capaz de determinar onde o hash começa e termina sem colchetes explícitos.
speakingcode

Matrizes aninhadas de atributos não permitem atributos aninhados. Atributos aninhados e attr_accessor estão listados no meu aplicativo como "Parâmetros não permitidos". Ainda à procura de uma solução segura.
Katarzyna

No caso de vários objetos aninhados, você também deve permitir que o ID funcione. Mais informações aqui: stackoverflow.com/questions/18308714/…
Fabrice Carrega

1
Isso permite apenas UM conjunto de atributos aninhados. Isso não funcionará no caso de um para muitos.
AKWF 10/0318

23

Achei esta sugestão útil no meu caso:

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

Verifique este link do comentário de Xavier no github.

Essa abordagem coloca na lista de permissões todo o objeto de parâmetros [: measure] [: groundtruth].

Usando os atributos de perguntas originais:

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

4
Apenas uma observação: Isso ainda será exibido no log como parâmetros não permitidos, mas o modelo os aceitará de qualquer maneira.
Weston Ganger

5
Não tenho certeza do Rails 4, mas no meu projeto do Rails 5 eu tenho que ligar permit!para estar na lista de permissões, caso contrário ele permanecerá não permitido depois de tocar nele. Neste caso, seriaparams[:measurement][:groundtruth].permit!
nayiaw

@nayiaw eu também recebo a mensagem não permitida, mas adicionar permit!aumenta essa NoMethodError (undefined method permissão de erro ! ' for # <Array: 0x007f80cb71ea00>): `
wuliwong

O permit!método @wuliwong não está disponível em Array. Você precisará ter acesso à respectiva instância de classe para ter acesso permit!(já faz algum tempo, esqueci o nome da classe, mas é algo ActionController::Parametersbaseado nesta página ).
Nayiaw 18/04

8

Permitindo um objeto aninhado:

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

0

Se for o Rails 5, por causa da nova notação de hash: params.permit(:name, groundtruth: [:type, coordinates:[]])funcionará bem.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.