Ошибка запрещенных атрибутов в Rails 4 при возникновении ситуации, когда вы использовали attr_accessible в более ранних версиях Rails
После недавнего обновления до Rails 4 обновление атрибутов с использованием кода, похожего на приведенный ниже, не работает, я получаю сообщение об ошибке ActiveModel::ForbiddenAttributes
:
@user.update_attributes(params[:user], :as => :admin)
Где пользователь имеет следующую строку attr_accessible в модели:
attr_accessible :role_ids, :as =>admin
# or any attribute other than :role_ids contained within :user
Как вы решаете ту же задачу в Rails 4?
Ответы
Ответ 1
В Rails 4 теперь есть функции из встроенного по умолчанию гема strong_parameters.
Больше не нужно совершать вызовы :as => :admin
, и вам не нужны attr_accessible :user_attribute, :as => admin
в вашей модели. Причина этого заключается в том, что по умолчанию приложения rails теперь имеют "безопасность" для каждого атрибута в моделях. Вы должны permit
атрибут, к permit
вы хотите получить доступ/изменить.
Все, что вам нужно сделать сейчас, это permit
вызова во время update_attributes
:
@user.update_attributes(params[:user], permit[:user_attribute])
или, если быть более точным:
@user.update_attributes(params[:user].permit(:role_ids))
Эта единственная строка, однако, позволяет любому пользователю изменять permit
роль. Не забудьте разрешить доступ к этому действию только администратору или любой другой желаемой роли через другой фильтр, такой как:
authorize! :update, @user, :message => 'Not authorized as an administrator.'
, , который будет работать, если вы используете Devise и CanCan для аутентификации и авторизации.
Ответ 2
Если вы создаете новый сайт Rails 4, вы заметите, что созданные контроллеры теперь включают частный метод, который вы используете для получения ваших дезинфицированных параметров. Это приятная идиома, и выглядит примерно так:
private
def user_params
params.require(:user).permit(:username, :email, :password)
end
Старый способ разрешить массовое присвоение - использовать что-то вроде:
attr_accessible :username, :email, :password
в вашей модели, чтобы отметить определенные параметры как доступные.
Обновление
Для обновления у вас есть несколько вариантов. Лучшим решением было бы реорганизовать ваши контроллеры с помощью метода params. Это может быть больше работы, чем сейчас у вас есть время.
Защищенный атрибут gem
Альтернативой может быть использование драгоценного камня protected_attributes, который восстанавливает метод attr_accessible. Это делает несколько более плавный путь обновления одним основным предупреждением.
Основная оговорка
В Rails 3 любая модель без доступа attr_accessible допускала все атрибуты.
В Rails 4 с драгоценным камнем protected_attributes это поведение отменяется. Любая модель без вызова attr_accessible имеет все атрибуты. Теперь вы должны объявить attr_accessible на всех ваших моделях. Это означает, что если вы не используете attr_accessible, вам нужно добавить это ко всем вашим моделям, что может быть такой же работой, как создание метода params.
https://github.com/rails/protected_attributes
Ответ 3
Эта проблема также может быть вызвана камнем Канкана
Просто добавьте в application_controller.rb
before_filter do
resource = controller_name.singularize.to_sym
method = "#{resource}_params"
params[resource] &&= send(method) if respond_to?(method, true)
end
Работает без каких-либо дополнительных модификаций кода
получил это отсюда: https://github.com/ryanb/cancan/issues/835#issuecomment-18663815
Ответ 4
Не забудьте добавить новый метод user_params к действию контроллера:
def create
@user = User.new(user_params)
@user.save
redirect_to 'wherever'
end
Ответ 5
def create
@user = User.create(user_params)
....
end
def update
@user = User.find(params[:id])
if @user.update_attributes(blog_params)
redirect_to home_path, notice: "Your profile has been successfully updated."
else
render action: "edit"
end
end
private
def user_params
params.require(:user).permit(:name, :age, :others)
end