2009-05-29 8 views
8

Attualmente sto scrivendo qualche applicazione web intranet in cui le persone possono inviare richieste di amministratore per l'aggiunta di risorse diverse. L'esempio richieste sarebbero:Alternative all'uso del polimorfismo in Ruby on Rails

  • installare programmi, in questo utente caso selezionerà quale programma si vuole installare
  • aumento delle quote, in questo utente caso sarà basta inserire la quantità di spazio su disco di cui ha bisogno, o forse lo farà seleziona le quantità predefinite - 1 GB, 10 GB ecc ...
  • crea un nuovo alias email, in questo caso l'utente digiterà semplicemente l'alias.
  • ...

stavo pensando di avere un solo UserRequests modello con il riferimento al mittente e due attributi opzionali si sarebbe REFERENCE_ID che refefrence ad altre tabelle (per esempio, il Programma che lui vuole installato) e un altro sarebbe utilizzato per campi di tipo libero come alias o quota di posta elettronica.

Quindi il mio problema è che in base al tipo di richiesta il modello dovrebbe contenere alternativamente:

  • riferimento ad altra tabella
  • dati interi
  • dati stringa

Sulla base il tipo di richiesta che deve essere eseguita l'azione specificata - probabilmente l'alias email potrebbe essere aggiunto dai binari ma l'applicazione sul computer degli utenti verrà installata a mano.

Qualcuno ha avuto un problema simile? Pensi che usare il polimorfismo per questo genere di cose sia una buona idea? Hai qualche suggerimento su come organizzare i dati nelle tabelle?

risposta

8

Eredità tabella singola! In questo modo puoi avere ogni tipo di richiesta con convalide personalizzate, pur avendo tutte le richieste attive nella stessa tabella.

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 

E, naturalmente, alias il tuo string_data e integer_data-email o roba del genere per rendere il vostro altro codice ha un po 'più di significato. Lascia che la modella sia la piccola scatola nera che nasconde tutto.

+0

Questo è esattamente quello che stavo cercando e il tuo post ha illuminato la mia mente un po '. Grazie. –

+0

Ian ha ragione, STI è perfetto per la tua richiesta qui. Per un esempio di quando il polimorfismo sarebbe utile in questo caso, sarebbe se tu avessi sia un utente che ha_molte richieste, sia un programma che ha richieste_molte.Quindi potrebbero entrambi avere molte richieste grazie al polimorfismo, e le richieste possono ancora essere STI quanto vogliono – Houen

2

Vorrei utilizzare le associazioni polimorfiche, che consentono a un modello di appartenere a più di un altro modello utilizzando un'unica associazione. Qualcosa di simile a questo:

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 
  • Come sempre, Ryan Bates ha un ottimo Railscast sull'argomento.
+0

Questo è interessante ma in questo caso preferirei evitare di creare un tavolo/modello per ogni tipo di richiesta. Grazie per aver segnalato anche le guide. –