2010-12-29 13 views
8

Estoy creando una aplicación de administración de inventario con cuatro tipos de usuarios diferentes: administrador, empleado, fabricante, transportista. Todavía no he empezado todavía la codificación, pero esto es lo que estoy pensando .. Fabricantes y transportadores están relacionados con has_many: a través de muchos-a-muchos relación con los productos de la siguiente manera:Múltiples funciones de usuario en Ruby on Rails

class Manufacturer < ActiveRecord::Base 
has_many :products 
has_many :transporters, :through => :products 
end 

class Product < ActiveRecord::Base 
belongs_to :manufacturer 
belongs_to :transporter 
end 

class Transporter < ActiveRecord::Base 
has_many :products 
has_many :manufacturers, :through => :products 
end 

Todos los cuatro tipos de usuarios se haya ser capaz de iniciar sesión, pero tendrán diferentes permisos y vistas, etc. No creo que pueda ponerlos en la misma tabla (Usuarios), sin embargo, porque tendrán diferentes requisitos, es decir: los proveedores y fabricantes deben tener una dirección de facturación e información de contacto (a través de validaciones), pero los administradores y los empleados no deberían tener estos campos.

Si es posible, me gustaría tener una sola pantalla de inicio de sesión en lugar de 4 pantallas diferentes.

No estoy pidiendo el código exacto para construir esto, pero estoy teniendo problemas para determinar la mejor manera de hacerlo realidad. Cualquier idea sería muy apreciada, ¡gracias!

Respuesta

5

Su enfoque básico parece razonable. Te aconsejaría que hacer una clase base del usuario y el uso de ITS para tipos específicos de usuarios, por ejemplo:

class User < ActiveRecord::Base 
end 

class Manufacturer < User 
has_many :products 
has_many :transporters, :through => :products 
end 

... etc. De esta forma, si alguna vez existe la necesidad de agregar múltiples tipos de usuarios en una relación, independientemente del tipo, tiene una tabla para describir a los usuarios en general. Este es un enfoque bastante común.

Dependiendo de la cantidad de acceso que tendrán los diferentes usuarios al sistema, es posible que desee consultar una gema de Role Management como Declarative Authorization.

+0

¡Gracias por la ayuda! ¿Cómo se configurarían las tablas de la base de datos para esto, con una clase base de usuario y STI para tipos de usuarios específicos? Soy realmente nuevo en los rieles :) – aguynamedloren

+0

Solo tendrá una tabla de 'usuarios' en el db. La herencia de tabla única/STI utiliza un campo 'tipo' en una tabla base (en este caso 'usuarios') para distinguir entre subtipos de la clase base. Necesita agregar este campo en una migración. Entonces todos los atributos para todos los subtipos de la clase base se mantendrán en la tabla de usuarios, aunque muchos de ellos no serán utilizados por instancias/filas específicas. Este es el equilibrio utilizando el patrón STI: puede tener una cantidad de campos nulos para los atributos no utilizados, dependiendo de cuántos atributos específicos de subtipo haya. –

1

Le sugiero que haga un modelo de usuario, modelo de dirección, modelo de ContactInfo, etc. NO debe tener ese tipo de campos en el modelo de usuario. Normaliza la base de datos. Tener un FK en cada una de esas otras clases para User.id.

Si tienes que mantenerlos separados, y luego normalizar los inicios de sesión y que sea polimórfica para hacer referencia a su propietario (fabricante, empleado, etc.)

+0

Weeeelll ... tal vez. Tener una tabla de direcciones está ciertamente normalizado, pero en el mundo real muchas veces es exagerado, y de hecho la mayoría de las veces los fanáticos de la normalización incluso admiten que algo así como una dirección, que en la mayoría de los casos equivale a nada más que un campo varchar - no necesita ser normalizado en su propia tabla con toda la sobrecarga que incurre. ¿Realmente desea un SQL join hit para cada consulta de los usuarios? No muy eficiente para una operación tan simple. Depende mucho del dominio, y si las direcciones son realmente complejas y reutilizables, etc. –

+0

@Dave Sims: estoy completamente, respetuosamente en desacuerdo. En el mundo de hoy, necesitamos tanta información como sea posible. La normalización (especialmente con direcciones) permite una expansión futura: podemos permitir que un usuario tenga múltiples direcciones (hogar y trabajo, por ejemplo). Y, ya sea que SELECT * devuelva 10 columnas o JOIN devuelva 10 columnas, no importa (como que la sobrecarga es literalmente insignificante incluso para conjuntos de datos increíblemente grandes). Además, SIEMPRE no mostrará una dirección con un usuario, entonces, ¿por qué lo tendría en la tabla de usuarios? Es un objeto separado – sethvargo

+0

@Dave Sims - (cont.). Lo veo de esta manera. TENGO un primer nombre, TENGO un apellido. TENGO también una dirección. NO TENGO una dirección_line_1 y address_line_2, zip ..., una dirección TIENE una dirección_line_1, 2..zip, etc.Para mí, es más sensato tener estas cosas separadas. ¿Puedes tener un usuario sin una dirección? ¿REALMENTE quiere restringir el acceso a su sitio si alguien no tiene hogar? Estoy exagerado, pero creo que verás por qué la normalización es importante. – sethvargo

4

Para sistemas de múltiples usuarios, en general las formas preferidas son: uso del modelo de rol o STI. Si sus usuarios pueden tener múltiples funciones al mismo tiempo, como ser un solo usuario Fabricante y transportista, entonces el sistema base de Roles sería una buena solución. Si el rol de los usuarios es fijo, entonces creo que deberías ir con STI.