Ошибка запрещенных атрибутов в Rails 4 при возникновении ситуации, когда можно было бы использовать attr, доступный в более ранних версиях 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?
5 ответов:
Rails 4 теперь имеет функции изstrong_parameters gem, встроенных по умолчанию.
Больше не нужно делать вызовы
:as => :admin
, и вам не нуженattr_accessible :user_attribute, :as => admin
в вашей модели. Причина этого заключается в том, что по умолчанию приложения rails теперь имеют "безопасность" для каждого атрибута на моделях. Вы должныpermit
атрибут, к которому вы хотите получить доступ / изменить.Все, что вам нужно сделать сейчас, это позвонить
permit
во времяupdate_attributes
:@user.update_attributes(params[:user], permit[:user_attribute])
Или, если быть более точным:
@user.update_attributes(params[:user].permit(:role_ids))
Эта единственная строка, однако позволяет любому пользователю изменять роль
permit
ted. Вы должны помнить, что разрешать доступ к этому действию только администратору или любой другой желаемой роли через другой фильтр, такой как:authorize! :update, @user, :message => 'Not authorized as an administrator.'
. . . что будет работать, если вы используете Devise и CanCan для аутентификации и авторизации.
Если вы создадите новый сайт Rails 4, Вы заметите, что сгенерированные контроллеры теперь включают частный метод, который вы используете для получения ваших санированных параметров. Это хорошая идиома, и выглядит примерно так:
private def user_params params.require(:user).permit(:username, :email, :password) end
Старый способ разрешения массового назначения состоял в использовании чего-то вроде:
attr_accessible :username, :email, :password
На вашей модели, чтобы отметить определенные параметры как доступные.
Обновление
Для обновления у вас есть несколько вариантов. Вашим лучшим решением будет рефакторинг ваших контроллеров с помощью метода params. Это может быть больше работы, чем у вас сейчас есть времени.
Protected_attributes gem
Альтернативой может быть использование protected_attributes gem, который восстанавливает метод attr_accessible. Это делает путь обновления немного более плавным с одной важной оговоркой.
Главное Предостережение
В Rails 3 любая модель без вызова attr_accessible допускает все атрибуты.
В Rails 4 с protected_attributes gem это поведение меняется на противоположное. Любая модель без вызова attr_accessible имеет все атрибуты, ограниченные. Теперь вы должны объявить attr_accessible на всех ваших моделях. Это означает, что если вы не использовали attr_accessible, вам нужно будет добавить его ко всем вашим моделям, что может быть такой же работой, как просто создание метода params.
Эта проблема также может быть вызвана Cancan gem
Просто добавьте в 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
Не забудьте добавить новый метод user_params в действие контроллера:
def create @user = User.new(user_params) @user.save redirect_to 'wherever' end
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