2009-05-29 37 views
8

Actualmente estoy escribiendo alguna aplicación web de intranet en la que las personas pueden enviar solicitudes a los administradores para agregar recursos diferentes. Las solicitudes ejemplo sería:Alternativas para usar polimorfismo en Ruby on Rails

  • la instalación de programas, en este caso, el usuario seleccionará el programa que él quiere instalar
  • aumento de cuota, en este caso, el usuario se acaba de entrar en la cantidad de espacio en disco que necesita o tal vez lo hará seleccione las cantidades predefinidas - 1GB, 10GB, etc ...
  • cree un nuevo alias de correo electrónico, en este caso el usuario simplemente tecleará el alias.
  • ...

Estaba pensando en tener un solo modelo UserRequests con la referencia al remitente y dos atributos opcionales se estaría REFERENCE_ID que refefrence a otras tablas (por ejemplo, el Programa que él quiere instalar) y otro sería usado para campos de tipo como alias o cuotas de correo electrónico.

Así que mi problema es que en función del tipo de la solicitud el modelo debe contener:

  • referencia a otra tabla
  • datos enteros
  • datos de cadena

Basado en el tipo de la solicitud que se debe tomar la acción dada - probablemente se haya agregado el alias de correo electrónico de los rieles, pero la aplicación en la computadora de los usuarios se instalará a mano.

¿Alguien tuvo un problema similar? ¿Crees que usar polimorfismo para este tipo de cosas es una buena idea? ¿Tiene alguna sugerencia sobre cómo organizar los datos en las tablas?

Respuesta

8

Single Table Herencia! De esta forma, puede hacer que cada tipo de solicitud tenga validaciones personalizadas, al tiempo que mantiene todas las solicitudes en vivo en la misma tabla.

class CreateUserRequests < ActiveRecord::Migration 
    def self.up 
    create_table :user_requests do |t| 
     t.string :string_data, :type 
     t.integer :user_id, :integer_data 
     t.timestamps 
    end 
    end 
    def self.down 
    drop_table :user_requests 
    end 
end 


class UserRequest < ActiveRecord::Base 
    belongs_to :user 
end 

class EmailAliasRequest < UserRequest 
    validates_presence_of :string_data 
    validates_format_of :string_data, :with => EMAIL_REGEX 
end 

class ProgramInstallRequest < UserRequest 
    belongs_to :program, :class_name => "Program", :foreign_key => "integer_data" 
    validates_presence_of :integer_data 
end 

class QuotaIncreaseRequest < UserRequest 
    validates_presence_of :string_data 
    validates_inclusion_of :string_data, :in => %w(1GB 5GB 10GB 15GB) 
end 

Y, por supuesto, alias el string_data y integer_data a email o lo que sea para que su otro código tiene un poco más de sentido. Deje que el modelo sea la pequeña caja negra que lo esconde todo.

+0

Esto es exactamente lo que estaba buscando y tu publicación iluminó mi mente un poco. Gracias. –

+0

Ian tiene razón, STI es perfecto para su solicitud aquí. Para un ejemplo de cuándo el polimorfismo sería útil en este caso, eso sería si tuviera tanto un usuario que tiene muchas solicitudes como un programa que tiene muchas solicitudes.Entonces ambos podrían tener muchas solicitudes gracias al polimorfismo, y las solicitudes aún pueden ser ITS tanto como lo deseen – Houen

2

Usaría asociaciones polimórficas, que permiten que un modelo pertenezca a más de otro modelo utilizando una sola asociación. Algo como esto:

class AdminRequest < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :requestable, :polymorphic => true 
end 

class EmailAlias < ActiveRecord::Base 
    has_many :admin_requests, :as => :requestable 
end 

class ProgramInstall < ActiveRecord::Base 
    has_many :admin_requests, :as => :requestable 
end 

class QuotaIncrease < ActiveRecord::Base 
    has_many :admin_requests, :as => :requestable 
end 
  • Como siempre, Ryan Bates tiene una excelente Railscast sobre el tema.
+0

Esto es interesante, pero en este caso preferiría evitar crear una tabla/modelo para cada tipo de solicitud. Gracias por señalar los ferrocarriles también. –