ahoy_matey 4.0.3 → 4.2.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: 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