Msgstr "ПРЕДУПРЕЖДЕНИЕ: Невозможно назначить защищенные атрибуты"

Я использовал методы RESTful для создания модели (на самом деле, я использую Devise gem, что делает это для меня), и я добавил в модель новые поля с именем first_name и last_name. Миграция прошла нормально. Я добавил attr_accessor: first_name,: last_name к модели и ожидал, что он просто сработает. Но когда я пытаюсь назначить новые экземпляры с помощью Doctor.create({: first_name = > "MyName" }) и т.д., Я получаю ошибки, заявляя, что не могу назначать защищенные атрибуты.

Я думал, что цель использования attr_accessor состояла в том, чтобы обойти защищенность полей модели. Можете ли вы помочь мне понять это сообщение?

Изменить: oh, и, кстати, записи также не создаются. Я думал, они должны быть, так как это всего лишь предупреждение, но они не находятся в базе данных.

Edit2: вот моя модель

class Doctor < User
  has_many :patients
  has_many :prescriptions, :through=> :patients

  validates_presence_of :invitations, :on => :create, :message => "can't be blank"

  attr_accessor :invitations
end

и схемы, которая не имеет first_name и last_name, потому что они созданы в таблице пользователей, которая является предком врачей. Я использовал одиночное наследование таблицы.

create_table :doctors do |t|
  t.integer :invitations

  t.timestamps
end

и это переход на изменение таблицы пользователей

add_column :users, :first_name, :string
add_column :users, :last_name, :string
add_column :users, :type, :string

EDIT: вот файл семени. Я не включаю метод truncate_db_table, но он работает.

%w{doctors patients}.each do |m|
  truncate_db_table(m)  
end  

Doctor.create(:invitations=>5, :email=>"[email protected]", :first_name=>"Name", :last_name=>"LastName")
Patient.create(:doctor_id=>1, :gender=>"male", :date_of_birth=>"1991-02-24")

Ответ 1

Не путайте attr_accessor с attr_accessible. Accessor встроен в Ruby и определяет метод getter - model_instance.foo # returns something - и метод setter - model_instance.foo = 'bar'.

Доступность определяется Rails и делает атрибут назначаемым для массовых величин (делает это противоположно attr_protected).

Если first_name - это поле в вашей таблице базы данных моделей, Rails уже определил геттеры и сеттеры для этого атрибута. Все, что вам нужно сделать, это добавить attr_accessible :first_name.

Ответ 2

Чтобы небезопасно взломать ваше приложение, совершенно непригодное для производственного режима:

Перейдите в /config/application.rb. Прокрутите вниз до конца, где вы найдете

{config.active_record.whitelist_attributes = true}

Установите это в ложь.

РЕДАКТИРОВАТЬ/кстати (после 4 месяцев интенсивной работы в рубине, включая 11-недельный семинар): DHH считает, что для новичков (его слова) "запуск и запуск" важнее, чем "очень безопасный".

ОБРАЩАЙТЕСЬ: Многие опытные разработчики рельсов очень страстно желают, чтобы вы этого не хотели.

ОБНОВЛЕНИЕ: 3 года спустя, еще один способ сделать это - опять же, небезопасно, но лучше, чем вышеупомянутое решение, вероятно, потому что вы должны сделать это для каждой модели

class ModelName < ActiveRecord::Base
  column_names.each do |col|
    attr_accessible col.to_sym
  end
  ...
end

Ответ 3

Не используйте attr_accessor здесь. ActiveRecord создает их автоматически на модели. Кроме того, ActiveRecord не создает запись, если генерируется ошибка проверки или массового присвоения.

EDIT: вам не нужна таблица врачей, вам нужна таблица пользователей с столбцом типа для обработки Rails Наследование отдельных таблиц. Приглашения будут отображаться в таблице пользователей. Ах, я вижу в вашем добавленном примере кода у вас есть тип для пользователей. Избавьтесь от таблицы врачей, переместите приглашения пользователям, и я думаю, вы должны быть в порядке. Также избавиться от attr_accessor. Не требуется.

Имейте в виду, что рельсы STI используют одну и ту же таблицу для всех классов и подклассов конкретной модели. Все ваши записи доктора будут строками в таблице пользователей с типом "доктор"

EDIT: Также вы уверены, что хотите проверить наличие приглашений на создание, а не обновления?

Ответ 4

Добавьте attr_accessible : variable1, variable2 в файл маршрута таблицы.

Ответ 5

Согласитесь с ответом @Robert Speicher. Но я настоятельно рекомендую вам использовать Сильный параметр вместо attr_accessible для защиты от массового присвоения.

Ура!

Ответ 6

Если вы хотите отключить защиту массовых назначений для отдельного вызова (но не в глобальном масштабе), можно использовать параметр :without_protection => true. Я считаю это полезным для миграций и других мест, где ключи/значения хеш-кода жестко запрограммированы или, как известно, безопасны.

Пример здесь (работает и в rails 3.2): https://apidock.com/rails/v3.1.0/ActiveRecord/Base/create/class