cirandas.net

ref: master

plugins/analytics/models/analytics_plugin/page_view.rb


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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
  belongs_to :visit, class_name: 'AnalyticsPlugin::Visit', touch: true, validate: true

  belongs_to :referer_page_view, class_name: 'AnalyticsPlugin::PageView', validate: false

  belongs_to :user, class_name: 'Person', validate: false
  belongs_to :session, primary_key: :session_id, foreign_key: :session_id, class_name: 'Session', validate: false

  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 and 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