Рельсы Перечисленные типы или альтернативы
Я просто изучаю ruby на рельсах, и у меня есть таблица ролей пользователей (Owner, Admin и User). В коде будут места, где мне нужно проверить роль пользователя и показать разные параметры. Кто-нибудь знает, как это сделать, не прибегая к магическим числам или другим уродливым методам?
В веб-приложениях ASP.Net, над которыми я работал, я видел это, используя перечисленные типы:
public enum UserRole { Owner = 1, Admin = 2, User = 3 }
// ...
if (user.Role == UserRole.Admin)
// Show special admin options
Каждая отдельная роль в базе данных отражается как перечислимый тип со значением, установленным для идентификатора этой роли в базе данных. Это не похоже на очень хорошее решение, потому что это зависит от знания базы данных, которая может измениться. Даже если это правильный способ справиться с чем-то подобным, я не знаю, как использовать перечисленные типы в рельсах.
Буду признателен за понимание этого вопроса.
Ответы
Ответ 1
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
Ответ 2
Может ли функциональность, добавленная в 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 status
bug.status = :resolved # => set the bug status to resolved
Ответ 3
Это похоже на действительно хороший пример использования classy_enum gem. Он по существу позволяет вам определить фиксированный набор параметров, где каждый из них является классом с поведением и свойствами, специфичными для него. Это помогает сократить всю условную логику, которая стремится рассеяться по всему приложению.
Например, если вы делаете такие вещи:
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 имеет рабочий пример и подробно описывает драгоценный камень.
Ответ 4
Я предпочитаю использовать подходящий Authorization плагин для подобных ситуаций.
Это позволит вам
permit "role"
чтобы ограничить доступ к ролям и
permit? "role"
просто проверить доступ. Оба этих делегата на User#has_role?(role)
.
Не чувствуйте, что вам нужно использовать их реализацию ObjectRoles
. Вы можете использовать роли Hardwired
, а затем реализовать собственный метод User#has_role?(role)
для использования вашей существующей схемы.
Ответ 5
Просто начал изучать Rails (с С#) и имел этот тот же самый вопрос. Кажется, что у Rails действительно нет перечислений, потому что философия отличается. Я бы использовал тонны перечислений, чтобы попытаться организовать все детали в проекте С#, но, возможно, с тех пор, как Rails справляется так много для вас, они не так важны. Это не ответ, просто наблюдение.
Ответ 6
Там есть enum plugin на rubyforge, чтобы вы это сделали:
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/