Альтернатива массовому назначению для HABTM - PullRequest
0 голосов
/ 20 марта 2011

У меня похожая ситуация с этим вопросом , который уже был опубликован.Корактор спросил:

Я использую простую модель для авторизации пользователя с двумя пользователями ActiveRecords, а пользователь роли и роль имеют отношение HABTM друг к другу.,,Ручное назначение ролей с помощью @ user.roles или @ user.role_ids работает, но не "волшебство" внутри User # new или User # update_attributes.

Олег предложил

attr_accessible :role_ids

быть добавленным к пользовательской модели.Это позволило бы операторам массового присваивания обновлять роли.Однако он предостерег от использования этого подхода из-за проблем безопасности.

У меня есть дополнительный вопрос к ответу Олега -

В этой ситуации есть рекомендуемый метод обновления ролей без использования массовых-assignment?

Кроме того, предполагая, что

  1. вы аутентифицируете пользователей,
  2. разрешает администраторам только пользователей CRUD, помещая before_filter в users_controller,

Массовое присвоение role_ids по-прежнему актуально?

1 Ответ

2 голосов
/ 20 марта 2011

Массовое назначение - это функция Rails, предназначенная для использования меньшего количества кода для обновления модели, подобной этой

Model.create(params[:model])
@model.update_parameters(params[:model])

вместо

@model.field1 = params[:model][:field1]
@model.field2 = params[:model][:field2]
...
@model.save

Но с этой функцией возникает риск обновления значений, которые мы не намерены. Например, если мы хотим, чтобы только field1, field2 и field3 обновлялись пользователем, и вы используете update_parameters для массового назначения, существует риск обновления field4, если один из них передает model[user][field4]=some_value либо из url, либо любым другим пути. Если мы явно присваиваем поля в коде, у нас нет этого риска. Но тогда нам нужно будет установить значения для каждого поля (где бы мы ни обновлялись или создавались), что не очень продуктивно.

Итак, для использования функции массового назначения у нас есть 2 варианта. Сначала attr_protected

attr_protected :field4

Это защитит field4 от сохранения от массового присвоения от params [: model], даже если оно содержит field4. Для сохранения field4 мы должны явно вызвать установщик для field4 в код (@model.field4 =). Но проблема с attr_protected заключается в том, что Rails может предоставлять некоторые другие атрибуты, которые мы можем не знать для массового назначения. Например, если мы определим

has_many :model2s

в Model.rb Rails автоматически предоставит метод model2_ids=, к которому можно получить доступ посредством массового присваивания (если мы дадим model[model2_ids]= в URL-адресе, он создаст ассоциации, вообще не предназначенные). Таким образом, существует вероятность пропустить подобные атрибуты при использовании attr_protected.

Итак, рекомендуемый метод - использовать attr_accessible

attr_accessible :field1, :field2, :field3

Это сделает эти поля открытыми для массового назначения, а все остальные атрибуты в модели недоступны для массового назначения. Таким образом, рекомендуемый способ состоит в том, чтобы те атрибуты, которые мы предоставляем в форме для пользователей, редактировали как attr_accessible, и все остальные параметры будут защищены. Но, при использовании этого вы должны убедиться, что вы включили все атрибуты, которые вам нужны для редактирования, как attr_accessible.

В вашем случае, поскольку вы хотите, чтобы пользователь отредактировал role_ids, и вы предоставляете доступ к CRUD только для пользователей с правами администратора, я думаю, что вы можете использовать attr_accessible :role_ids. Альтернативой было бы назначить role_ids явно как .role_ids = params[:user][:role_ids]. Вы должны использовать это, если у вас есть другая форма, где вы не хотите, чтобы пользователь редактировал role_ids.

...