Domanda

Voglio registrare le azioni dell'utente nella mia applicazione Ruby on Rails.

Finora, ho un osservatore modello che inserisce i log nel database dopo gli aggiornamenti e crea. Per memorizzare quale utente ha eseguito l'azione registrata, è necessario accedere alla sessione ma ciò è problematico.

In primo luogo, rompe il modello MVC. In secondo luogo, le tecniche spaziano dall'hackish allo stravagante, forse forse addirittura legando l'implementazione al server Mongrel.

Qual è l'approccio giusto da adottare?

È stato utile?

Soluzione

Trovo che questa sia una domanda molto interessante. Ho intenzione di pensare ad alta voce qui un momento ...

Alla fine, ci troviamo di fronte a una decisione di violare una pratica accettabile del modello di progettazione al fine di ottenere un set specifico di funzionalità. Quindi, dobbiamo chiederci

1) Quali sono le possibili soluzioni che non violerebbero il modello MVC

2) Quali sono le possibili soluzioni che violerebbe il modello MVC

3) Quale opzione è la migliore? Ritengo che i modelli di progettazione e le pratiche standard siano molto importanti, ma allo stesso tempo se attenersi a essi rende il codice più complesso, la soluzione giusta potrebbe benissimo essere quella di violare la pratica. Alcune persone potrebbero non essere d'accordo con me su questo.

Consideriamo prima il n. 1

In cima alla mia testa, vorrei pensare alle seguenti possibili soluzioni

A) Se sei veramente interessato a chi sta eseguendo queste azioni, questi dati dovrebbero essere memorizzati nel modello in qualche modo? Renderebbe disponibili queste informazioni al tuo osservatore. E significa anche che qualsiasi altro chiamante front-end della tua classe ActiveRecord ottiene la stessa funzionalità.

B) Se non sei veramente interessato a capire chi ha creato una voce, ma più interessato a registrare le stesse azioni sul web, allora potresti considerare " osservare " le azioni del controller. È passato un po 'di tempo da quando ho cercato la fonte di Rails, quindi non sono sicuro di chi il loro ActiveRecord :: Observer " osserva " il modello, ma potresti essere in grado di adattarlo a un osservatore del controller. In questo senso, non stai più osservando il modello ed è logico rendere le informazioni sui dati di sessione e altri tipi di controller a quell'osservatore. C) La soluzione più semplice, con il minimo "struttura", è semplicemente eliminare il codice di registrazione alla fine dei metodi di azione che stai guardando.

Prendi in considerazione l'opzione 2 ora, rompendo le pratiche MVC.

A) Mentre proponi, potresti trovare i mezzi per far sì che il tuo modello Observer abbia accesso ai dati della sessione. Hai abbinato il tuo modello alla tua logica aziendale.

B) Non riesco a pensare ad altri qui :)

La mia inclinazione personale, senza conoscere più dettagli sul tuo progetto, è 1A, se voglio allegare persone alle registrazioni, o 1C se ci sono solo pochi posti in cui sono interessato a farlo. Se stai davvero cercando una soluzione di registrazione affidabile per tutti i tuoi controller e azioni, potresti prendere in considerazione 1B.

Avere il tuo osservatore del modello trovare i dati della sessione è un po '"puzzolente", e probabilmente si spezzerebbe se provassi ad usare il tuo modello in qualsiasi altro progetto / situazione / contesto.

Altri suggerimenti

Hrm, questa è una situazione appiccicosa. Devi praticamente violare MVC per farlo funzionare bene.

Farei qualcosa del genere:

class MyObserverClass < ActiveRecord::Observer
  cattr_accessor :current_user # GLOBAL VARIABLE. RELIES ON RAILS BEING SINGLE THREADED

  # other logging code goes here
end

class ApplicationController
  before_filter :set_current_user_for_observer

  def set_current_user_for_observer
    MyObserverClass.current_user = session[:user]
  end
end

È un po 'confuso, ma non è più confuso di molte altre cose fondamentali che ho visto.

Tutto quello che dovresti fare per renderlo thread-safe (questo importa solo se esegui jruby comunque) è cambiare cattr_accessor in modo che sia un metodo corretto, e fargli archiviare i suoi dati nella memoria locale del thread

Hai ragione sull'interruzione di MVC. Suggerirei di usare i callback nei controller, soprattutto perché ci sono situazioni (come un modello che salva viene chiamato ma fallisce la convalida) in cui non vorresti che un osservatore registrasse nulla.

Ho trovato un modo chiaro per fare ciò che è suggerito dalla risposta che ho scelto.

http://pjkh.com / articoli / 2009/02/02 / creazione di-un-audit-log-in-rails

Questa soluzione utilizza un modello AuditLog e un modulo TrackChanges per aggiungere funzionalità di tracciamento a qualsiasi modello. Tuttavia, è necessario aggiungere una riga al controller quando si aggiorna o si crea comunque.

In passato, quando facevo qualcosa del genere, ho teso ad estendere la classe del modello utente per includere l'idea dell '"utente corrente"

Osservando le risposte precedenti, vedo suggerimenti per memorizzare l'utente del record attivo effettivo nella sessione. Ciò ha diversi svantaggi.

  • Memorizza un oggetto possibilmente grande nel database delle sessioni
  • Significa che la copia dell'utente viene "memorizzata nella cache" per tutto il tempo (o fino a quando non viene forzata la disconnessione). Ciò significa che qualsiasi modifica dello stato di questo utente non verrà riconosciuta fino a quando l'utente non si disconnette e riconnette. Ciò significa, ad esempio, che il tentativo di disabilitare l'utente lo attenderà disconnettersi e riconnettersi. Questo probabilmente non è il comportamento che desideri.

In modo che all'inizio di una richiesta (in un filtro) prenda il user_id dalla sessione e legga l'utente, impostando User.current_user.

Qualcosa del genere ...

class User
  cattr_accessor :current_user
end

class Application
  before_filter :retrieve_user

  def retrieve_user
    if session[:user_id].nil?
      User.current_user = nil
    else
      User.current_user = User.find(session[:user_id])
    end
  end
end

Da allora in poi dovrebbe essere banale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top