2009-10-11 16 views
6

Voglio gestire due tipi di impostazioni di configurazione globale:Qual è il modo migliore per memorizzare le impostazioni globali dell'applicazione in un'applicazione Rails?

  • impostazioni che possono essere modificate dall'utente, come se mail di notifica per determinati eventi vengono inviati o meno.
  • Impostazioni collegate a un'edizione di prodotto specifica, ad esempio la disattivazione di una funzione in una versione gratuita, disponibile solo nella versione commerciale.

Qual è il modo migliore per memorizzare queste impostazioni? Database, file di configurazione, hardcoded nell'origine, ...?

risposta

6

Per entrambi i casi di database. Utilizzerai le stesse strutture per più persone/prodotti, quindi ha senso. Inoltre ti permette di cambiare le cose senza riavviare il server.

L'ho gestito in questo modo in passato: Per le impostazioni specifiche per l'utente, ho creato un modello/tabella UserSettings, che ha un rapporto uno-a-uno con un utente. Il ragionamento per questo è che la maggior parte delle operazioni che coinvolgono gli utenti non richiedono che queste impostazioni vengano caricate, quindi sono incluse nei carichi utente dal database solo quando ne ho bisogno.

Quando faccio questo, di solito raggrupperò i nomi delle mie colonne, in modo che possa scrivere aiutanti che creano dinamicamente in base ai nomi. Ciò significa che non dovrò modificare le mie viste per incorporare nuove impostazioni a meno che non ne aggiunga una con uno schema di denominazione diverso.

Per le impostazioni specifiche di un prodotto, beh ciò dipende da come si stanno facendo le cose. E ci sono un paio di modi per interpretare la tua domanda.

Il modo in cui l'ho letto è che si desidera decidere a livello di prodotto. Quali impostazioni gli utenti possono ignorare o disabilitare le impostazioni di un utente. E possibilmente definire alcune impostazioni specifiche del prodotto.

Vorrei utilizzare un prodotto uno-a-molti per impostare la relazione. La tabella delle impostazioni sarebbe semplicistica (product_id, setting_name, setting_default_value, allow_user_change)

Questo fa un certo numero di cose. Ti consente di avere un elenco variabile di impostazioni per prodotti diversi (perfetto per il caso in cui stai offrendo molti prodotti diversi invece di vari livelli di accesso ai servizi). Permette anche di definire quali impostazioni un utente può/non può cambiare e fornire valori per quel tipo di prodotto. Questo può essere modificato da una vista amministratore senza riavviare l'applicazione. Inoltre, non è legato alle impostazioni dell'utente, al punto che se un utente non ha un'impostazione elencata in product_settings non ci saranno problemi.

Lo svantaggio è che si avranno più impostazioni comuni in questa tabella. Vorrei spostare le impostazioni che ogni prodotto avrà un valore diverso per un campo nella tabella del prodotto.

Sarà inoltre necessario scrivere convalide per garantire che un utente non modifichi un'impostazione il cui prodotto dice che non è possibile. Dovrai anche scrivere metodi di supporto per unire le impostazioni dal lato prodotto e utente.

0

Ecco la mia esperienza con questo tipo di cose: non eseguire l'override del comportamento.

Vedete, il tuo primo pensiero sta per essere qualcosa di simile:

Hmm .... Non ci sono impostazioni di sistema che possono o non possono essere ignorate dagli utenti (o prodotti). Hey! Lo so! È composizione!

E tecnicamente, avresti ragione. Quindi, creerai una tabella delle impostazioni e inserirai tutte le tue impostazioni. E poi avrai una tabella user_settings, in cui dovrai sovrascrivere quelle impostazioni se l'utente decide in questo modo. E funzionerà bene.

Fino a quando non si aggiunge un'impostazione a una tabella e non l'altra.

Oppure si ottiene un errore che l'impostazione X non può essere ignorata a livello di utente o di prodotto e ci vogliono più di 5 secondi per capire esattamente dove è impostata tale impostazione.

E poi vi renderete conto:

Ehi, sto tenendo traccia di tutte queste impostazioni in almeno due luoghi diversi. Sembra un po 'stupido.

E tu avresti ragione.

Quindi sì. Vai avanti e mantieni le impostazioni nel DB, ma salvale distintamente per ogni utente o prodotto. Utilizza i valori predefiniti intelligenti nella creazione di righe e manterrà le cose semplici e piacevoli.

+1

Hai fatto tutti i tipi di ipotesi su ciò che sta pensando e su come ha intenzione di implementarlo, ma la sua vera domanda era "Qual è il modo migliore per memorizzare queste impostazioni?" Nessuna delle tue ipotesi ha alcun senso in quel contesto. Non penso che questo si qualifica come un "uomo di paglia", ma non sono sicuro di quale altro chiamarlo. –

0

Per il primo tipo di impostazioni, li terrei nel modello Utente (tabella Utenti).

Il secondo tipo di impostazioni, dovrebbe tornare al database. Ad esempio, se un utente ha un account gratuito, questo verrà in qualche modo salvato nel database. Avrei alcuni helper in Application, ad esempio "gratis?" o "commerciale?". Questi helper potrebbero scoprire se sono veri o falsi, chiedendo il modello utente/account attualmente connesso. È quindi possibile utilizzare questi helper in diverse parti dell'applicazione per decidere se mostrare o nascondere determinate funzionalità.

+0

Dovresti denormalizzare per fare questo. Probabilmente sotto forma di un campo di impostazioni serializzato. Non necessariamente una cosa negativa, ma la denormalizzazione è sempre un compromesso. –

1
class Flag < ActiveRecord::Base 
    # id, user_id, name, value (serialized probably) 

    belongs_to :user 

    DEFAULTS = { 
    "newsletter" => false 
    } 

    def self.lookup(user, flag) 
    # Please involve memcached here 
    case flag 
    when "ssl_enabled" 
     # Check if user has paid for sufficient access to SSL 
     return false 
    else 
     stored_flag = self.find_by_user_id_and_name(user.id, flag) 
     if stored_flag 
     return stored_flag.value 
     else 
     return DEFAULTS[flag] 
     end 
    end 
    end 
end 

class User < ActiveRecord::Base 
    has_many :flags 

    def flag(name) 
    return Flag.lookup(self, name) 
    end 
end 

Per le cose che si basa edizione del prodotto, è probabile che non può realmente memorizzare le cose nel database, perché la bandiera sta per essere basata su qualche pezzo di codice di autorizzazione, invece di dati statici.

Problemi correlati