ruby-on-rails - how - rails enum migration
Rails Enumerated Types o Alternativas (6)
Estoy aprendiendo Ruby on Rails y tengo una tabla de roles de usuario (Propietario, Administrador y Usuario). Habrá lugares en el código donde necesito verificar el rol del usuario y mostrar diferentes opciones. ¿Alguien sabe cómo hacer esto sin recurrir a números mágicos u otros métodos desagradables?
En las aplicaciones web ASP.Net en las que he trabajado, he visto esto hecho mediante el uso de tipos enumerados:
public enum UserRole { Owner = 1, Admin = 2, User = 3 }
// ...
if (user.Role == UserRole.Admin)
// Show special admin options
Cada función diferente en la base de datos se refleja como un tipo enumerado con un valor establecido en la ID de esa función en la base de datos. Esa no parece una solución muy buena porque depende del conocimiento de la base de datos que puede cambiar. Incluso si es la forma correcta de manejar algo como esto, no sé cómo usar tipos enumerados en rieles.
Apreciaría cualquier idea sobre este asunto.
¿Podría la funcionalidad agregada en Rails 4.1 ser lo que estás buscando?
http://coherence.io/blog/2013/12/17/whats-new-in-rails-4-1.html
Copia de la publicación del blog:
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
Empezando a aprender Rails (de C #), y tenía exactamente la misma pregunta. Parece que Rails realmente no tiene enumeraciones porque la filosofía es diferente. Usaría toneladas de enumeraciones para tratar de organizar todos los detalles en un proyecto de C #, pero quizás dado que Rails maneja tanto para ti, no son tan importantes. No es realmente una respuesta, solo una observación.
Este parece ser un muy buen caso para usar mi gema classy_enum . En esencia, le permite definir un conjunto fijo de opciones, donde cada una es una clase con comportamiento y propiedades específicas. Ayuda a reducir toda la lógica condicional que tiende a dispersarse a lo largo de la aplicación.
Por ejemplo, si estás haciendo cosas como esta:
class User < ActiveRecord::Base
def options
if user.is_admin?
[...admin options...]
else
[...non admin options...]
end
end
end
Luego llamando como: user.options
otro lugar ...
classy_enum le permite mover esa lógica a un lugar separado y tener la misma funcionalidad sin lógica condicional:
class User < ActiveRecord::Base
classy_enum_attr :role
delegate :options, :to => :role
end
El README tiene un ejemplo de trabajo y describe la gema en detalle.
Hay un complemento enum en rubyforge, por lo que haces:
t.column :severity, :enum, :limit => [:low, :medium, :high, :critical]
Es bastante feo usar :limit
atributo de :limit
para pasar parámetros, pero es una forma más estandarizada.
Para instalar solo hazlo:
script/plugin install svn://rubyforge.org/var/svn/enum-column/plugins/enum-column
actualmente funciona con Rails 2.2.2 o posterior. Enlace de Rubyforge: www.rubyforge.org/projects/enum-column/
Prefiero usar el complemento de autorización acertadamente llamado para situaciones como esta.
Esto te permitirá
permit "role"
restringir el acceso a los roles, y
permit? "role"
simplemente para probar el acceso. Ambos delegan en User#has_role?(role)
.
No sienta que tiene que usar su implementación ObjectRoles
. Puede usar los roles Hardwired
y luego implementar su propio método User#has_role?(role)
para usar su esquema existente.
Ruby en sí no tiene un tipo enumerado, pero este sitio muestra un método http://www.rubyfleebie.com/enumerations-and-ruby/
Puede hacer algo como esto en su modelo de Usuario:
#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