ahoy_matey 1.5.3 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +88 -0
  3. data/CONTRIBUTING.md +42 -0
  4. data/LICENSE.txt +1 -1
  5. data/README.md +369 -380
  6. data/app/controllers/ahoy/base_controller.rb +15 -15
  7. data/app/controllers/ahoy/events_controller.rb +8 -2
  8. data/app/controllers/ahoy/visits_controller.rb +8 -1
  9. data/app/jobs/ahoy/geocode_job.rb +10 -0
  10. data/app/jobs/ahoy/geocode_v2_job.rb +28 -0
  11. data/config/routes.rb +1 -1
  12. data/lib/ahoy.rb +68 -86
  13. data/lib/ahoy/base_store.rb +97 -0
  14. data/lib/ahoy/controller.rb +26 -17
  15. data/lib/ahoy/database_store.rb +89 -0
  16. data/lib/ahoy/engine.rb +7 -7
  17. data/lib/ahoy/helper.rb +40 -0
  18. data/lib/ahoy/model.rb +5 -27
  19. data/lib/ahoy/{properties.rb → query_methods.rb} +25 -9
  20. data/lib/ahoy/tracker.rb +101 -42
  21. data/lib/ahoy/utils.rb +7 -0
  22. data/lib/ahoy/version.rb +1 -1
  23. data/lib/ahoy/visit_properties.rb +99 -37
  24. data/lib/generators/ahoy/activerecord_generator.rb +41 -0
  25. data/lib/generators/ahoy/base_generator.rb +13 -0
  26. data/lib/generators/ahoy/install_generator.rb +44 -0
  27. data/lib/generators/ahoy/mongoid_generator.rb +16 -0
  28. data/lib/generators/ahoy/templates/active_record_event_model.rb.tt +10 -0
  29. data/lib/generators/ahoy/templates/active_record_migration.rb.tt +62 -0
  30. data/lib/generators/ahoy/templates/active_record_visit_model.rb.tt +6 -0
  31. data/lib/generators/ahoy/templates/base_store_initializer.rb.tt +20 -0
  32. data/lib/generators/ahoy/templates/database_store_initializer.rb.tt +5 -0
  33. data/lib/generators/ahoy/{stores/templates/mongoid_event_model.rb → templates/mongoid_event_model.rb.tt} +4 -2
  34. data/lib/generators/ahoy/{stores/templates/mongoid_visit_model.rb → templates/mongoid_visit_model.rb.tt} +15 -9
  35. data/vendor/assets/javascripts/ahoy.js +336 -113
  36. metadata +54 -144
  37. data/.gitignore +0 -17
  38. data/Gemfile +0 -6
  39. data/Rakefile +0 -8
  40. data/ahoy_matey.gemspec +0 -38
  41. data/lib/ahoy/deckhands/location_deckhand.rb +0 -49
  42. data/lib/ahoy/deckhands/request_deckhand.rb +0 -52
  43. data/lib/ahoy/deckhands/technology_deckhand.rb +0 -47
  44. data/lib/ahoy/deckhands/traffic_source_deckhand.rb +0 -22
  45. data/lib/ahoy/deckhands/utm_parameter_deckhand.rb +0 -23
  46. data/lib/ahoy/geocode_job.rb +0 -13
  47. data/lib/ahoy/logger_silencer.rb +0 -75
  48. data/lib/ahoy/stores/active_record_store.rb +0 -60
  49. data/lib/ahoy/stores/active_record_token_store.rb +0 -113
  50. data/lib/ahoy/stores/base_store.rb +0 -88
  51. data/lib/ahoy/stores/bunny_store.rb +0 -33
  52. data/lib/ahoy/stores/fluentd_store.rb +0 -17
  53. data/lib/ahoy/stores/kafka_store.rb +0 -40
  54. data/lib/ahoy/stores/kinesis_firehose_store.rb +0 -42
  55. data/lib/ahoy/stores/log_store.rb +0 -53
  56. data/lib/ahoy/stores/mongoid_store.rb +0 -63
  57. data/lib/ahoy/subscribers/active_record.rb +0 -19
  58. data/lib/ahoy/throttle.rb +0 -17
  59. data/lib/generators/ahoy/stores/active_record_events_generator.rb +0 -53
  60. data/lib/generators/ahoy/stores/active_record_generator.rb +0 -16
  61. data/lib/generators/ahoy/stores/active_record_visits_generator.rb +0 -43
  62. data/lib/generators/ahoy/stores/bunny_generator.rb +0 -15
  63. data/lib/generators/ahoy/stores/custom_generator.rb +0 -15
  64. data/lib/generators/ahoy/stores/fluentd_generator.rb +0 -15
  65. data/lib/generators/ahoy/stores/kafka_generator.rb +0 -15
  66. data/lib/generators/ahoy/stores/kinesis_firehose_generator.rb +0 -15
  67. data/lib/generators/ahoy/stores/log_generator.rb +0 -15
  68. data/lib/generators/ahoy/stores/mongoid_events_generator.rb +0 -19
  69. data/lib/generators/ahoy/stores/mongoid_generator.rb +0 -14
  70. data/lib/generators/ahoy/stores/mongoid_visits_generator.rb +0 -27
  71. data/lib/generators/ahoy/stores/templates/active_record_event_model.rb +0 -12
  72. data/lib/generators/ahoy/stores/templates/active_record_events_migration.rb +0 -19
  73. data/lib/generators/ahoy/stores/templates/active_record_initializer.rb +0 -3
  74. data/lib/generators/ahoy/stores/templates/active_record_visit_model.rb +0 -4
  75. data/lib/generators/ahoy/stores/templates/active_record_visits_migration.rb +0 -57
  76. data/lib/generators/ahoy/stores/templates/bunny_initializer.rb +0 -9
  77. data/lib/generators/ahoy/stores/templates/custom_initializer.rb +0 -10
  78. data/lib/generators/ahoy/stores/templates/fluentd_initializer.rb +0 -3
  79. data/lib/generators/ahoy/stores/templates/kafka_initializer.rb +0 -9
  80. data/lib/generators/ahoy/stores/templates/kinesis_firehose_initializer.rb +0 -17
  81. data/lib/generators/ahoy/stores/templates/log_initializer.rb +0 -3
  82. data/lib/generators/ahoy/stores/templates/mongoid_initializer.rb +0 -3
  83. data/test/properties/mysql_json_test.rb +0 -18
  84. data/test/properties/mysql_text_test.rb +0 -19
  85. data/test/properties/postgresql_hstore_test.rb +0 -18
  86. data/test/properties/postgresql_json_test.rb +0 -18
  87. data/test/properties/postgresql_jsonb_test.rb +0 -18
  88. data/test/properties/postgresql_text_test.rb +0 -19
  89. data/test/test_helper.rb +0 -99
  90. data/test/visit_properties_test.rb +0 -44
@@ -1,52 +0,0 @@
1
- module Ahoy
2
- module Deckhands
3
- class RequestDeckhand
4
- attr_reader :request
5
-
6
- def initialize(request, options = {})
7
- @request = request
8
- @options = options
9
- end
10
-
11
- def ip
12
- request.remote_ip
13
- end
14
-
15
- def user_agent
16
- request.user_agent
17
- end
18
-
19
- def referrer
20
- @options[:api] ? params["referrer"] : request.referer
21
- end
22
-
23
- def landing_page
24
- @options[:api] ? params["landing_page"] : request.original_url
25
- end
26
-
27
- def platform
28
- params["platform"]
29
- end
30
-
31
- def app_version
32
- params["app_version"]
33
- end
34
-
35
- def os_version
36
- params["os_version"]
37
- end
38
-
39
- def screen_height
40
- params["screen_height"]
41
- end
42
-
43
- def screen_width
44
- params["screen_width"]
45
- end
46
-
47
- def params
48
- @params ||= request.params
49
- end
50
- end
51
- end
52
- end
@@ -1,47 +0,0 @@
1
- module Ahoy
2
- module Deckhands
3
- class TechnologyDeckhand
4
- def initialize(user_agent)
5
- @user_agent = user_agent
6
- end
7
-
8
- def browser
9
- agent.name
10
- end
11
-
12
- def os
13
- agent.os.name
14
- end
15
-
16
- def device_type
17
- @device_type ||= begin
18
- browser = Browser.new(@user_agent)
19
- if browser.bot?
20
- "Bot"
21
- elsif browser.device.tv?
22
- "TV"
23
- elsif browser.device.console?
24
- "Console"
25
- elsif browser.device.tablet?
26
- "Tablet"
27
- elsif browser.device.mobile?
28
- "Mobile"
29
- else
30
- "Desktop"
31
- end
32
- end
33
- end
34
-
35
- protected
36
-
37
- def agent
38
- @agent ||= self.class.user_agent_parser.parse(@user_agent)
39
- end
40
-
41
- # performance
42
- def self.user_agent_parser
43
- @user_agent_parser ||= UserAgentParser::Parser.new
44
- end
45
- end
46
- end
47
- end
@@ -1,22 +0,0 @@
1
- module Ahoy
2
- module Deckhands
3
- class TrafficSourceDeckhand
4
- def initialize(referrer)
5
- @referrer = referrer
6
- end
7
-
8
- def referring_domain
9
- @referring_domain ||= Addressable::URI.parse(@referrer).host.first(255) rescue nil
10
- end
11
-
12
- def search_keyword
13
- @search_keyword ||= (self.class.referrer_parser.parse(@referrer)[:term][0..255] rescue nil).presence
14
- end
15
-
16
- # performance hack for referer-parser
17
- def self.referrer_parser
18
- @referrer_parser ||= RefererParser::Parser.new
19
- end
20
- end
21
- end
22
- end
@@ -1,23 +0,0 @@
1
- module Ahoy
2
- module Deckhands
3
- class UtmParameterDeckhand
4
- def initialize(landing_page, params = nil)
5
- @landing_page = landing_page
6
- @params = params || {}
7
- end
8
-
9
- def landing_params
10
- @landing_params ||= begin
11
- landing_uri = Addressable::URI.parse(@landing_page) rescue nil
12
- (landing_uri && landing_uri.query_values) || {}
13
- end
14
- end
15
-
16
- %w(utm_source utm_medium utm_term utm_content utm_campaign).each do |name|
17
- define_method name do
18
- @params[name] || landing_params[name]
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,13 +0,0 @@
1
- module Ahoy
2
- class GeocodeJob < ActiveJob::Base
3
- queue_as :ahoy
4
-
5
- def perform(visit)
6
- deckhand = Deckhands::LocationDeckhand.new(visit.ip)
7
- Ahoy::VisitProperties::LOCATION_KEYS.each do |key|
8
- visit.send(:"#{key}=", deckhand.send(key)) if visit.respond_to?(:"#{key}=")
9
- end
10
- visit.save!
11
- end
12
- end
13
- end
@@ -1,75 +0,0 @@
1
- # from https://github.com/rails/activerecord-session_store/blob/master/lib/active_record/session_store/extension/logger_silencer.rb
2
- require "thread"
3
- require "active_support/core_ext/class/attribute_accessors"
4
- require "active_support/core_ext/module/aliasing"
5
- require "active_support/core_ext/module/attribute_accessors"
6
- require "active_support/concern"
7
-
8
- module Ahoy
9
- module LoggerSilencer
10
- extend ActiveSupport::Concern
11
-
12
- included do
13
- cattr_accessor :silencer
14
- self.silencer = true
15
- alias_method :level_without_threadsafety, :level
16
- alias_method :level, :level_with_threadsafety
17
- alias_method :add_without_threadsafety, :add
18
- alias_method :add, :add_with_threadsafety
19
- end
20
-
21
- def thread_level
22
- Thread.current[thread_hash_level_key]
23
- end
24
-
25
- def thread_level=(level)
26
- Thread.current[thread_hash_level_key] = level
27
- end
28
-
29
- def level_with_threadsafety
30
- thread_level || level_without_threadsafety
31
- end
32
-
33
- def add_with_threadsafety(severity, message = nil, progname = nil, &block)
34
- if (defined?(@logdev) && @logdev.nil?) || (severity || UNKNOWN) < level
35
- true
36
- else
37
- add_without_threadsafety(severity, message, progname, &block)
38
- end
39
- end
40
-
41
- # Silences the logger for the duration of the block.
42
- def silence_logger(temporary_level = Logger::ERROR)
43
- if silencer
44
- begin
45
- self.thread_level = temporary_level
46
- yield self
47
- ensure
48
- self.thread_level = nil
49
- end
50
- else
51
- yield self
52
- end
53
- end
54
-
55
- for severity in Logger::Severity.constants
56
- class_eval <<-EOT, __FILE__, __LINE__ + 1
57
- def #{severity.downcase}? # def debug?
58
- Logger::#{severity} >= level # DEBUG >= level
59
- end # end
60
- EOT
61
- end
62
-
63
- private
64
-
65
- def thread_hash_level_key
66
- @thread_hash_level_key ||= :"ThreadSafeLogger##{object_id}@level"
67
- end
68
- end
69
- end
70
-
71
- class NilLogger
72
- def self.silence_logger
73
- yield
74
- end
75
- end
@@ -1,60 +0,0 @@
1
- module Ahoy
2
- module Stores
3
- class ActiveRecordStore < BaseStore
4
- def track_visit(options, &block)
5
- @visit =
6
- visit_model.new do |v|
7
- v.id = ahoy.visit_id
8
- v.visitor_id = ahoy.visitor_id
9
- v.user = user if v.respond_to?(:user=)
10
- v.started_at = options[:started_at]
11
- end
12
-
13
- set_visit_properties(visit)
14
-
15
- yield(visit) if block_given?
16
-
17
- begin
18
- visit.save!
19
- geocode(visit)
20
- rescue *unique_exception_classes
21
- # do nothing
22
- end
23
- end
24
-
25
- def track_event(name, properties, options, &block)
26
- event =
27
- event_model.new do |e|
28
- e.id = options[:id]
29
- e.visit_id = ahoy.visit_id
30
- e.user = user if e.respond_to?(:user=)
31
- e.name = name
32
- e.properties = properties
33
- e.time = options[:time]
34
- end
35
-
36
- yield(event) if block_given?
37
-
38
- begin
39
- event.save!
40
- rescue *unique_exception_classes
41
- # do nothing
42
- end
43
- end
44
-
45
- def visit
46
- @visit ||= visit_model.where(id: ahoy.visit_id).first if ahoy.visit_id
47
- end
48
-
49
- protected
50
-
51
- def visit_model
52
- ::Visit
53
- end
54
-
55
- def event_model
56
- ::Ahoy::Event
57
- end
58
- end
59
- end
60
- end
@@ -1,113 +0,0 @@
1
- module Ahoy
2
- module Stores
3
- class ActiveRecordTokenStore < BaseStore
4
- def track_visit(options, &block)
5
- @visit =
6
- visit_model.new do |v|
7
- v.visit_token = ahoy.visit_token
8
- v.visitor_token = ahoy.visitor_token
9
- v.user = user if v.respond_to?(:user=)
10
- v.started_at = options[:started_at] if v.respond_to?(:started_at)
11
- v.created_at = options[:started_at] if v.respond_to?(:created_at)
12
- end
13
-
14
- set_visit_properties(visit)
15
-
16
- yield(visit) if block_given?
17
-
18
- begin
19
- visit.save!
20
- geocode(visit)
21
- rescue *unique_exception_classes
22
- # do nothing
23
- end
24
- end
25
-
26
- def track_event(name, properties, options, &block)
27
- if self.class.uses_deprecated_subscribers?
28
- options[:controller] ||= controller
29
- options[:user] ||= user
30
- options[:visit] ||= visit
31
- options[:visit_token] ||= ahoy.visit_token
32
- options[:visitor_token] ||= ahoy.visitor_token
33
-
34
- subscribers = Ahoy.subscribers
35
- if subscribers.any?
36
- subscribers.each do |subscriber|
37
- subscriber.track(name, properties, options.dup)
38
- end
39
- else
40
- $stderr.puts "No subscribers"
41
- end
42
- else
43
- event =
44
- event_model.new do |e|
45
- e.visit_id = visit.try(:id)
46
- e.user = user
47
- e.name = name
48
- e.properties = properties
49
- e.time = options[:time]
50
- end
51
-
52
- yield(event) if block_given?
53
-
54
- event.save!
55
- end
56
- end
57
-
58
- def visit
59
- @visit ||= (visit_model.where(visit_token: ahoy.visit_token).first if ahoy.visit_token)
60
- end
61
-
62
- def exclude?
63
- (!Ahoy.track_bots && bot?) ||
64
- (
65
- if Ahoy.exclude_method
66
- warn "[DEPRECATION] Ahoy.exclude_method is deprecated - use exclude? instead"
67
- if Ahoy.exclude_method.arity == 1
68
- Ahoy.exclude_method.call(controller)
69
- else
70
- Ahoy.exclude_method.call(controller, request)
71
- end
72
- else
73
- false
74
- end
75
- )
76
- end
77
-
78
- def user
79
- @user ||= begin
80
- user_method = Ahoy.user_method
81
- if user_method.respond_to?(:call)
82
- user_method.call(controller)
83
- elsif user_method
84
- controller.send(user_method)
85
- else
86
- super
87
- end
88
- end
89
- end
90
-
91
- class << self
92
- def uses_deprecated_subscribers
93
- warn "[DEPRECATION] Ahoy subscribers are deprecated"
94
- @uses_deprecated_subscribers = true
95
- end
96
-
97
- def uses_deprecated_subscribers?
98
- @uses_deprecated_subscribers || false
99
- end
100
- end
101
-
102
- protected
103
-
104
- def visit_model
105
- Ahoy.visit_model || ::Visit
106
- end
107
-
108
- def event_model
109
- ::Ahoy::Event
110
- end
111
- end
112
- end
113
- end
@@ -1,88 +0,0 @@
1
- module Ahoy
2
- module Stores
3
- class BaseStore
4
- def initialize(options)
5
- @options = options
6
- end
7
-
8
- def track_visit(options)
9
- end
10
-
11
- def track_event(name, properties, options)
12
- end
13
-
14
- def visit
15
- end
16
-
17
- def authenticate(user)
18
- @user = user
19
- if visit && visit.respond_to?(:user) && !visit.user
20
- begin
21
- visit.user = user
22
- visit.save!
23
- rescue ActiveRecord::AssociationTypeMismatch
24
- # do nothing
25
- end
26
- end
27
- end
28
-
29
- def report_exception(e)
30
- raise e
31
- end
32
-
33
- def user
34
- @user ||= (controller.respond_to?(:current_user) && controller.current_user) || (controller.respond_to?(:current_resource_owner, true) && controller.send(:current_resource_owner)) || nil
35
- end
36
-
37
- def exclude?
38
- bot?
39
- end
40
-
41
- def generate_id
42
- SecureRandom.uuid
43
- end
44
-
45
- protected
46
-
47
- def bot?
48
- @bot ||= request ? Browser.new(request.user_agent).bot? : false
49
- end
50
-
51
- def request
52
- @request ||= @options[:request] || controller.try(:request)
53
- end
54
-
55
- def controller
56
- @controller ||= @options[:controller]
57
- end
58
-
59
- def ahoy
60
- @ahoy ||= @options[:ahoy]
61
- end
62
-
63
- def visit_properties
64
- ahoy.visit_properties
65
- end
66
-
67
- def set_visit_properties(visit)
68
- keys = visit_properties.keys
69
- keys.each do |key|
70
- visit.send(:"#{key}=", visit_properties[key]) if visit.respond_to?(:"#{key}=") && visit_properties[key]
71
- end
72
- end
73
-
74
- def geocode(visit)
75
- if Ahoy.geocode == :async
76
- Ahoy::GeocodeJob.set(queue: Ahoy.job_queue).perform_later(visit)
77
- end
78
- end
79
-
80
- def unique_exception_classes
81
- classes = []
82
- classes << ActiveRecord::RecordNotUnique if defined?(ActiveRecord::RecordNotUnique)
83
- classes << PG::UniqueViolation if defined?(PG::UniqueViolation)
84
- classes
85
- end
86
- end
87
- end
88
- end