ahoy_matey 4.0.3 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8291f7d5566895e2973be22a9dd2e4f3cd43449d1289a5d176b38eed17c9a81d
4
- data.tar.gz: a2551e19aefafbf339f77dea16b3544ce2d3f6084372523029c5ac2b86a13260
3
+ metadata.gz: e92b695b80a72d0e60e30f459c8b8e8a72df4d33652aafab25cd6798c3b39b60
4
+ data.tar.gz: e1654e31ba9add55b36290bd0e8da150abd5bd358662e11a34120bd074ef2ed3
5
5
  SHA512:
6
- metadata.gz: c29a7d295c896e8191b213f877668910f6ca751d50750e1262ac41b2bedf971ec2342dc73dc9ac27d8f4e25306e83474162687bfbef8f44ea9887287adc89f57
7
- data.tar.gz: 901f80e0995a39f63b6d4ae4f36c8a8c1b064f9820b7783d495775152c81d7310aa40efa2286398fbdf2e7108dd80bb9a6415acf44e62e5a414f71c1d0a5975c
6
+ metadata.gz: 34654baa122484f10b8cb0a169fafae0018aa06d31b341ac43c5d202ef7314f96bb17cb87247f04c47b87173d055d0a61a211792b4a6958266c00e2ed1135799
7
+ data.tar.gz: 35d424209a166bf189b87b4dc9c37a3106b522ae6ce9614debc8a8ce550a416de7bb78ab055b6e433ca46a0e207357ccd57078dd2ddbcece7ccf3dfe3d43e568
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ## 4.2.0 (2023-02-07)
2
+
3
+ - Added primary key type to generated migration
4
+ - Updated Ahoy.js to 0.4.1
5
+
6
+ ## 4.1.0 (2022-06-12)
7
+
8
+ - Ensure `exclude_method` is only called once per request
9
+ - Fixed error with Mongoid when `Mongoid.raise_not_found_error` is `true`
10
+ - Fixed association for Mongoid
11
+
1
12
  ## 4.0.3 (2022-01-15)
2
13
 
3
14
  - Support for `importmap-rails` is no longer experimental
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014-2021 Andrew Kane
1
+ Copyright (c) 2014-2023 Andrew Kane
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -4,8 +4,6 @@
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
-
9
7
  :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
10
8
 
11
9
  :tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
@@ -17,7 +15,7 @@ Track visits and events in Ruby, JavaScript, and native apps. Data is stored in
17
15
  Add this line to your application’s Gemfile:
18
16
 
19
17
  ```ruby
20
- gem 'ahoy_matey'
18
+ gem "ahoy_matey"
21
19
  ```
22
20
 
23
21
  And run:
@@ -197,9 +195,9 @@ Order.joins(:ahoy_visit).group("device_type").count
197
195
  Here’s what the migration to add the `ahoy_visit_id` column should look like:
198
196
 
199
197
  ```ruby
200
- class AddVisitIdToOrders < ActiveRecord::Migration[6.1]
198
+ class AddAhoyVisitToOrders < ActiveRecord::Migration[7.0]
201
199
  def change
202
- add_column :orders, :ahoy_visit_id, :bigint
200
+ add_reference :orders, :ahoy_visit
203
201
  end
204
202
  end
205
203
  ```
@@ -361,7 +359,7 @@ Ahoy uses [Geocoder](https://github.com/alexreisner/geocoder) for geocoding. We
361
359
  To enable geocoding, add this line to your application’s Gemfile:
362
360
 
363
361
  ```ruby
364
- gem 'geocoder'
362
+ gem "geocoder"
365
363
  ```
366
364
 
367
365
  And update `config/initializers/ahoy.rb`:
@@ -381,7 +379,7 @@ Ahoy.job_queue = :low_priority
381
379
  For privacy and performance, we recommend geocoding locally. Add this line to your application’s Gemfile:
382
380
 
383
381
  ```ruby
384
- gem 'maxminddb'
382
+ gem "maxminddb"
385
383
  ```
386
384
 
387
385
  For city-level geocoding, download the [GeoLite2 City database](https://dev.maxmind.com/geoip/geoip2/geolite2/) and create `config/initializers/geocoder.rb` with:
@@ -500,6 +498,8 @@ Previously set cookies are automatically deleted. If you use JavaScript tracking
500
498
  ahoy.configure({cookies: false});
501
499
  ```
502
500
 
501
+ Note: With anonymity sets, visits no longer expire after 4 hours of inactivity. A new visit is only created when the IP mask or user agent changes (for instance, when a user updates their browser). There are plans to address this in the next major version.
502
+
503
503
  ## Data Retention
504
504
 
505
505
  Data should only be retained for as long as it’s needed. Delete older data with:
@@ -784,7 +784,7 @@ There are two notable changes to geocoding:
784
784
  2. The `geocoder` gem is now an optional dependency. To use geocoding, add it to your Gemfile:
785
785
 
786
786
  ```ruby
787
- gem 'geocoder'
787
+ gem "geocoder"
788
788
  ```
789
789
 
790
790
  Also, check out the [upgrade notes](https://github.com/ankane/ahoy.js#upgrading) for Ahoy.js.
@@ -811,20 +811,10 @@ bundle install
811
811
  bundle exec rake test
812
812
  ```
813
813
 
814
- To test query methods, use:
814
+ To test different adapters, use:
815
815
 
816
816
  ```sh
817
- # Postgres
818
- createdb ahoy_test
819
- bundle exec rake test:query_methods:postgresql
820
-
821
- # SQLite
822
- bundle exec rake test:query_methods:sqlite
823
-
824
- # MySQL and MariaDB
825
- mysqladmin create ahoy_test
826
- bundle exec rake test:query_methods:mysql
827
-
828
- # MongoDB
829
- bundle exec rake test:query_methods:mongoid
817
+ ADAPTER=postgresql bundle exec rake test
818
+ ADAPTER=mysql2 bundle exec rake test
819
+ ADAPTER=mongoid bundle exec rake test
830
820
  ```
@@ -1,4 +1,5 @@
1
1
  # for smooth update from Ahoy 1 -> 2
2
+ # TODO remove in 5.0
2
3
  module Ahoy
3
4
  class GeocodeJob < ActiveJob::Base
4
5
  queue_as { Ahoy.job_queue }
@@ -53,7 +53,12 @@ module Ahoy
53
53
 
54
54
  def visit
55
55
  unless defined?(@visit)
56
- @visit = visit_model.find_by(visit_token: ahoy.visit_token) if ahoy.visit_token
56
+ if defined?(Mongoid::Document) && visit_model < Mongoid::Document
57
+ # find_by raises error by default when not found
58
+ @visit = visit_model.where(visit_token: ahoy.visit_token).first if ahoy.visit_token
59
+ else
60
+ @visit = visit_model.find_by(visit_token: ahoy.visit_token) if ahoy.visit_token
61
+ end
57
62
  end
58
63
  @visit
59
64
  end
data/lib/ahoy/tracker.rb CHANGED
@@ -185,7 +185,10 @@ module Ahoy
185
185
  end
186
186
 
187
187
  def exclude?
188
- @store.exclude?
188
+ unless defined?(@exclude)
189
+ @exclude = @store.exclude?
190
+ end
191
+ @exclude
189
192
  end
190
193
 
191
194
  def report_exception(e)
data/lib/ahoy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Ahoy
2
- VERSION = "4.0.3"
2
+ VERSION = "4.2.0"
3
3
  end
data/lib/ahoy.rb CHANGED
@@ -7,18 +7,18 @@ require "active_support/core_ext"
7
7
  require "safely/core"
8
8
 
9
9
  # modules
10
- require "ahoy/utils"
11
- require "ahoy/base_store"
12
- require "ahoy/controller"
13
- require "ahoy/database_store"
14
- require "ahoy/helper"
15
- require "ahoy/model"
16
- require "ahoy/query_methods"
17
- require "ahoy/tracker"
18
- require "ahoy/version"
19
- require "ahoy/visit_properties"
20
-
21
- require "ahoy/engine" if defined?(Rails)
10
+ require_relative "ahoy/utils"
11
+ require_relative "ahoy/base_store"
12
+ require_relative "ahoy/controller"
13
+ require_relative "ahoy/database_store"
14
+ require_relative "ahoy/helper"
15
+ require_relative "ahoy/model"
16
+ require_relative "ahoy/query_methods"
17
+ require_relative "ahoy/tracker"
18
+ require_relative "ahoy/version"
19
+ require_relative "ahoy/visit_properties"
20
+
21
+ require_relative "ahoy/engine" if defined?(Rails)
22
22
 
23
23
  module Ahoy
24
24
  mattr_accessor :visit_duration
@@ -126,7 +126,6 @@ ActiveSupport.on_load(:action_view) do
126
126
  include Ahoy::Helper
127
127
  end
128
128
 
129
- # Mongoid
130
129
  ActiveSupport.on_load(:mongoid) do
131
130
  Mongoid::Document::ClassMethods.include(Ahoy::Model)
132
131
  end
data/lib/ahoy_matey.rb CHANGED
@@ -1 +1 @@
1
- require "ahoy"
1
+ require_relative "ahoy"
@@ -1,3 +1,4 @@
1
+ require "rails/generators"
1
2
  require "rails/generators/active_record"
2
3
 
3
4
  module Ahoy
@@ -49,6 +50,18 @@ module Ahoy
49
50
  def migration_version
50
51
  "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
51
52
  end
53
+
54
+ def primary_key_type
55
+ ", id: :#{key_type}" if key_type
56
+ end
57
+
58
+ def foreign_key_type
59
+ ", type: :#{key_type}" if key_type
60
+ end
61
+
62
+ def key_type
63
+ Rails.configuration.generators.options.dig(:active_record, :primary_key_type)
64
+ end
52
65
  end
53
66
  end
54
67
  end
@@ -1,6 +1,6 @@
1
1
  class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
2
2
  def change
3
- create_table :ahoy_visits do |t|
3
+ create_table :ahoy_visits<%= primary_key_type %> do |t|
4
4
  t.string :visit_token
5
5
  t.string :visitor_token
6
6
 
@@ -8,7 +8,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version
8
8
  # simply remove any you don't want
9
9
 
10
10
  # user
11
- t.references :user
11
+ t.references :user<%= foreign_key_type %>
12
12
 
13
13
  # standard
14
14
  t.string :ip
@@ -46,9 +46,9 @@ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version
46
46
 
47
47
  add_index :ahoy_visits, :visit_token, unique: true
48
48
 
49
- create_table :ahoy_events do |t|
50
- t.references :visit
51
- t.references :user
49
+ create_table :ahoy_events<%= primary_key_type %> do |t|
50
+ t.references :visit<%= foreign_key_type %>
51
+ t.references :user<%= foreign_key_type %>
52
52
 
53
53
  t.string :name
54
54
  t.<%= properties_type %> :properties
@@ -2,7 +2,7 @@ class Ahoy::Event
2
2
  include Mongoid::Document
3
3
 
4
4
  # associations
5
- belongs_to :visit, index: true
5
+ belongs_to :visit, class_name: "Ahoy::Visit", index: true
6
6
  belongs_to :user, index: true, optional: true
7
7
 
8
8
  # fields
@@ -1,16 +1,15 @@
1
1
  /*!
2
- * Ahoy.js
2
+ * Ahoy.js v0.4.1
3
3
  * Simple, powerful JavaScript analytics
4
4
  * https://github.com/ankane/ahoy.js
5
- * v0.4.0
6
5
  * MIT License
7
6
  */
8
7
 
9
8
  (function (global, factory) {
10
9
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
11
10
  typeof define === 'function' && define.amd ? define(factory) :
12
- (global = global || self, global.ahoy = factory());
13
- }(this, (function () { 'use strict';
11
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.ahoy = factory());
12
+ })(this, (function () { 'use strict';
14
13
 
15
14
  // https://www.quirksmode.org/js/cookies.html
16
15
 
@@ -67,7 +66,7 @@
67
66
 
68
67
  ahoy.configure = function (options) {
69
68
  for (var key in options) {
70
- if (options.hasOwnProperty(key)) {
69
+ if (Object.prototype.hasOwnProperty.call(options, key)) {
71
70
  config[key] = options[key];
72
71
  }
73
72
  }
@@ -102,7 +101,7 @@
102
101
  function serialize(object) {
103
102
  var data = new FormData();
104
103
  for (var key in object) {
105
- if (object.hasOwnProperty(key)) {
104
+ if (Object.prototype.hasOwnProperty.call(object, key)) {
106
105
  data.append(key, object[key]);
107
106
  }
108
107
  }
@@ -170,6 +169,9 @@
170
169
  document.addEventListener(eventName, function (e) {
171
170
  var matchedElement = matchesSelector(e.target, selector);
172
171
  if (matchedElement) {
172
+ var skip = getClosest(matchedElement, "data-ahoy-skip");
173
+ if (skip !== null && skip !== "false") { return; }
174
+
173
175
  callback.call(matchedElement, e);
174
176
  }
175
177
  });
@@ -186,8 +188,9 @@
186
188
 
187
189
  // https://stackoverflow.com/a/2117523/1177228
188
190
  function generateId() {
189
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
190
- var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
191
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
192
+ var r = Math.random() * 16 | 0;
193
+ var v = c === 'x' ? r : (r & 0x3 | 0x8);
191
194
  return v.toString(16);
192
195
  });
193
196
  }
@@ -237,11 +240,11 @@
237
240
  xhr.withCredentials = config.withCredentials;
238
241
  xhr.setRequestHeader("Content-Type", "application/json");
239
242
  for (var header in config.headers) {
240
- if (config.headers.hasOwnProperty(header)) {
243
+ if (Object.prototype.hasOwnProperty.call(config.headers, header)) {
241
244
  xhr.setRequestHeader(header, config.headers[header]);
242
245
  }
243
246
  }
244
- xhr.onload = function() {
247
+ xhr.onload = function () {
245
248
  if (xhr.status === 200) {
246
249
  success();
247
250
  }
@@ -266,11 +269,11 @@
266
269
  }
267
270
 
268
271
  function trackEvent(event) {
269
- ahoy.ready( function () {
270
- sendRequest(eventsUrl(), eventData(event), function() {
272
+ ahoy.ready(function () {
273
+ sendRequest(eventsUrl(), eventData(event), function () {
271
274
  // remove from queue
272
275
  for (var i = 0; i < eventQueue.length; i++) {
273
- if (eventQueue[i].id == event.id) {
276
+ if (eventQueue[i].id === event.id) {
274
277
  eventQueue.splice(i, 1);
275
278
  break;
276
279
  }
@@ -281,7 +284,7 @@
281
284
  }
282
285
 
283
286
  function trackEventNow(event) {
284
- ahoy.ready( function () {
287
+ ahoy.ready(function () {
285
288
  var data = eventData(event);
286
289
  var param = csrfParam();
287
290
  var token = csrfToken();
@@ -303,7 +306,7 @@
303
306
 
304
307
  function cleanObject(obj) {
305
308
  for (var key in obj) {
306
- if (obj.hasOwnProperty(key)) {
309
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
307
310
  if (obj[key] === null) {
308
311
  delete obj[key];
309
312
  }
@@ -318,14 +321,14 @@
318
321
  id: presence(this.id),
319
322
  "class": presence(this.className),
320
323
  page: page(),
321
- section: getClosestSection(this)
324
+ section: getClosest(this, "data-section")
322
325
  });
323
326
  }
324
327
 
325
- function getClosestSection(element) {
326
- for ( ; element && element !== document; element = element.parentNode) {
327
- if (element.hasAttribute('data-section')) {
328
- return element.getAttribute('data-section');
328
+ function getClosest(element, attribute) {
329
+ for (; element && element !== document; element = element.parentNode) {
330
+ if (element.hasAttribute(attribute)) {
331
+ return element.getAttribute(attribute);
329
332
  }
330
333
  }
331
334
 
@@ -377,7 +380,7 @@
377
380
  }
378
381
 
379
382
  for (var key in config.visitParams) {
380
- if (config.visitParams.hasOwnProperty(key)) {
383
+ if (Object.prototype.hasOwnProperty.call(config.visitParam, key)) {
381
384
  data[key] = config.visitParams[key];
382
385
  }
383
386
  }
@@ -431,12 +434,12 @@
431
434
  js: true
432
435
  };
433
436
 
434
- ahoy.ready( function () {
437
+ ahoy.ready(function () {
435
438
  if (config.cookies && !ahoy.getVisitId()) {
436
439
  createVisit();
437
440
  }
438
441
 
439
- ahoy.ready( function () {
442
+ ahoy.ready(function () {
440
443
  log(event);
441
444
 
442
445
  event.visit_token = ahoy.getVisitId();
@@ -449,7 +452,7 @@
449
452
  saveEventQueue();
450
453
 
451
454
  // wait in case navigating to reduce duplicate events
452
- setTimeout( function () {
455
+ setTimeout(function () {
453
456
  trackEvent(event);
454
457
  }, 1000);
455
458
  }
@@ -467,8 +470,8 @@
467
470
  };
468
471
 
469
472
  if (additionalProperties) {
470
- for(var propName in additionalProperties) {
471
- if (additionalProperties.hasOwnProperty(propName)) {
473
+ for (var propName in additionalProperties) {
474
+ if (Object.prototype.hasOwnProperty.call(additionalProperties, propName)) {
472
475
  properties[propName] = additionalProperties[propName];
473
476
  }
474
477
  }
@@ -482,7 +485,7 @@
482
485
  }
483
486
  onEvent("click", selector, function (e) {
484
487
  var properties = eventProperties.call(this, e);
485
- properties.text = properties.tag == "input" ? this.value : (this.textContent || this.innerText || this.innerHTML).replace(/[\s\r\n]+/g, " ").trim();
488
+ properties.text = properties.tag === "input" ? this.value : (this.textContent || this.innerText || this.innerHTML).replace(/[\s\r\n]+/g, " ").trim();
486
489
  properties.href = this.href;
487
490
  ahoy.track("$click", properties);
488
491
  });
@@ -526,7 +529,7 @@
526
529
  ahoy.start = function () {};
527
530
  };
528
531
 
529
- documentReady(function() {
532
+ documentReady(function () {
530
533
  if (config.startOnReady) {
531
534
  ahoy.start();
532
535
  }
@@ -534,4 +537,4 @@
534
537
 
535
538
  return ahoy;
536
539
 
537
- })));
540
+ }));
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: 4.0.3
4
+ version: 4.2.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: 2022-01-15 00:00:00.000000000 Z
11
+ date: 2023-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -113,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
113
  - !ruby/object:Gem::Version
114
114
  version: '0'
115
115
  requirements: []
116
- rubygems_version: 3.3.3
116
+ rubygems_version: 3.4.6
117
117
  signing_key:
118
118
  specification_version: 4
119
119
  summary: Simple, powerful, first-party analytics for Rails