Не удается массово назначить защищенные атрибуты - PullRequest
4 голосов
/ 16 марта 2012

Мой features файл выглядит так:

Given there are the following users:
    | email              | password | admin |
    | admin@ticketee.com | password | true  |

И моя user модель не объявляет атрибут admin как attr_accessible для предотвращения массового назначения.Соответственно, я внес изменения в файл user_steps.rb для решения этой проблемы.

Given /^there are the following users:$/ do |table|
  table.hashes.each do |attributes|
   unconfirmed = attributes.delete("unconfirmed") == "true"
   @user = User.create!(attributes)
   @user.update_attribute("admin", attributes["admin"] == "true")
   @user.confirm! unless unconfirmed
 end
end

Теперь это должно работать в соответствии с книгой - Rails3 в действии.Я также проверил код на их онлайн-репо .Запуск этого с огурцом дает следующую ошибку:

Can't mass-assign protected attributes: admin (ActiveModel::MassAssignmentSecurity::Error)
  ./features/step_definitions/user_steps.rb:4:in `block (2 levels) in <top (required)>'
  ./features/step_definitions/user_steps.rb:2:in `each'
  ./features/step_definitions/user_steps.rb:2:in `/^there are the following users:$/'
  features/creating_projects.feature:7:in `Given there are the following users:'

Любая помощь будет принята с благодарностью.Я действительно не могу понять, что здесь не так.

Большое спасибо!

Ответы [ 5 ]

8 голосов
/ 16 марта 2012

В пользовательской модели добавьте:

attr_accessible :admin

Обновление:

Атрибут admin может быть назначен массово, и любой хакер может легко установить его, отправивэто с параметрами.

3 голосов
/ 14 ноября 2012

Я получил это, изменив определение шага:

   Given /^there are the following users:$/ do |table|
      table.hashes.each do |attributes|
      unconfirmed = attributes.delete("unconfirmed") == "true"
      admin = attributes.delete("admin") == "true"
      @user = User.create!(attributes)
      @user.admin = admin
      @user.confirm! unless unconfirmed
      end
    end
1 голос
/ 10 августа 2012

Предполагая, что это основано на "Rails 3 в действии", пример кода на самом деле имеет ту же проблему.Из журнала:

WARNING: Can't mass-assign protected attributes: admin
(0.1ms)  SELECT 1 FROM "users" WHERE "users"."email" = 'sfcarroll2@gmail.com' LIMIT 1
User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."confirmation_token" =     'f9zDB57RDXsziBdGpmnW' LIMIT 1

Однако в файле config / environment / development.rb значение mass_assignment_sanitizer не установлено.По умолчанию новый проект rails 3.2 установит это.Если он закомментирован, код будет выполнен.Значение по умолчанию:

config.active_record.mass_assignment_sanitizer = :strict

Затем образец кода устанавливает атрибут с помощью закрытого метода set_admin .Это хорошая практика кодирования?Я не уверен, но это работает.

Кстати, это отличная книга.

1 голос
/ 16 марта 2012

Почему бы просто не использовать @user.admin = attributes["admin"] == "true"?

Вам нужно будет избавиться от значения admin из хеша атрибутов - чтобы полный код был

admin = attributes.delete("admin") == "true"
...
@user = User.new(attributes)
@user.admin = admin
@user.save!

Я изменил пользователя.Создайте!в User.new + @ user.save, потому что вы устанавливаете атрибут, но не сохраняете модель после.Если @ user.confirm!Сохраняя модель, вы не увидите никаких ошибок, но не стоит полагаться на побочные эффекты от других подобных методов.Лучше быть явным.

0 голосов
/ 11 августа 2013

Я думаю, что самый простой способ сделать это:

Given /^there are the following users:$/ do |table|
  table.hashes.each do |attributes|
    unconfirmed = attributes.delete("unconfirmed") == "true" # this will delete the attribute unconfirmed from first
    # scenario on the signing_in.feature but it's also make a variable unconfirmed true (2 in one action)

    admin = attributes.delete("admin") == "true"

    @user = User.create!(attributes)

    @user.update_attribute("admin", "true") if admin

    # with the user and password, it will create the user as admin.
    @user.confirm! unless unconfirmed  # this is work for the second scenario check rails 3 in action page 152.
  end
end

Таким образом, вы удалите атрибут admin из атрибутов, чтобы вы могли создать нового пользователя; без ошибки массового назначения атрибутов. Но для «теста» мы сохраняем переменную admin, чтобы назначить атрибут user.admin, если admin был true. Дело в том, что вы не сделаете администратора доступным в модели User для защиты своего сайта от взлома, но мы делаем это только для того, чтобы пройти наш тест. На вашем сайте вы должны внедрить безопасный способ обновления пользователя после его создания.

...