Рейки 4 - Сильні параметри - Вкладені об'єкти


144

У мене досить просте запитання. Але поки не знайшли рішення.

Отже ось рядок JSON, який я надсилаю на сервер:

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

Використовуючи новий метод дозволу, я отримав:

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

Це не nullпризводить до помилок, але створений запис бази даних містить замість значення groundtruth.

Якщо я просто встановив:

params.require(:measurement).permit!

Все врятується, як очікувалося, але, звичайно, це вбиває безпеку, забезпечену сильними параметрами.

Я знайшов рішення, як дозволити масиви, але не єдиний приклад з використанням вкладених об'єктів. Це повинно бути можливо якось, оскільки це має бути досить поширеним випадком використання. Отже, як це працює?



1
@vinodadhikary Це було правильно ... Я думаю, що ОП заплутаний. Як би це не звучало, коли ви хочете дозволити вкладені атрибути, ви вказуєте атрибути вкладеного об'єкта в масиві. З іншого боку, якщо ви хочете вкласти декілька об'єктів, тоді ви загортаєте їх у хеш… див. Api.rubyonrails.org/classes/ActionController/… та github.com/rails/rails/blob/master/actionpack/lib/…
j03w

@ j03w, Дякую за посилання на джерело. Це вже зрозуміло. Ви повинні додати відповідь для цього висновку, оскільки я думаю, що це допоможе багатьом іншим людям.
vee

Відповіді:


181

Як би це не звучало, коли ви хочете дозволити вкладені атрибути, ви вказуєте атрибути вкладеного об'єкта в масиві. У вашому випадку це було б

Оновлення, як запропонував @RafaelOliveira

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

З іншого боку, якщо ви хочете вкласти декілька об'єктів, тоді ви загортаєте їх у хеш… як це

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


Насправді рейки мають досить гарну документацію щодо цього: http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit

Для подальшого роз'яснення ви можете ознайомитись із реалізацією permitта strong_parametersсамою собою: https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/strong_parameters.rb#L246-L247


5
обидва випадки однакові у цій відповіді, насправді просто фігурні дужки навколо {: groundtruth => [...]}; Це хеш, але інтерпретатор може визначити, де починається і закінчується хеш без явних фігурних дужок.
говоритьcodecode

Вкладені масиви атрибутів не дозволяють вкладені атрибути. Вкладені атрибути та attr_accessor вказані в моїй програмі як "Недозволені параметри". Ще шукаю безпечне рішення.
Катажина

У випадку декількох вкладених об'єктів ви також повинні дозволити ідентифікатору для цього працювати. Більше інформації тут: stackoverflow.com/questions/18308714/…
Fabrice Carrega

1
Це дозволяє лише ОДИН набір вкладених атрибутів. У випадку від одного до багатьох це не вдасться.
AKWF

23

Я вважаю цю пропозицію корисною у своєму випадку:

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

Перевірте це посилання коментаря Xavier на github.

Такий підхід дорівнює спискам усього об'єкта params [: measurement] [: groundtruth].

Використання оригінальних атрибутів питань:

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

4
Лише бічна примітка. Це все ще відображатиметься в журналі як недозволені параметри, але модель все одно їх прийме.
Вестон Гангер

5
Не впевнений у Rails 4, але в моєму проекті Rails 5 я повинен закликати permit!бути дозволеним до списку, інакше він залишається недозволеним після його натискання. У цьому випадку це було бparams[:measurement][:groundtruth].permit!
nayiaw

@nayiaw я також отримую невідповідне повідомлення, але додавання permit!підвищує цей NoMethodError (undefined method дозвіл на помилку ! ' для # <масив: 0x007f80cb71ea00>): `
wuliwong

permit!Метод @wuliwong недоступний у Array. Ви повинні будете мати доступ до відповідного примірника класу , щоб мати доступ до permit!(це було в той час , так що я забув ім'я класу , але це що - щось на зразок ActionController::Parametersзасноване на цій сторінці ).
nayiaw

8

Дозвіл вкладеного об'єкта:

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

0

Якщо це Rails 5, через нове позначення хеш: params.permit(:name, groundtruth: [:type, coordinates:[]])буде добре працювати.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.