Search code examples
ruby-on-railsrubyruby-on-rails-4enumerationenumerable

Ruby on Rails get next enum from current model's enum value


I'm using an enum in my model defined as such:

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

I wanted an easy way to get the next role from a user's current role, so I came up with this:

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

In the view, I'd likely add onto this the following method chain: [...].first.humanize.titleize.

I'm only somewhat concerned about my solution here, but mainly wanted to know if there was a better (read: more built-in) way to get what I'm after? I know there are only four enums there and I admit I started my implementation with if ... elsif ... etc.. In other words, I find myself more proficient in Rails than I do with Ruby itself. Can someone elaborate how one "should" do this?


Solution

  • User.roles is just an ActiveSupport::HashWithIndifferentAccess that looks like:

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

    Using that, this solution is pretty close to yours but without the exception handling. I would also be doing this as an instance method on User, not a class method.

    Returns the subsequent role as a String, nil if the current role is :admin

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

    You can then call (ruby 2.3 required for the &. safe navigation operator)

    user.next_role&.humanize