Tengo una aplicación de rieles que tiene tres tipos diferentes de usuarios y los necesito a todos para compartir la misma información de perfil común. Sin embargo, cada usuario diferente también tiene atributos únicos. No estoy seguro de cómo separar los diferentes campos.Registro activo de Rails: cómo modelar un escenario de usuario/perfil
- de administración (sitio de ancho de administración)
- propietario (de una tienda/etc)
- miembro (como un miembro de una cooperativa)
estoy usando legado para autenticación y cancan para autorización. Por lo tanto, tengo un modelo de usuario con un conjunto de funciones que se pueden aplicar al usuario. Esta clase se ve esto:
class User < ActiveRecord::Base
# ... devise stuff omitted for brevity ...
# Roles association
has_many :assignments
has_many :roles, :through => :assignments
# For cancan: https://github.com/ryanb/cancan/wiki/Separate-Role-Model
def has_role?(role_sym)
roles.any? { |r| r.name.underscore.to_sym == role_sym }
end
end
Cada usuario tiene un perfil que incluye:
- Primera & Apellido
- Info dirección (ciudad/st/zip/etc)
- Teléfono
No quiero contaminar el modelo de usuario con esta información, así que lo estoy lanzando en un modelo de perfil. Esta parte es bastante simple. Esto convierte el modelo de usuario en algo como esto:
class User < ActiveRecord::Base
# ... devise stuff omitted for brevity ...
# ... cancan stuff omitted for brevity ...
has_one :profile
end
Los campos adicionales es donde tengo algunos sentimientos de inquietud acerca de cómo modelar son ...
Si un usuario es un administrador, tendrán campos únicos, tales como:
- admin_field_a: cadena
- admin_field_b: cadena
- etc
Si un usuario es un propietario que tendrán campos únicos ...
- stripe_api_key: cadena
- stripe_test_api_key: cadena
- stripe_account_number: cadena
- has_one: tienda # AR refence a otro modelo que el administrador y el miembro no tienen.
Si un usuario es miembro van a tener unos campos adicionales tales como:
- stripe_account_number: cadena
- belongs_to: tienda # la tienda que son un miembro de
- has_many: nota
...
y un modelo tienda contendrá un has_many sobre los miembros por lo que trabajamos los miembros de la tienda.
El problema está en los campos adicionales. ¿Los configuro como clases diferentes? Ponerlos en una diferente He Actualmente intentado un par de modos distintos de configurar esto:
Una forma es configurar el modelo de usuario como root agregada
class User < ActiveRecord::Base
# ...
# Roles association
has_many :assignments
has_many :roles, :through => :assignments
# Profile and other object types
has_one :profile
has_one :admin
has_one :owner
has_one :member
# ...
end
La ventaja de este enfoque es la El modelo de usuario es la raíz y puede acceder a todo. La caída es que si el usuario es un "propietario", entonces las referencias de "administrador" y "miembro" serán nulas (y el cartesiano de las otras posibilidades: administrador pero no propietario o miembro, etc.).
La otra opción que estaba pensando era que cada tipo de heredar el usuario a partir del modelo del usuario como tal:
class User < ActiveRecord::Base
# ... other code removed for brevity
has_one :profile
end
class Admin < User
# admin fields
end
class Owner < User
# owner fields
end
class Member < User
# member fields
end
problema con esto es que estoy contaminando el objeto Usuario con todo tipo de de Nil en la tabla donde un tipo no necesita los valores de otro tipo/etc. Solo parece un poco desordenado, pero no estoy seguro.
La otra opción era crear cada tipo de cuenta como la raíz, pero tienen al usuario como un objeto secundario, como se muestra a continuación.
class Admin
has_one :user
# admin fields go here.
end
class Owner
has_one :user
# owner fields go here.
end
class Member
has_one :user
# member fields go here.
end
El problema con lo anterior es que no estoy seguro de cómo cargar la clase apropiada una vez el usuario inicie sesión. Voy a tener su user_id y voy a ser capaz de decir qué papel son (debido a la asociación de roles en el modelo de usuario), pero no estoy seguro de cómo pasar del usuario UP a un objeto raíz. ¿Métodos? ¿otro?
Conclusión tengo unas pocas maneras diferentes de hacer esto, pero no estoy seguro de lo que el enfoque de "rieles" correctas es. ¿Cuál es la forma correcta de modelar esto en rieles AR? (MySQL backend). Si no hay un enfoque "correcto", cuál es el mejor de los anteriores (también estoy abierto a otras ideas).
Gracias!
Esta es la respuesta que yo Estoy marcando como "esto funcionó" porque cuando lo probé funcionó bastante bien. Gracias por la respuesta muy bien pensada y detallada de Jeffrey. :) Sin embargo, después de consultar con Michael Hartl (RailsTutorial.org) sobre algún MVP (mínimo producto viable), he decidido incluir todos los datos de perfil en el modelo de Usuario para simplificar las interacciones con el modelo. Si el MVP resulta exitoso y es rentable, entonces puedo arreglar esto más tarde. –