Rails - как объявить attr_accessible для нескольких ролей без дублирования

Есть ли способ объявить attr_accessible для нескольких ролей без тонны дублирования?

Если у меня есть несколько пользовательских ролей, и каждой роли разрешено редактировать другой поднабор атрибутов, вот как выглядит мое объявление attr_accessible:

attr_accessible :first_name, :last_name, :active, :as => :admin
attr_accessible :first_name, :last_name, :as => :manager
attr_accessible :first_name, :last_name, :as => :guest

Я хотел бы либо

  • A) определить массив доступных атрибутов, которые могут разные роли или
  • B) определяют массив ролей, чем могут обращаться к тем же атрибуты

Возможно ли это?

Ответы

Ответ 1

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

ROLES = [:admin, :manager, :support, :user, :guest]
ACTIVE_ROLES = [:admin, :support]
ROLES.each do |role|
   fields = [:first_name, :last_name]
   fields += [:active] if ACTIVE_ROLES.include?(role)
   attr_accessible *fields, :as => role
end

Ответ 2

Я просто потратил много времени, пытаясь найти лучший способ сделать это. Казалось странным, что рельсовые люди ожидали, что вы продублируете целую кучу кода!

После некоторого поиска в источнике рельсов, вы можете просто передать массив для назначения атрибутов сразу нескольким ролям (: по умолчанию это роль Active Record по умолчанию)

attr_accessible :name, :email, :as => [ :default, :admin ]    
attr_accessible :featured, :as => :admin

В вашей модели нет грязных рубиновых массивов!

Ответ 3

Вы попробовали что-то вроде:

COMMON_FIELDS = [:first_name, :last_name]

attr_accessible COMMON_FIELDS | [:active, :as => :admin]
attr_accessible COMMON_FIELDS | [:as => :manager]
attr_accessible COMMON_FIELDS | [:as => :guest]

Еще один возможный способ (непроверенный):

attr_accessible :first_name, :last_name
ADMIN_ACCESSIBLE   = [:active]
MANAGER_ACCESSIBLE = []
GUEST_ACCESSIBLE   = []

protected

def mass_assignment_authorizer
  if role == :all
    self.class.protected_attributes
  else
    super + (eval("#{role}_accessible".upcase) || [])
  end
end