Counter mit Ruby on Rails

Eine der ersten Anforderungen von Kunden an eine Webseite ist: Wie viele Besucher tummeln sich auf meiner Seite? Dazu baut man einen sogenannten Zugriffszähler (oder auch counter) in seine Applikation ein. In meinen Anfängen schon oft mit PHP gemacht, nie aber mit Rails. Das soll dieser Artikel ändern. Er ist aber auch eine (Gedanken-)Stütze für mich, wenn ich mal wieder drüber nachdenke, wie man einen solchen Counter schreibt oder erweitern kann.

Eigentlich ist es recht einfach, einen Counter in Rails zu erstellen. Wir erzeugen zuerst ein Model ‚visit‘, welches einen Besuch eines Nutzers darstellt.

script/generate model visit

Dann schreiben wir noch die migrations um und migrieren unsere Datenbank auf die neueste Version.

class CreateVisits < ActiveRecord::Migration
  def self.up
    create_table :visits do |t|
      t.string :ip
      t.string :referrer
      t.string :browser_agent
      t.string :page
      t.timestamps
    end
  end
 
  def self.down
    drop_table :visits
  end
end
rake db:migrate

Dann brauchen wir noch eine Methode, in der wir neue User in die DB packen. Ich habe das ganze über eine Methode in meinem PagesController (der meine Seiten verwaltet) gelöst. Diese Methode wird in einem before_filter aufgerufen.

class PagesController < ApplicationController   
before_filter :write_statistics 
 
# ... andere Logik  
 
protected   
def write_statistics     
# Suche nach Einträgen von heute mit passender IP und Browser Agent     
visit = Visit.find(:first, :conditions =>{
      :ip => request.remote_ip.to_s,
      :browser_agent => request.env['HTTP_USER_AGENT'],
      :updated_at => DateTime.now.beginning_of_day..DateTime.now.end_of_day
    })
    if visit.nil?
      # eintrag existiert noch nicht -> anlegen, fertig
      v = Visit.new({
          :ip => request.remote_ip.to_s,
          :browser_agent => request.env['HTTP_USER_AGENT'],
          :page => "#{params[:controller]}/#{params[:action]}",
          :referrer => request.env['HTTP_REFERRER']
        })
      # Logging
      logger.error "Fehler beim Speichern eines Visits" unless v.save
    end
  end
 
end

Den Inhalt der Methode kann man natürlich nach seinen Wünschen anpassen. In dem Fall wird jeder Besucher pro Tag einmal gespeichert. (Hinweis: Evtl. müssen die Parameter config.time_zone und config.active_record.default_timezone in der environment.rb auf die gewünschte Zeitzone angepasst werden)
Ergänzend dazu kann man nun einige Helper erstellen, die überall verwendet werden können:

module PagesHelper
 
  def visitors_today
    v = Visit.find(:all, :conditions => {
        :updated_at => DateTime.now.beginning_of_day..DateTime.now.end_of_day
      })
    v.size
  end
 
  # day as DateTime
  def visitors_on day
    v = Visit.find(:all, :conditions => {
        :updated_at => day.beginning_of_day..day.end_of_day
      })
    v.size
  end
 
  def visitors_total
    Visit.count
  end
 
end

Erweiterungsmöglichkeiten:

  • Alle Seiten speichern, die der Besucher aufruft, Vorteil: bessere Auswertungsmöglichkeiten (Welche Seiten werden häufig besucht, etc.), Nachteil: sehr schnell viele Daten – abhängig von Seitenzahl
  • Weitere Kontrollen einbauen: Cookies, Sessions, etc.
  • Helpermethoden in einem Partial zu einer „Statistik-Box“ zusammenfassen