Перечислимые типы или альтернативы Rails - PullRequest
26 голосов
/ 26 мая 2009

Я только изучаю ruby ​​на рельсах, и у меня есть таблица пользовательских ролей (Владелец, Администратор и Пользователь). В коде будут места, где мне нужно будет проверить роль пользователя и показать разные варианты. Кто-нибудь знает, как это сделать, не прибегая к магическим числам или другим уродливым методам?

В веб-приложениях ASP.Net, над которыми я работал, я видел, как это делается с помощью перечисляемых типов:

public enum UserRole { Owner = 1, Admin = 2, User = 3 }

// ...

if (user.Role == UserRole.Admin)
    // Show special admin options

Каждая отдельная роль в базе данных отображается как перечислимый тип со значением, установленным для идентификатора этой роли в базе данных. Это не очень хорошее решение, потому что оно зависит от знания базы данных, которая может измениться. Даже если это правильный способ обработки чего-то подобного, я не знаю, как использовать перечислимые типы в рельсах.

Буду признателен за понимание этого вопроса.

Ответы [ 6 ]

26 голосов
/ 26 мая 2009

У самого Ruby нет перечислимого типа, но на этом сайте показан метод http://www.rubyfleebie.com/enumerations-and-ruby/

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

#constants
OWNER = 1
ADMIN = 2
USER = 3

def is_owner?
  self.role == OWNER
end

def is_admin?
  self.role == ADMIN
end

def is_user?
  self.role == USER
end
12 голосов
/ 26 декабря 2013

Может ли функциональность, добавленная в Rails 4.1, быть тем, что вы ищете?

http://coherence.io/blog/2013/12/17/whats-new-in-rails-4-1.html

Копировать из блога:

class Bug < ActiveRecord::Base
  # Relevant schema change looks like this:
  #
  # create_table :bugs do |t|
  #   t.column :status, :integer, default: 0 # defaults to the first value (i.e. :unverified)
  # end

  enum status: [ :unverified, :confirmed, :assigned, :in_progress, :resolved, :rejected, :reopened ]

...

Bug.resolved           # => a scope to find all resolved bugs
bug.resolved?          # => check if bug has the status resolved
bug.resolved!          # => update! the bug with status set to resolved
bug.status             # => a string describing the bug's status
bug.status = :resolved # => set the bug's status to resolved
4 голосов
/ 24 марта 2011

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

Например, если вы делаете такие вещи:

class User < ActiveRecord::Base
  def options
    if user.is_admin?
      [...admin options...]
    else
      [...non admin options...]
    end
  end
end

Тогда звоните как: user.options куда-то еще ...

classy_enum позволяет вам переместить эту логику в отдельное место и иметь ту же функциональность без условной логики:

class User < ActiveRecord::Base
  classy_enum_attr :role

  delegate :options, :to => :role
end

README имеет рабочий пример и подробно описывает драгоценный камень.

2 голосов
/ 11 июня 2011

Я только начал изучать Rails (из C #), и у меня возник точно такой же вопрос. Кажется, что в Rails действительно нет перечислений, потому что философия другая. Я бы использовал тонны перечислений, чтобы попытаться упорядочить все детали в проекте C #, но, возможно, поскольку Rails так много для вас обрабатывает, они не так важны. Это не совсем ответ, просто наблюдение.

2 голосов
/ 26 мая 2009

Я предпочитаю использовать плагин с точно названным Authorization для таких ситуаций.

Это позволит вам

permit "role" 

для ограничения доступа к ролям и

permit? "role"

чтобы просто проверить доступ. Оба эти делегата User#has_role?(role).

Не думайте, что вам нужно использовать их ObjectRoles реализацию. Вы можете использовать роли Hardwired, а затем реализовать свой собственный метод User#has_role?(role) для использования существующей схемы.

0 голосов
/ 09 июля 2010

На rubyforge есть enum плагин , поэтому вы делаете:

t.column :severity, :enum, :limit => [:low, :medium, :high, :critical]

Довольно уродливо использовать атрибут :limit для передачи параметров, но это более стандартизированный способ.

Для установки достаточно сделать:

script/plugin install svn://rubyforge.org/var/svn/enum-column/plugins/enum-column

В настоящее время он работает с Rails 2.2.2 или новее. Ссылка на Rubyforge: www.rubyforge.org/projects/enum-column/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...