2009-10-15 2 views
3

У меня есть большое приложение Rails, которое имеет 34 разных типа пользователей через одностраничное наследование. Когда приложение было первоначально спроектировано, предполагалось, что Пользователь будет иметь разные типы поведения, основанные на типе. Это предположение было неправильным, поэтому я ищу рефакторинг.Лучший способ обработки различных типов пользователей?

Вопрос в том, как бы вы реорганизовали пользовательский STI?

  • Добавить тонну логических атрибутов пользователя (то есть. User#is_employee?, User.is_contractor?)
  • Rename User#type к User#user_type и просто делать сопоставления строк на основе поля
  • Некоторые ужасны таблицы поиска решения
  • Что-то я 'm missing ...

Чтобы уточнить, пользователю требуется «тип» для причин ACL, но с STI они действительно просто пустые модели a и STI вызывает проблемы со спеканием, общей болью в заднице и т. д.

ответ

0

Все ли 34 модели пуста?

Если вы можете сделать:

self.inheritance_column = nil 

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

if @user.type == "Employee" 
    # do something 
end 
+0

Интересно и просто ... –

0

Это трудно ответить на этот вопрос, не зная, каким образом ваши «причины ACL» будут использовать тип, но ...

По моему опыту, я всегда был с User#user_type. Мне всегда казалось, что случаи были достаточно редки, чтобы это было хорошо. Хотя у меня было только несколько типов пользователей. Другой вариант (который может быть то, что вы намекая с вашей второй вариант) будет использовать method_missing для обработки сопоставления строк, и позволить ей вести себя, как вариант 1.

Например:

def method_missing(method, *args, &block) 
if(method.to_s.starts_with?('is_')) 
    self.user_type == method.to_s.gsub("is_", "").gsub("?", "") 
end 
end 

это вернет true для is_contractor?, если user_type является подрядчиком.

Обратите внимание, что предоставленный фрагмент не проверен и что прикованные gsub выглядят довольно ужасно. Я уверен, что это может быть написано как приятное небольшое регулярное выражение или каким-то другим умным способом.

3

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

Простая модель ACL: пользователь имеет много ролей, каждая роль имеет много разрешений. Набор разрешений для пользователя - это набор всех разрешений для всех ролей, к которым принадлежит пользователь.

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

@user.can_view_payroll_info_for?(@employee, 2.years.ago) ==> true 
@user.can_view_payroll_info_for?(@employee, Time.now) ==> false 

Большая часть времени, хотя, роль как высокое разрешение, как вам нужно получить:

@john.has_role(:content_author) ==> true 
@john.has_role(:moderator) ==> true 

@benny.has_role(:content_author) ==> true 
@benny.has_role(:moderator) ==> false 

@michael.has_role(:moderator) ==> true 
@michael.has_role(:content_author) ==> false 

Вы можете реализовать его так просто, как запятая (одобренные) строки в столбце «Роль» для пользователя или таблицы соединений, если вы хотите, чтобы роли были нормализованы.

Смежные вопросы