Noosfero/noosfero

View on GitHub
plugins/analytics/models/analytics_plugin/page_view.rb

Summary

Maintainability
A
0 mins
Test Coverage
class AnalyticsPlugin::PageView < ApplicationRecord
  serialize :data

  attr_accessible *self.column_names
  attr_accessible :user, :profile

  attr_accessor :request
  attr_accessible :request

  extend ActsAsHavingSettings::ClassMethods
  acts_as_having_settings field: :options

  belongs_to :profile, validate: true, optional: true
  belongs_to :visit, class_name: "AnalyticsPlugin::Visit", touch: true, validate: true, optional: true

  belongs_to :referer_page_view, class_name: "AnalyticsPlugin::PageView", validate: false, optional: true

  belongs_to :user, class_name: "Person", validate: false, optional: true
  belongs_to :session, primary_key: :session_id, foreign_key: :session_id, class_name: "Session", validate: false, optional: true

  validates :request, presence: true, on: :create
  validates :url, presence: true

  before_validation :extract_request_data, on: :create
  before_validation :fill_referer_page_view, on: :create
  before_validation :fill_visit, on: :create
  before_validation :fill_is_bot, on: :create

  after_update :destroy_empty_visit
  after_destroy :destroy_empty_visit

  scope :in_sequence, -> { order "analytics_plugin_page_views.request_started_at ASC" }

  scope :page_loaded, -> { where "analytics_plugin_page_views.page_loaded_at IS NOT NULL" }
  scope :not_page_loaded, -> { where "analytics_plugin_page_views.page_loaded_at IS NULL" }

  scope :no_bots, -> { where.not is_bot: true }
  scope :bots, -> { where is_bot: true }

  scope :loaded_users, -> { in_sequence.page_loaded.no_bots }

  def request_duration
    self.request_finished_at - self.request_started_at
  end

  def initial_time
    self.page_loaded_at || self.request_finished_at
  end

  def user_last_time_seen
    self.initial_time + self.time_on_page
  end

  def user_on_page?
    Time.now < self.user_last_time_seen + AnalyticsPlugin::TimeOnPageUpdateInterval
  end

  def page_load!(time)
    self.page_loaded_at = time
    self.update_column :page_loaded_at, self.page_loaded_at
  end

  def increase_time_on_page!
    now = Time.now
    return unless now > self.initial_time

    self.time_on_page = now - self.initial_time
    self.update_column :time_on_page, self.time_on_page
  end

  def find_referer_page_view
    return if self.referer_url.blank?

    AnalyticsPlugin::PageView.order("request_started_at DESC")
                             .where(url: self.referer_url, session_id: self.session_id, user_id: self.user_id, profile_id: self.profile_id).first
  end

  def browser
    @browser ||= Browser.new self.user_agent
  end

  protected

    def extract_request_data
      self.url = self.request.url.sub /\/+$/, ""
      self.referer_url = self.request.referer
      self.user_agent = self.request.headers["User-Agent"]
      self.request_id = self.request.env["action_dispatch.request_id"]
      self.remote_ip = self.request.remote_ip
      true
    end

    def fill_referer_page_view
      self.referer_page_view = self.find_referer_page_view
      true
    end

    def fill_visit
      self.visit = self.referer_page_view.visit if self.referer_page_view && self.referer_page_view.user_on_page?
      self.visit ||= AnalyticsPlugin::Visit.new profile: profile
      true
    end

    def fill_is_bot
      self.is_bot = self.browser.bot?
      true
    end

    def destroy_empty_visit
      return unless self.visit_id_changed?

      old_visit = AnalyticsPlugin::Visit.find self.visit_id_was
      old_visit.destroy if old_visit.page_views.empty?
    end
end