2009-05-29 8 views
8

J'écris actuellement une application web intranet où les gens peuvent soumettre aux admins des demandes d'ajout de ressources différentes. L'exemple des demandes seraient:Alternatives pour utiliser le polymorphisme dans Ruby on Rails

  • l'installation de programmes, dans ce cas l'utilisateur sélectionnera quel programme il veut installé
  • quota de plus en plus, dans ce cas l'utilisateur ne suffit d'entrer la quantité d'espace disque dont il a besoin ou peut-être qu'il sélectionnez les quantités prédéfinies - 1GB, 10GB etc ...
  • créer un nouvel alias email, dans ce cas, l'utilisateur tape simplement l'alias.
  • ...

Je pensais avoir juste un UserRequests modèle avec la référence à l'expéditeur et deux attributs facultatifs on serait REFERENCE_ID qui refefrence à d'autres tables (pour exemple le programme qu'il veut installé) et un autre serait utilisé pour les champs de type libre comme alias de messagerie ou quota.

Donc mon problème est que en fonction du type de la demande, le modèle doit contenir soit:

  • référence à autre table
  • données entières
  • données de chaîne

Basé sur le type de la requête l'action donnée devrait être prise - probablement l'alias de courrier électronique pourrait être ajouté des rails mais l'application sur l'ordinateur d'utilisateurs sera installée à la main.

Est-ce que quelqu'un a eu un problème similaire? Pensez-vous que l'utilisation du polymorphisme pour ce genre de choses est une bonne idée? Avez-vous des suggestions sur la façon d'organiser les données dans les tableaux?

Répondre

8

Héritage de table unique! De cette façon, vous pouvez faire en sorte que chaque type de requête ait des validations personnalisées, tout en ayant toutes les requêtes en ligne dans la même table.

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 

Et bien sûr, alias votre string_data et integer_data-email ou autres joyeusetés pour rendre votre autre code ont un peu plus de sens. Laissez le modèle être la petite boîte noire qui cache tout.

+0

C'est exactement ce que je cherchais et votre message m'a un peu éclairé. Merci. –

+0

Ian a raison, STI est parfait pour votre demande ici. Pour un exemple de quand le polymorphisme serait utile dans ce cas, ce serait si vous aviez à la fois un utilisateur qui a beaucoup de demandes, et un programme qui a beaucoup de demandes.Ensuite, ils pourraient tous deux avoir beaucoup de demandes grâce au polymorphisme, et les demandes peuvent toujours être STI autant qu'ils veulent – Houen

2

J'utiliserais des associations polymorphes, qui permettent à un modèle d'appartenir à plus d'un autre modèle en utilisant une seule association. Quelque chose comme ceci:

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 
  • Comme toujours, Ryan Bates a un excellent Railscast sur le sujet.
+0

Ceci est intéressant mais dans ce cas je préférerais éviter de créer une table/un modèle pour chaque type de requête. Merci d'avoir signalé les émissions de radio aussi. –