Rails 4 - Сильные Параметры - Вложенные объекты

144

У меня довольно простой вопрос. Но пока не нашли решения.

Итак, вот строка JSON, которую я отправляю на сервер:

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

Используя новый метод разрешения, я получил:

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

Это не вызывает ошибок, но созданная запись базы данных содержит nullвместо значения Groundtruth.

Если бы я только установил:

params.require(:measurement).permit!

Все сохраняется как ожидалось, но, конечно, это убивает безопасность, обеспечиваемую строгими параметрами.

Я нашел решения, как разрешить массивы, но не один пример использования вложенных объектов. Это должно быть как-то возможно, так как это должно быть довольно распространенным вариантом использования. Итак, как это работает?

Бенджамин М
источник
взгляните на этот stackoverflow.com/questions/14483963/…
Раджарши Дас
1
@vinodadhikary Это было правильно ... Я думаю, что ОП сбит с толку. Как бы странно это ни звучало, если вы хотите разрешить вложенные атрибуты, вы указываете атрибуты вложенного объекта в массиве. С другой стороны, если вы хотите вложить несколько объектов, вы заключаете их в хеш… см. Api.rubyonrails.org/classes/ActionController/… и github.com/rails/rails/blob/master/actionpack/lib/…
J03W
@ j03w, спасибо за ссылку на источник. Теперь понятно. Вы должны добавить ответ здесь для этого открытия, так как я думаю, что это поможет многим другим людям.
ви

Ответы:

181

Как бы странно это ни звучало, если вы хотите разрешить вложенные атрибуты, вы указываете атрибуты вложенного объекта в массиве. В вашем случае это было бы

Обновление в соответствии с предложением @RafaelOliveira

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

С другой стороны, если вы хотите вложить несколько объектов, вы заключаете их в хеш… вот так

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


Rails на самом деле имеет довольно хорошую документацию по этому вопросу: 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

j03w
источник
5
оба случая одинаковы в этом ответе, просто фигурные скобки необязательны для {: groundtruth => [...]}; Это хеш, но интерпретатор может определить, где хеш начинается и заканчивается без явных фигурных скобок.
говорящий
Вложенные массивы атрибутов не допускают вложенные атрибуты. Вложенные атрибуты и attr_accessor перечислены в моем приложении как «Недопустимые параметры». Все еще ищу безопасное решение.
Катаржина
В случае нескольких вложенных объектов, вы также должны разрешить идентификатор для этого работать. Более подробная информация здесь: stackoverflow.com/questions/18308714/…
Фабрис Каррега
1
Это разрешает только ОДИН набор вложенных атрибутов. Это не будет работать в случае один ко многим.
AKWF
23

Я нашел это предложение полезным в моем случае:

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

Проверьте эту ссылку комментария Ксавье на github.

Этот подход помещает в белый список весь объект params [: measure] [: groundtruth].

Используя оригинальные атрибуты вопросов:

  def product_params
    params.require(:measurement).permit(:name, :groundtruth).tap do |whitelisted|
      whitelisted[:groundtruth] = params[:measurement][:groundtruth]
    end
  end
M.ElSaka
источник
4
Просто примечание: это все равно будет отображаться в журнале как недопустимые параметры, но модель все равно примет их.
Уэстон Гангер
5
Не уверен насчет Rails 4, но в моем проекте Rails 5 мне нужно позвонить, permit!чтобы попасть в белый список, иначе он остался недопустимым после нажатия. В этом случае это будетparams[:measurement][:groundtruth].permit!
nayiaw
@nayiaw я также получаю недопустимое сообщение, но добавление permit!вызывает это NoMethodError (undefined method разрешение на ошибку ! ' для # <Array: 0x007f80cb71ea00>): `
wuliwong
permit!Метод @wuliwong недоступен в Array. Вам нужно будет иметь доступ к соответствующему экземпляру класса, чтобы иметь к permit!нему доступ (это было давно, поэтому я забыл имя класса, но это что-то вроде ActionController::Parametersоснованного на этой странице ).
nayiaw
8

Разрешение вложенного объекта:

params.permit( {:school => [:id , :name]}, 
               {:student => [:id, 
                            :name, 
                            :address, 
                            :city]},
                {:records => [:marks, :subject]})
Codiee
источник
0

Если это Rails 5, из-за новой хэш-записи: params.permit(:name, groundtruth: [:type, coordinates:[]])будет работать нормально.

user8164115
источник