#ruby-on-rails #ruby
#ruby-on-rails #ruby
Вопрос:
У меня есть модель пользователя, которая выглядит следующим образом
class User
ROLES = {
"Admin" => 1,
"Manager" => 2,
"Officer" => 3
}
def admin?
role == 1
end
def manager?
role == 2
end
def officer?
role == 3
end
end
где role
находится столбец в users
таблице, и мне было интересно, могу ли я использовать общий метод для построения 3 методов проверки ролей из ROLES
хэша?
Редактировать
итак, похоже, это ответ
class User
ROLES = {
"Admin" => 1,
"Manager" => 2,
"Officer" => 3
}
# methods used to identify whether a user is a specific role
ROLES.each { |k, v| define_method("#{k.downcase}?") { role == v } }
end
Комментарии:
1.
ROLES
не используется каким-либо полезным образом в вашем коде. Как вы хотите, чтобы это было задействовано?2. роль def? current_user.role заканчивается?
3. @sawa ..
ROLES
в основном действует как виртуальная таблицаroles
. Я использую его в представлениях, чтобы найти роль по значению столбцаrole
(1, 2 или 3), а также заполнить выпадающий список для роли в представлении добавления / редактирования. Здесь я хочу, чтобы он сопоставил имя метода со значением роли (1, 2, 3).4. @mikhail.. Я использую эти методы, чтобы проверить, является ли пользователь администратором, менеджером или должностным лицом
5. @mikhail
def role? current_user.role end
нарушает соглашение ruby, возвращая число или строку вместо логического значения.
Ответ №1:
Я не полностью уверен в ваших намерениях, но, может быть, вот так?
class User
%w[admin manager officer].each_with_index{|m, i| define_method("#{m}?"){role == i 1}}
end
или, используя ROLES
,
class User
ROLES.each{|m, i| define_method("#{m.downcase}?"){role == i}}
end
Ответ №2:
Я думаю, есть пара вариантов.
Во-первых, вы могли бы добавить реализацию method_missing, чтобы проверить, является ли метод одним из имен вашей роли. Что-то вроде:
def method_missing?(sym, *args)
if args.empty? amp;amp; ROLES.any? { |r| r.downcase "?" == sym.to_s }
# No additional arguments and the symbol for the method called
# matches a role name
role == ROLES[sym.to_s.chomp('?')] # Check the value
else
super
end
end
В качестве альтернативы вы могли бы настроить методы из хэша ваших ролей:
class User
ROLES = { ... }
ROLES.each_pair do |r, n|
class_eval "def #{r.downcase}?; role == #{n}; end"
end
end
Ответ №3:
Возможно, вы могли бы сделать это несколькими различными способами, вопрос в том, как вы хотите, чтобы это вело себя, и где вы хотите простоты использования / гибкости?
Если я пойму, что вы пытаетесь сделать, что-то вроде этого может помочь
def to_methods(roles_hash)
roles_hash.each_pair do |key, value|
class_eval {
"def #{key}?
role == #{value}
end"
}
end
end
Это создаст для вас методы для каждой роли. Это то, что вы хотели сделать?
Комментарии:
1. это именно то, чего я хочу.. В принципе, я мог бы добавить больше ролей к хэшу ролей, и метод будет сгенерирован автоматически.
Ответ №4:
Я полагаю, вы могли бы сделать что-то подобное, но я думаю, что ваш способ читается лучше…
(ROLES = {
"Admin" => 1,
"Manager" => 2,
"Officer" => 3,
}).each { |k, v| define_method(k.downcase '?') { role == v }}