Domanda

Sto lavorando su un'applicazione Rails, dove sto usando il caching delle pagine viene salvato il risultato HTML statico. Il caching funziona bene. Ho problemi con scadenza delle cache, però.

Credo che il mio problema è, in parte, perché io non sono in scadenza la cache dal mio controller. Tutte le azioni necessarie per questo vengono trattati all'interno del modello. Questo sembra che dovrebbe essere fattibile, ma tutti i riferimenti alla scadenza della cache basata su modelli che mi sto trovando sembra di essere aggiornati, o stanno altrimenti non funziona.

Nel mio file environment.rb, sto chiamando

config.load_paths += %W( #{RAILS_ROOT}/app/sweepers )

E ho, nella cartella / spazzatrici, un file LinkSweeper:

class LinkSweeper < ActionController::Caching::Sweeper
  observe Link

  def after_update(link)
    clear_links_cache(link)
  end

  def clear_links_cache(link)
  # expire_page :controller => 'links', :action => 'show', :md5 => link.md5
    expire_page '/l/'+ link.md5 + '.html'
  end
end

... perché non è l'eliminazione della pagina memorizzata nella cache quando aggiorno il modello (processo:? Utilizzando script / console, sto selezionando elementi dal database e salvarli, ma le loro pagine corrispondenti non siano eliminazione dalla cache), e sono anche chiamando il metodo specifico del modello di collegamento che normalmente invocare la spazzatrice. Né lavori.

Se è importante, il file memorizzato nella cache è un hash MD5 fuori un valore chiave nella tabella Links. La pagina memorizzata nella cache è sempre memorizzato come qualcosa di simile a / l / 45ed4aade64d427 ... 99919cba2bd90f.html.

In sostanza, sembra che la spazzatrice non è effettivamente osservando il Link. Ho anche letto ( qui ) che potrebbe sarà possibile aggiungere semplicemente la spazzatrice per config.active_record.observers in environment.rb, ma che non sembrano farlo (e non ero sicuro se la load_path di app / spazzatrici in environment.rb ovviato quello).

È stato utile?

Soluzione

Solo una nota:. È possibile utilizzare cache_sweeper in ApplicationController

class ApplicationController < ActionController::Base
  cache_sweeper :my_sweeper
end

class MySweeper < ActionController::Caching::Sweeper
  observe MyModel

  def after_update(my_model)
    expire_page(...)
  end
end

Altri suggerimenti

Così ho provato un certo numero di approcci diversi, per vedere cosa funziona, e non quello che fa.

Anche in questo caso, per riassumere la situazione: Il mio obiettivo è quello di scadere pagine memorizzate nella cache quando un aggiornamento degli oggetti, ma per scadere loro senza fare affidamento su un'azione di controllo spazzatrici convenzionali utilizzano una linea nel controller di notificare. la spazzatrice che ha bisogno per funzionare. In questo caso, non è possibile utilizzare una riga nel controllore, come l'aggiornamento avviene all'interno del modello. tutorial spazzatrice normali non funzionano, come si presume che l'interazione principale con l'oggetto database è attraverso il controller.

Se, nella lettura di questo, si vede un modo per stringere il mio codice, si prega di commentare e fatemi sapere.

Per prima cosa, diamo un'occhiata a delle cose che funzionano, nel caso in cui sei bloccato su questo, anche, e hanno bisogno di aiuto.

Di tutte le cose che ho provato, l'unica cosa che sembrava davvero il lavoro è stato quello di dichiarare un comando di after_update nel Observer per il modello. In questo comando, ho usato il comando esplicito per l'azione expire_page, e comprendeva un percorso che era stato dichiarato in routes.rb.

. Questo funziona:

In config / routes.rb:

map.link 'l/:md5.:format',  :controller => 'links', :action => 'show'

In app / modelli / link_observer.rb:

def after_update(link)
  ActionController::Base.expire_page(app.link_path(:md5 => link.md5))
end

Si noti che che "MD5" è specifico per la mia app. Si potrebbe desiderare di utilizzare:. Id o qualche altro identificatore univoco

Ho anche scoperto che dichiarando che ActionController :: Base ... linea dal metodo nel modello che sta facendo l'aggiornamento ha funzionato. Cioè, all'interno Link.rb, nel metodo che è in realtà l'aggiornamento del database, se ho appena bloccato che tutta la linea in, ha funzionato. Ma dal momento che potrei voler scadere che cache di pagina su altri metodi in futuro, preferirei averlo estratto nel Observer.

Ora, diamo un'occhiata ad alcune cose che non hanno funzionato, nel caso in cui si sta Googling in giro per questo.

Calling "expire_page (...)" all'interno del after_update (link) metodo all'interno link_observer.rb non ha funzionato, in quanto ha restituito un "metodo non definito` expire_page '" Errore

Creazione di un file Sweeper che ha osservato il modello non ha funzionato. Non riuscivo a trovare eventuali codici di errore, ma solo sembrava essere nemmeno a conoscenza che aveva un lavoro da fare. Questo è stato dopo aver chiamato in modo esplicito "config.load_paths + =% W (# {} RAILS_ROOT / app / spazzatrici)" all'interno di environment.rb. Solo nel caso in cui qualcosa di grasso dalle dita in quel codice, qui è:

class LinkSweeper < ActionController::Caching::Sweeper
  observe Link

  def after_update(link)
    clear_links_cache(link)
  end

  def clear_links_cache(link)
    # DID NOT WORK    expire_page :controller => 'links', :action => 'show', :md5 => link.md5
    # DID NOT WORK    expire_page '/l/'+ link.md5 + '.html'
    # DID NOT WORK    ActionController::Base.expire_page(app.link_path(:md5 => link.md5))
  end
end

Quello sopra esempio aveva il file link_sweeper.rb in una directory, / app / spazzatrici. Ho anche provato a mettere link_sweeper.rb all'interno della directory app / modelli, e provato a chiamare con le config.active_record.observers comando nel environment.rb:

config.active_record.observers = :link_observer, :link_sweeper

Ma che non ha funzionato, neanche.

Quindi, sì. E 'molto probabile che uno di questi metodi avrebbe funzionato, e che io incasinato qualcosa nel codice. Ma credo di aver fatto tutto secondo le regole.

In definitiva, per riassumere: Piuttosto che usare una spazzatrice per scadere il caching delle pagine, si vuole impostare una richiamata after_ nel Observer del modello. Ti consigliamo di utilizzare il percorso esplicito al metodo Base.expire_page:

def after_update(<model>) # where <model> is the name of the model you're observing
  ActionController::Base.expire_page(app.<model>_path(:id => <model>.id)) # where <model> is the name of the model you're observing
end

Speriamo che questo vi aiuterà a qualcun altro lungo la strada. Anche in questo caso, se si vede da nessuna parte nel mio codice non-lavoro in cui avrei dovuto fare qualcosa di diverso, per favore fatemelo sapere. Se vedi qualcosa nel mio codice di lavoro che può essere più stretto, per favore fatemelo sapere anche questo.

stavo sperimentando lo stesso problema quando si cerca di fare frammento di caching (binari 3). Impossibile ottenere la spazzatrice per osservare, così ho optato per la soluzione per renderlo un AR Observer come descritto sopra e chiamando ApplicationController.new.expire_fragment(...).

L'ho fatto ottenere questo lavoro. L'unica lieve differenza nella mia messa a punto è che la spazzatrice è parte di un motore Rails; che rappresenta lievi differenze (caricamento del file spazzino con una necessaria nel motore di init invece di aggiungere al percorso di carico in environment.rb, ecc).

Quindi, la spazzatrice viene caricato nel init.rb del motore in questo modo:

require File.join(File.dirname(__FILE__), 'app', 'sweepers', cached_category_count_sweeper')

L'ho chiamato una spazzatrice perché "spazza" la cache, ma credo che il suo solo un osservatore sul modello:

class CachedCategoryCountSweeper < ActiveRecord::Observer
  observe CategoryFeature

  def before_save(cf)
    expire_cache(cf.category_id_was) if cf.category_id_changed?
  end

  def after_save(cf)
    expire_cache(cf.category_id)
  end

  def after_destroy(cf)
    expire_cache(cf.category_id)
  end

  def expire_cache(c)
    ApplicationController.expire_page("/categories/#{c}/counts.xml") if !c.nil?
  end
end

Francamente, non mi piace dover codificare il percorso, ma ho provato ad aggiungere:

include ActionController:UrlWriter

e quindi utilizzando il metodo del percorso, ma ha funzionato solo per me in fase di sviluppo. Non ha funzionato nella produzione, perché il mio server di produzione utilizza una radice URL relativo (invece di host virtuali) e il metodo "page_cache_path" interna sarebbe costantemente ottenere il percorso del file sbagliato così non poteva scadere.

Dal momento che questo è un osservatore, ho aggiunto al environment.rb:

config.active_record.observers = :cached_category_count_sweeper

Infine, il controller che utilizza la cache (non ha scadenza di esso, che è fatto attraverso il modello osservatore):

class CachedCategoryCountsController < ApplicationController
  caches_page :index

  # GET /cached_category_counts.xml
  def index
    ...
  end
end

In ogni caso, spero che questo aiuta.

Andres Montano

Sono stato in grado di farlo funzionare, per modo di aggiungere

ActionController::Base.expire_page(app.link_path(:md5 => @link.md5))

per il metodo nel Modello stesso che è l'aggiornamento del database. Questo si sente un po 'hacky, però, e mi piacerebbe sapere se qualcuno può spiegare perché non funziona con la normale configurazione spazzino, e se c'è un modo più elegante per gestire questo.

Questo frammento di codice (a parte le personalizzazioni ho messo dentro per la mia app) è venuto da questo post su ruby-forum.com .

ho scritto un po 'su questo argomento qui: Rails Cache Sweeper Confusion . Piacerebbe sentire le vostre opinioni.

In base a @moiristo e S' @ZoogieZork risposte, sto indovinando questo dovrebbe funzionare (non testato).

class LinkSweeper < ActiveRecord::Observer
  include ActionController::Caching::Pages
  # or if you want to expire fragments
  #include ActionController::Caching::Fragments

  observe Link

  def after_update(link)
    expire_page( ... )
    #expire_fragment( ... )
  end
end
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top