Szyny 4 - Silne parametry - Obiekty zagnieżdżone

144

Mam dość proste pytanie. Ale do tej pory nie znalazłem rozwiązania.

Oto ciąg JSON, który wysyłam na serwer:

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

Korzystając z nowej metody zezwolenia, otrzymałem:

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

Nie nullpowoduje to żadnych błędów, ale utworzony wpis bazy danych zawiera zamiast wartości groundtruth.

Jeśli tylko ustawię:

params.require(:measurement).permit!

Wszystko jest zapisywane zgodnie z oczekiwaniami, ale oczywiście zabija to bezpieczeństwo zapewniane przez mocne parametry.

Znalazłem rozwiązania, jak zezwolić na tablice, ale ani jednego przykładu z użyciem obiektów zagnieżdżonych. To musi być jakoś możliwe, ponieważ powinien to być dość powszechny przypadek użycia. Więc jak to działa?

Benjamin M.
źródło
zajrzyj do tego stackoverflow.com/questions/14483963/…
Rajarshi Das
1
@vinodadhikary To było poprawne… Myślę, że OP jest zdezorientowany. Choć brzmi to dziwnie, kiedy chcesz zezwolić na zagnieżdżone atrybuty, określasz atrybuty zagnieżdżonego obiektu w tablicy. Z drugiej strony, jeśli chcesz zagnieżdżać wiele obiektów, zawijasz je wewnątrz hasha… patrz api.rubyonrails.org/classes/ActionController/ ... i github.com/rails/rails/blob/master/actionpack/lib/ ...
j03w
@ j03w, Dzięki za link do źródła. Teraz jest jasne. Powinieneś dodać tutaj odpowiedź na to odkrycie, ponieważ myślę, że pomoże to wielu innym ludziom.
vee

Odpowiedzi:

181

Choć brzmi to dziwnie, kiedy chcesz zezwolić na zagnieżdżone atrybuty, określasz atrybuty zagnieżdżonego obiektu w tablicy. W twoim przypadku tak by było

Zaktualizuj zgodnie z sugestią @RafaelOliveira

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

Z drugiej strony, jeśli chcesz zagnieżdżać wiele obiektów, umieszczasz je wewnątrz hasha… w ten sposób

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


Railsy mają całkiem niezłą dokumentację na ten temat: http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit

W celu uzyskania dalszych wyjaśnień, można spojrzeć na realizację permiti strong_parameterssama: https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/strong_parameters.rb#L246-L247

j03w
źródło
5
oba przypadki są takie same w tej odpowiedzi, właściwie po prostu nawiasy klamrowe są opcjonalne wokół {: groundtruth => [...]}; Jest to skrót, ale interpreter jest w stanie określić, gdzie zaczyna się i kończy skrót bez wyraźnych nawiasów klamrowych.
speakcode
Zagnieżdżone tablice atrybutów nie pozwalają na zagnieżdżone atrybuty. Zagnieżdżone atrybuty i attr_accessor są wymienione w mojej aplikacji jako „Niedozwolone parametry”. Wciąż szukam bezpiecznego rozwiązania.
Katarzyna
W przypadku wielu obiektów zagnieżdżonych, powinieneś także zezwolić na id, aby to zadziałało. Więcej informacji tutaj: stackoverflow.com/questions/18308714/…
Fabrice Carrega
1
Pozwala to tylko na JEDEN zestaw zagnieżdżonych atrybutów. To nie zadziała w przypadku jednego do wielu.
AKWF
23

Ta sugestia okazała się przydatna w moim przypadku:

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

Sprawdź ten link do komentarza Xaviera na github.

To podejście tworzy białą listę całego obiektu params [: measurement] [: groundtruth].

Używając oryginalnych atrybutów pytań:

  def product_params
    params.require(:measurement).permit(:name, :groundtruth).tap do |whitelisted|
      whitelisted[:groundtruth] = params[:measurement][:groundtruth]
    end
  end
M.ElSaka
źródło
4
Na marginesie, to nadal będzie wyświetlane w dzienniku jako niedozwolone parametry, ale model i tak je zaakceptuje.
Weston Ganger
5
Nie jestem pewien co do Rails 4, ale w moim projekcie Rails 5 muszę zadzwonić, permit!aby znaleźć się na białej liście, bo inaczej pozostało niedozwolone po dotknięciu. W tym przypadku byłoby toparams[:measurement][:groundtruth].permit!
nayiaw
@nayiaw Otrzymuję również niedozwoloną wiadomość, ale dodanie permit!zwiększa NoMethodError (undefined method zezwolenie na błąd ! ' for # <Array: 0x007f80cb71ea00>): `
wuliwong
permit!Metoda @wuliwong nie jest dostępna w Array. Będziesz musiał mieć dostęp do odpowiedniej instancji klasy, aby mieć dostęp do permit!(minęło trochę czasu, więc zapomniałem nazwy klasy, ale jest ona ActionController::Parametersoparta na tej stronie ).
nayiaw
8

Zezwalanie na zagnieżdżony obiekt:

params.permit( {:school => [:id , :name]}, 
               {:student => [:id, 
                            :name, 
                            :address, 
                            :city]},
                {:records => [:marks, :subject]})
Codiee
źródło
0

Jeśli jest to Rails 5, z powodu nowej notacji hash: params.permit(:name, groundtruth: [:type, coordinates:[]])będzie działać dobrze.

user8164115
źródło