Назначение защищенного атрибута в Rails
У меня есть поле на моей модели пользователя, которое защищено, потому что оно определяет уровень допуска. Поэтому он должен быть защищен и не может быть назначен по массе. Таким образом, хотя атрибуты по умолчанию защищены в 3.2, на самом деле это поведение, которое я хочу.
Однако на одном методе контроллера я хочу разрешить менеджеру назначать это поле, например, при создании пользователя или обновлении пользователя.
Как разрешить назначение этого атрибута для определенных действий контроллера?
Например, у меня есть мой контроллер:
# app/controllers/admin/users_controller.rb
def create
@user = User.new(params[:user])
# ...
end
Теперь, что я хотел бы сделать, это исключить clearance
от params[:user]
, но, похоже, он отфильтровывается, вызывается и возникает исключение еще до того, как эта строка достигнута (я попытался debugger
прямо перед этой строкой и даже закомментируйте ее, все равно возникло исключение).
Куда попадают защищенные атрибуты, если нет при вызове User#new
?
2 ответа
Способ Rails сделать это - назначить атрибуты без защиты или использовать роль администратора:
@user = User.new
@user.assign_attributes(params[:user], :without_protection => true)
@user.save
Тем не менее, я нашел это немного утомительным, поэтому я написал гем под названием sudo_attributes, который дает (на мой взгляд) лучший API:
@user = User.sudo_new(params[:user])
@user.save
Он имитирует все методы создания, создания и обновления Rails (new, build, create, create!, update_attributes и т. Д.).
В прошлом я предпочитал давать этой операции свой собственный метод, который устанавливает только это значение:
# app/controllers/admin/users_controller.rb
def full_clearance
User.find(params[:id]).update_attribute(:clearance, 'full')
end
def restricted_clearance
User.find(params[:id]).update_attribute(:clearance, 'restricted')
end
Теперь, посмотрев на путь Rails, о котором говорил Берлингтон, я бы предпочел использовать роли, чтобы дать конкретному действию доступ к атрибуту оформления:
# /app/models/user.rb
attr_accessible :attributes_accessible_by_default, ..., :clearance, :as => :manager
# app/controllers/admin/users_controller.rb
def create
@user = User.new(params[:user].merge(:as => :manager)
# ...
end
В этом случае даже возможно предоставить пользователю доступ на основе атрибута роли:
# app/controllers/admin/users_controller.rb
def create
@user = User.new(params[:user].merge(:as => current_user.role.to_sym)
# ...
end
но это может привести к возникновению ошибок снова.