Avete alcune opzioni diverse per saltare un aggiornamento della cache contatore, e quello che si sceglie dipende davvero da come vuoi strutturare la tua applicazione. Discuterò i diversi modi in cui è possibile aggirare la cache del contatore e menzionare alcune delle considerazioni che si potrebbero voler fare nel farlo.
Fondamentalmente, ci sono tre diversi modi si può saltare l'aggiornamento della cache contatore:
- Monkey patch your model to disable the counter cache callback
- Use an update method that doesn't trigger callbacks
- definire un modello alternativo che punta alla stessa tabella che non ha la stesso comportamento di callback e usarlo quando si inserisce massa nel database
Si noti che le prime due opzioni sopra sono più g enerally related to disabilitazione di callback in ActiveRecord, e questo ha senso perché la counter cache è implementata internamente per mezzo di un callback.
Quando Rails carica un modello che ha associazioni con una cache contatore, definisce dinamicamente i metodi di callback. Se si desidera disabilitare questi come callback, è necessario prima capire quali sono i nomi di callback.
Ci sono due modi principali per capire quali sono i metodi che Rails ha definito per implementare questi callback. Puoi leggere l'origine di Rails per scoprire i nomi che genererà tramite l'intorpolazione String, oppure puoi usare l'introspezione per capire a quali metodi risponde la tua classe. Fornirò un esempio di come è possibile utilizzare l'introspezione per scoprire i callback definiti da ActiveRecord al fine di implementare automaticamente la cache di contatori.
Supponiamo di avere una classe chiamata SpecialReply che discende da una classe Rispondi che discende da ActiveRecord :: Base (this example comes from the test suite with Rails). Ha una colonna della cache contatore come definito di seguito:
class SpecialReply < ::Reply
belongs_to :special_topic, :foreign_key => 'parent_id', :counter_cache => 'replies_count'
end
Nella console, è possibile vedere quali metodi la classe risponde utilizzando .methods
. Questo sta per produrre un sacco di rumore, dal momento che ogni istanza di Object
risponde già ad un sacco di metodi, in modo da poter restringere la lista come segue:
1.9.3-p194 :001 > sr = SpecialReply.new
1.9.3-p194 :002 > sr.methods - Object.methods
Nella seconda riga che stai dicendo, spettacolo tutti i metodi a cui risponde la mia istanza di SpecialReply, meno quelli a cui tutti gli oggetti rispondono. Questo spesso aiuta con l'introspezione filtrando i metodi che non sono particolari per il tipo di classe che stai guardando.
Sfortunatamente anche dopo questo filtraggio c'è molto rumore dovuto ai metodi che ActiveRecord aggiunge a tutte le sue classi discendenti. In questo caso grep
è utile - dal ActiveRecord crea utilmente metodi di callback da banco che contengono la stringa counter_cache
(see the meta-programming used by ActiveRecord to generate a counter cache method for a belongs_to
association), è possibile scoprire i callback definiti relativi a contrastare le cache con il seguente:
1.9.3-p194 :001 > sr = SpecialReply.new
1.9.3-p194 :002 > sr.methods.map(&:to_s).grep(/counter_cache/)
Si noti che dal grep
opera su una stringa e methods
restituisce una matrice di nomi di metodi simbolo, per prima cosa utilizziamo uno to_proc
(&:
) per convertire tutti i simboli in stringhe e quindi grep out quelli contenenti counter_cache
. Questo mi lascia con i seguenti metodi che sembrano come se fossero probabilmente generato automaticamente da ActiveRecord come callback per l'attuazione contatore caching:
belongs_to_counter_cache_after_create_for_special_topic
belongs_to_counter_cache_before_destroy_for_special_topic
belongs_to_counter_cache_after_create_for_topic
belongs_to_counter_cache_before_destroy_for_topic
belongs_to_counter_cache_after_create_for_topic_with_primary_key
belongs_to_counter_cache_before_destroy_for_topic_with_primary_key
si dovrebbe essere in grado di seguire un processo simile nel vostro programma per determinare i nomi dei metodi aggiunti da ActiveRecord in modo da poterli buttare fuori dopo existing instructions for removing callbacks.
La scelta tra le opzioni di cui sopra dipende in realtà dalla struttura del programma e dai compromessi che si desidera prendere in considerazione per una maggiore efficienza dei dati di caricamento. È importante notare che le prime due opzioni possono rendere il codice meno leggibile modificando il comportamento di una classe dall'esterno (patch di scimmia) e possono rendere instabile il sistema ignorando le regole di business (aggiornamenti delle colonne della cache) sugli aggiornamenti dei dati. Per questi motivi, vorrei riflettere sull'opportunità di creare un'altra classe per caricare i dati in modo ottimizzato, riducendo al minimo l'impatto sulla leggibilità o sulla coerenza dei dati.
Hai risolto questo? Stesso problema... –