1

Я использую перечисление в моей модели определяется как например:Рубин на Rails получить следующее перечисление от значения перечисления текущей модели

enum role: [:member, :content_creator, :moderator, :admin] 

Я хотел простой способ получить следующую роль от текущей роли пользователя, так что я пришел с этим:

def self.next_role(user) 
    begin 
    User.roles.drop(User.roles[user.role] + 1).to_enum.next 
    rescue StopIteration 
    nil 
    end 
end 

по мнению, я бы, вероятно, добавить на этот следующий метод цепи: [...].first.humanize.titleize.

Я только немного обеспокоен моим решением здесь, но в основном хотел узнать, был ли улучшенный (читай: более встроенный) способ получить то, что мне нужно? Я знаю, что есть только четыре перечисления, и я признаю, что начал свою реализацию с if ... elsif ... etc.. Другими словами, я считаю себя более опытным в Rails, чем с Ruby. Может кто-то уточнить, как это сделать?

+0

ли это ручная упаковка? Что такое «next» для ': admin'? – tadman

+0

Стрелять. Отличный вопрос. Что вы думаете о «ноль» в качестве кандидата? Я хотел бы, чтобы этот метод сообщил, что после ': admin' ничего не происходит. –

+0

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

ответ

2

User.roles это просто ActiveSupport::HashWithIndifferentAccess, который выглядит как:

{ 'member' => 0, 
    'content_creator' => 1, 
    'moderator' => 2, 
    'admin' => 3 } 

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

Возвращает последующую роль в виде строки, ноль, если текущая роль: администратор

def next_role 
    User.roles.key(User.roles[role] + 1) 
end 

Вы можете позвонить (рубин 2.3, необходимые для оператора &. безопасной навигации)

user.next_role&.humanize 
+0

o_0 (мне это нравится). Мне очень нравится ваше решение. –

+0

Неправильно ли беспокоиться о referencin g 'User.roles' дважды? И я согласен с вами в том, что это должен быть метод экземпляра, поскольку я всегда прошу следующего перечисления ссылаться на текущего пользователя. Но я думал, что это должен быть метод класса, поскольку вся коллекция ролей на самом деле не является проблемой конкретного пользователя, но тем более концепция пользователя в целом. Вы согласны? –

+1

По моему опыту доступ к хэшу enum не относится к производительности, конечно, не в поддержке генерации представления. Я думаю, что бит о «всегда спрашивает ... в отношении ... пользователя» - это то, что выскакивает на меня, говоря: это должен быть метод экземпляра. Очевидно, он работает в любом случае. Прагматично метод экземпляра приводит к меньшему количеству символов для ввода для вызывающий :) –

0

Как это захватить вас? Хорошо, так что это не более «встроено». Но я подумал, что это было совсем другое решение от вашего решения (которое было довольно умно), чтобы бросить в микс, по крайней мере, предложить некоторые различные элементы для потенциальной интеграции.

def self.next_role(user) 
    next_role = user.role.to_i + 1 
    next_role == self.roles.length ? nil : self.roles.invert[next_role] 
    end 
+0

Мне тоже нравится ваше решение! Он определенно уходит от обращения к 'User.roles' более одного раза, что на самом деле является моей самой большой проблемой. Я продолжу обдумывать это ... –

+0

вы также вам не понадобится. Сначала в начале цепочки в вашем представлении – matt721

+0

Я думаю, что 'user.role' вернет строку, имя переименования, затем' .to_i' затем превратит это в '0'. –