ahoy_matey 3.3.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d09c2a1f7783c94ad857652adfbe8150deb702f9162daf28c2bf9c11454f4277
4
- data.tar.gz: 0e0a9779762c9ad912ba6d8866f85783c00aa0a96f3c53a4b6b803a3cdf41af2
3
+ metadata.gz: 1fb8aecda5242614f518d06dbdc9449305f0ed30677d667e01eb1edefc627bc7
4
+ data.tar.gz: 8f52fbe0bab0a0ac1c5722b06f342add3d31c0c441230b77f03ae566e07f746b
5
5
  SHA512:
6
- metadata.gz: e479ea5345820038c0a4fe4296504781614b53c6cfef5a79856c51073f768dc64082d494ba64d1e03ec41a346832c320565de63c5953f3bdf91e6e2697a1b7c9
7
- data.tar.gz: 5fc7c4e73835b1ffc7be2d9c125894baccf204b7e7785784887574d80b8d7581d10e1ced1c0562cd7804ad66a22ce05df64ef6b302a981faa567569b618c8557
6
+ metadata.gz: '059927d7fe2344882860ae81ff23e142a09ed955da818da8d3e679b03173b39e64ffc611e4e682a912901678cd9b790b461805f788c423cd2b4331c2a340c226'
7
+ data.tar.gz: f2d53c35500ee4d30485cfbf6c5d444cbf03c50cec4762783a972411343e19b8baf53b61286cc4aa78bbbe98a69df21da701989422263780447341fdce756db0
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 4.0.0 (2021-08-14)
2
+
3
+ - Disabled geocoding by default
4
+ - Made the `geocoder` gem an optional dependency
5
+ - Updated Ahoy.js to 0.4.0
6
+ - Updated API to return 400 status code when missing required parameters
7
+ - Dropped support for Ruby < 2.6 and Rails < 5.2
8
+
1
9
  ## 3.3.0 (2021-08-13)
2
10
 
3
11
  - Added `country_code` to geocoding
data/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  Track visits and events in Ruby, JavaScript, and native apps. Data is stored in your database by default, and you can customize it for any data store as you grow.
6
6
 
7
+ **Ahoy 4.0 was recently released** - see [how to upgrade](#upgrading)
8
+
7
9
  :postbox: Check out [Ahoy Email](https://github.com/ankane/ahoy_email) for emails and [Field Test](https://github.com/ankane/field_test) for A/B testing
8
10
 
9
11
  :tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
@@ -143,12 +145,6 @@ end
143
145
  ahoy.track("Viewed book", {title: "The World is Flat"});
144
146
  ```
145
147
 
146
- Track events automatically with:
147
-
148
- ```javascript
149
- ahoy.trackAll();
150
- ```
151
-
152
148
  See [Ahoy.js](https://github.com/ankane/ahoy.js) for a complete list of features.
153
149
 
154
150
  #### Native Apps
@@ -350,7 +346,13 @@ Safely.report_exception_method = ->(e) { Rollbar.error(e) }
350
346
 
351
347
  Ahoy uses [Geocoder](https://github.com/alexreisner/geocoder) for geocoding. We recommend configuring [local geocoding](#local-geocoding) or [load balancer geocoding](#load-balancer-geocoding) so IP addresses are not sent to a 3rd party service. If you do use a 3rd party service and adhere to GDPR, be sure to add it to your subprocessor list. If Ahoy is configured to [mask IPs](#ip-masking), the masked IP is used (this can reduce accuracy but is better for privacy).
352
348
 
353
- To enable geocoding, update `config/initializers/ahoy.rb`:
349
+ To enable geocoding, add this line to your application’s Gemfile:
350
+
351
+ ```ruby
352
+ gem 'geocoder'
353
+ ```
354
+
355
+ And update `config/initializers/ahoy.rb`:
354
356
 
355
357
  ```ruby
356
358
  Ahoy.geocode = true
@@ -743,62 +745,19 @@ Send a `POST` request to `/ahoy/events` with `Content-Type: application/json` an
743
745
 
744
746
  ## Upgrading
745
747
 
746
- ### 3.0
747
-
748
- If you installed Ahoy before 2.1 and want to keep legacy user agent parsing and bot detection, add to your Gemfile:
749
-
750
- ```ruby
751
- gem "browser", "~> 2.0"
752
- gem "user_agent_parser"
753
- ```
754
-
755
- And add to `config/initializers/ahoy.rb`:
756
-
757
- ```ruby
758
- Ahoy.user_agent_parser = :legacy
759
- ```
760
-
761
- ### 2.2
762
-
763
- Ahoy now ships with better bot detection if you use Device Detector. This should be more accurate but can significantly reduce the number of visits recorded. For existing installs, it’s opt-in to start. To use it, add to `config/initializers/ahoy.rb`:
764
-
765
- ```ruby
766
- Ahoy.bot_detection_version = 2
767
- ```
768
-
769
- ### 2.1
770
-
771
- Ahoy recommends [Device Detector](https://github.com/podigee/device_detector) for user agent parsing and makes it the default for new installations. To switch, add to `config/initializers/ahoy.rb`:
748
+ ### 4.0
772
749
 
773
- ```ruby
774
- Ahoy.user_agent_parser = :device_detector
775
- ```
750
+ There are two notable changes to geocoding:
776
751
 
777
- Backfill existing records with:
778
-
779
- ```ruby
780
- Ahoy::Visit.find_each do |visit|
781
- client = DeviceDetector.new(visit.user_agent)
782
- device_type =
783
- case client.device_type
784
- when "smartphone"
785
- "Mobile"
786
- when "tv"
787
- "TV"
788
- else
789
- client.device_type.try(:titleize)
790
- end
752
+ 1. Geocoding is now disabled by default (this was already the case for new installations with 3.2.0+). Check out the instructions for [how to enable it](#geocoding).
791
753
 
792
- visit.browser = client.name
793
- visit.os = client.os_name
794
- visit.device_type = device_type
795
- visit.save(validate: false) if visit.changed?
796
- end
797
- ```
754
+ 2. The `geocoder` gem is now an optional dependency. To use geocoding, add it to your Gemfile:
798
755
 
799
- ### 2.0
756
+ ```ruby
757
+ gem 'geocoder'
758
+ ```
800
759
 
801
- See the [upgrade guide](docs/Ahoy-2-Upgrade.md)
760
+ Also, check out the [upgrade notes](https://github.com/ankane/ahoy.js#upgrading) for Ahoy.js.
802
761
 
803
762
  ## History
804
763
 
@@ -5,19 +5,27 @@ module Ahoy
5
5
  skip_after_action(*filters, raise: false)
6
6
  skip_around_action(*filters, raise: false)
7
7
 
8
- before_action :verify_request_size
9
- before_action :renew_cookies
10
-
11
8
  if respond_to?(:protect_from_forgery)
12
9
  protect_from_forgery with: :null_session, if: -> { Ahoy.protect_from_forgery }
13
10
  end
14
11
 
12
+ before_action :verify_request_size
13
+ before_action :check_params
14
+ before_action :renew_cookies
15
+
15
16
  protected
16
17
 
17
18
  def ahoy
18
19
  @ahoy ||= Ahoy::Tracker.new(controller: self, api: true)
19
20
  end
20
21
 
22
+ def check_params
23
+ if ahoy.send(:missing_params?)
24
+ logger.info "[ahoy] Missing required parameters"
25
+ render plain: "Missing required parameters\n", status: :bad_request
26
+ end
27
+ end
28
+
21
29
  # set proper ttl if cookie generated from JavaScript
22
30
  # approach is not perfect, as user must reload the page
23
31
  # for new cookie settings to take effect
@@ -28,7 +36,7 @@ module Ahoy
28
36
  def verify_request_size
29
37
  if request.content_length > Ahoy.max_content_length
30
38
  logger.info "[ahoy] Payload too large"
31
- render plain: "Payload too large\n", status: 413
39
+ render plain: "Payload too large\n", status: :payload_too_large
32
40
  end
33
41
  end
34
42
  end
@@ -6,6 +6,8 @@ module Ahoy
6
6
  location =
7
7
  begin
8
8
  Geocoder.search(ip).first
9
+ rescue NameError
10
+ raise "Add the geocoder gem to your Gemfile to use geocoding"
9
11
  rescue => e
10
12
  Ahoy.log "Geocode error: #{e.class.name}: #{e.message}"
11
13
  nil
data/lib/ahoy.rb CHANGED
@@ -4,7 +4,6 @@ require "ipaddr"
4
4
  # dependencies
5
5
  require "active_support"
6
6
  require "active_support/core_ext"
7
- require "geocoder"
8
7
  require "safely/core"
9
8
 
10
9
  # modules
@@ -44,7 +43,7 @@ module Ahoy
44
43
  self.quiet = true
45
44
 
46
45
  mattr_accessor :geocode
47
- self.geocode = true
46
+ self.geocode = false
48
47
 
49
48
  mattr_accessor :max_content_length
50
49
  self.max_content_length = 8192
@@ -128,10 +127,6 @@ ActiveSupport.on_load(:action_view) do
128
127
  end
129
128
 
130
129
  # Mongoid
131
- # TODO use
132
- # ActiveSupport.on_load(:mongoid) do
133
- # Mongoid::Document::ClassMethods.include(Ahoy::Model)
134
- # end
135
- if defined?(ActiveModel)
136
- ActiveModel::Callbacks.include(Ahoy::Model)
130
+ ActiveSupport.on_load(:mongoid) do
131
+ Mongoid::Document::ClassMethods.include(Ahoy::Model)
137
132
  end
@@ -19,35 +19,21 @@ module Ahoy
19
19
  when "mongoid"
20
20
  relation = where(Hash[properties.map { |k, v| ["properties.#{k}", v] }])
21
21
  when /mysql/
22
- if column_type == :json
23
- properties.each do |k, v|
24
- if v.nil?
25
- v = "null"
26
- elsif v == true
27
- v = "true"
28
- end
29
-
30
- relation = relation.where("JSON_UNQUOTE(properties -> ?) = ?", "$.#{k}", v.as_json)
31
- end
32
- else
33
- properties.each do |k, v|
34
- # TODO cast to json instead
35
- relation = relation.where("properties REGEXP ?", "[{,]#{{k.to_s => v}.to_json.sub(/\A\{/, "").sub(/\}\z/, "").gsub("+", "\\\\+")}[,}]")
22
+ column = column_type == :json || connection.try(:mariadb?) ? "properties" : "CAST(properties AS JSON)"
23
+ properties.each do |k, v|
24
+ if v.nil?
25
+ v = "null"
26
+ elsif v == true
27
+ v = "true"
36
28
  end
29
+
30
+ relation = relation.where("JSON_UNQUOTE(JSON_EXTRACT(#{column}, ?)) = ?", "$.#{k}", v.as_json)
37
31
  end
38
32
  when /postgres|postgis/
39
- if column_type == :jsonb
33
+ case column_type
34
+ when :jsonb
40
35
  relation = relation.where("properties @> ?", properties.to_json)
41
- elsif column_type == :json
42
- properties.each do |k, v|
43
- relation =
44
- if v.nil?
45
- relation.where("properties ->> ? IS NULL", k.to_s)
46
- else
47
- relation.where("properties ->> ? = ?", k.to_s, v.as_json.to_s)
48
- end
49
- end
50
- elsif column_type == :hstore
36
+ when :hstore
51
37
  properties.each do |k, v|
52
38
  relation =
53
39
  if v.nil?
@@ -57,10 +43,7 @@ module Ahoy
57
43
  end
58
44
  end
59
45
  else
60
- properties.each do |k, v|
61
- # TODO cast to jsonb instead
62
- relation = relation.where("properties SIMILAR TO ?", "%[{,]#{{k.to_s => v}.to_json.sub(/\A\{/, "").sub(/\}\z/, "").gsub("+", "\\\\+")}[,}]%")
63
- end
46
+ relation = relation.where("properties::jsonb @> ?", properties.to_json)
64
47
  end
65
48
  else
66
49
  raise "Adapter not supported: #{adapter_name}"
@@ -84,17 +67,10 @@ module Ahoy
84
67
  when "mongoid"
85
68
  raise "Adapter not supported: #{adapter_name}"
86
69
  when /mysql/
87
- if connection.try(:mariadb?)
88
- props.each do |prop|
89
- quoted_prop = connection.quote("$.#{prop}")
90
- relation = relation.group("JSON_UNQUOTE(JSON_EXTRACT(properties, #{quoted_prop}))")
91
- end
92
- else
93
- column = column_type == :json ? "properties" : "CAST(properties AS JSON)"
94
- props.each do |prop|
95
- quoted_prop = connection.quote("$.#{prop}")
96
- relation = relation.group("JSON_UNQUOTE(JSON_EXTRACT(#{column}, #{quoted_prop}))")
97
- end
70
+ column = column_type == :json || connection.try(:mariadb?) ? "properties" : "CAST(properties AS JSON)"
71
+ props.each do |prop|
72
+ quoted_prop = connection.quote("$.#{prop}")
73
+ relation = relation.group("JSON_UNQUOTE(JSON_EXTRACT(#{column}, #{quoted_prop}))")
98
74
  end
99
75
  when /postgres|postgis/
100
76
  # convert to jsonb to fix
data/lib/ahoy/tracker.rb CHANGED
@@ -19,8 +19,6 @@ module Ahoy
19
19
  def track(name, properties = {}, options = {})
20
20
  if exclude?
21
21
  debug "Event excluded"
22
- elsif missing_params?
23
- debug "Missing required parameters"
24
22
  else
25
23
  data = {
26
24
  visit_token: visit_token,
@@ -41,8 +39,6 @@ module Ahoy
41
39
  def track_visit(defer: false, started_at: nil)
42
40
  if exclude?
43
41
  debug "Visit excluded"
44
- elsif missing_params?
45
- debug "Missing required parameters"
46
42
  else
47
43
  if defer
48
44
  set_cookie("ahoy_track", true, nil, false)
@@ -155,6 +151,7 @@ module Ahoy
155
151
  @options[:api]
156
152
  end
157
153
 
154
+ # private, but used by API
158
155
  def missing_params?
159
156
  if Ahoy.cookies && api? && Ahoy.protect_from_forgery
160
157
  !(existing_visit_token && existing_visitor_token)
data/lib/ahoy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Ahoy
2
- VERSION = "3.3.0"
2
+ VERSION = "4.0.0"
3
3
  end
@@ -19,7 +19,7 @@ end
19
19
  # set to true for JavaScript tracking
20
20
  Ahoy.api = false
21
21
 
22
- # set to true for geocoding
23
- # we recommend configuring local geocoding first
22
+ # set to true for geocoding (and add the geocoder gem to your Gemfile)
23
+ # we recommend configuring local geocoding as well
24
24
  # see https://github.com/ankane/ahoy#geocoding
25
25
  Ahoy.geocode = false
@@ -4,7 +4,7 @@ end
4
4
  # set to true for JavaScript tracking
5
5
  Ahoy.api = false
6
6
 
7
- # set to true for geocoding
8
- # we recommend configuring local geocoding first
7
+ # set to true for geocoding (and add the geocoder gem to your Gemfile)
8
+ # we recommend configuring local geocoding as well
9
9
  # see https://github.com/ankane/ahoy#geocoding
10
10
  Ahoy.geocode = false
@@ -2,7 +2,7 @@
2
2
  * Ahoy.js
3
3
  * Simple, powerful JavaScript analytics
4
4
  * https://github.com/ankane/ahoy.js
5
- * v0.3.9
5
+ * v0.4.0
6
6
  * MIT License
7
7
  */
8
8
 
@@ -26,7 +26,7 @@
26
26
  if (domain) {
27
27
  cookieDomain = "; domain=" + domain;
28
28
  }
29
- document.cookie = name + "=" + escape(value) + expires + cookieDomain + "; path=/";
29
+ document.cookie = name + "=" + escape(value) + expires + cookieDomain + "; path=/; samesite=lax";
30
30
  },
31
31
  get: function (name) {
32
32
  var i, c;
@@ -478,8 +478,7 @@
478
478
 
479
479
  ahoy.trackClicks = function (selector) {
480
480
  if (selector === undefined) {
481
- log("trackClicks will require a selector in 0.4.0");
482
- selector = "a, button, input[type=submit]";
481
+ throw new Error("Missing selector");
483
482
  }
484
483
  onEvent("click", selector, function (e) {
485
484
  var properties = eventProperties.call(this, e);
@@ -491,8 +490,7 @@
491
490
 
492
491
  ahoy.trackSubmits = function (selector) {
493
492
  if (selector === undefined) {
494
- log("trackSubmits will require a selector in 0.4.0");
495
- selector = "form";
493
+ throw new Error("Missing selector");
496
494
  }
497
495
  onEvent("submit", selector, function (e) {
498
496
  var properties = eventProperties.call(this, e);
@@ -501,10 +499,9 @@
501
499
  };
502
500
 
503
501
  ahoy.trackChanges = function (selector) {
502
+ log("trackChanges is deprecated and will be removed in 0.5.0");
504
503
  if (selector === undefined) {
505
- // put here instead of above to prevent message with trackAll
506
- log("trackChanges is deprecated and will be removed in 0.4.0");
507
- selector = "input, textarea, select";
504
+ throw new Error("Missing selector");
508
505
  }
509
506
  onEvent("change", selector, function (e) {
510
507
  var properties = eventProperties.call(this, e);
@@ -512,14 +509,6 @@
512
509
  });
513
510
  };
514
511
 
515
- ahoy.trackAll = function() {
516
- log("trackAll is deprecated and will be removed in 0.4.0");
517
- ahoy.trackView();
518
- ahoy.trackClicks("a, button, input[type=submit]");
519
- ahoy.trackSubmits("form");
520
- ahoy.trackChanges("input, textarea, select");
521
- };
522
-
523
512
  // push events from queue
524
513
  try {
525
514
  eventQueue = JSON.parse(getCookie("ahoy_events") || "[]");
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ahoy_matey
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-13 00:00:00.000000000 Z
11
+ date: 2021-08-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,28 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '5'
19
+ version: '5.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '5'
27
- - !ruby/object:Gem::Dependency
28
- name: geocoder
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 1.4.5
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: 1.4.5
26
+ version: '5.2'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: safely_block
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -120,7 +106,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
120
106
  requirements:
121
107
  - - ">="
122
108
  - !ruby/object:Gem::Version
123
- version: '2.4'
109
+ version: '2.6'
124
110
  required_rubygems_version: !ruby/object:Gem::Requirement
125
111
  requirements:
126
112
  - - ">="