ahoy_matey 5.1.0 → 5.5.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: f8f4afce5d34400d46473e74e607c7758ef18e93d719d476b83c54bca455bd76
4
- data.tar.gz: a64234a08867ad06f2084d4191c920f1ef12c0e290161e906303e8bcb744ead1
3
+ metadata.gz: 44d4e5d43d7fad25db6c27bc9bdfcefa0a4226be502b312a53aa6ad845f17d4d
4
+ data.tar.gz: 51798d1dd69a5f42f64dc18d3195d8ad80fe85568c78d839c470d708bfc6b18a
5
5
  SHA512:
6
- metadata.gz: 2ef86e6a698447417887b1dbbd5491ca4e073811cba9bcff2cfd1b42d42291ae39c96652d8dce8c006945264932d611ed80321c1ab8f3c02ed4e9f8f98e6bd64
7
- data.tar.gz: 1427722ca7b83c98e7db34eaf56fc86a46fd10c5d14659bb93e1e465cb7f24345cf15fc7125916d13512fa6e269c378cd5ca06e9c7b927ea62df967ee54762c3
6
+ metadata.gz: 78fceba09807aa17acf80c2c6d61d10b4eb9f8318780650f07714d0307864c417003084de42a6f856065e46cf977743aab0e5008f308924c741e4ecc786db3c7
7
+ data.tar.gz: e0603191b7a45e2835617b7b32c6d59aaa00f04dd641683a5fd0b8a4b841422819d51b124b93f9f0b6301dbbdc80a3dabdf1928fc21c0119930002a07c07d7cf
data/CHANGELOG.md CHANGED
@@ -1,3 +1,34 @@
1
+ ## 5.5.0 (2026-04-08)
2
+
3
+ - Fixed error with `Ahoy::Tracker` outside of requests
4
+ - Dropped support for Ruby < 3.3 and Rails < 7.2
5
+
6
+ ## 5.4.2 (2026-03-31)
7
+
8
+ - Fixed cookie deletion with `cookie_domain` and `cookie_options` options
9
+ - Updated Ahoy.js to 0.4.5
10
+
11
+ ## 5.4.1 (2025-09-30)
12
+
13
+ - Fixed deprecation warning with Rack 3.1+
14
+
15
+ ## 5.4.0 (2025-05-04)
16
+
17
+ - Dropped support for Ruby < 3.2 and Rails < 7.1
18
+
19
+ ## 5.3.0 (2025-02-01)
20
+
21
+ - Dropped support for Ruby < 3.1 and Rails < 7
22
+ - Dropped support for Mongoid < 8
23
+
24
+ ## 5.2.1 (2024-10-07)
25
+
26
+ - Fixed connection leasing for Active Record 7.2+
27
+
28
+ ## 5.2.0 (2024-09-04)
29
+
30
+ - Improved error handling for invalid API parameters
31
+
1
32
  ## 5.1.0 (2024-03-26)
2
33
 
3
34
  - Added support for Trilogy
@@ -354,3 +385,19 @@ Breaking changes
354
385
  ## 0.1.0 (2014-03-19)
355
386
 
356
387
  - First major release
388
+
389
+ ## 0.0.4 (2014-03-01)
390
+
391
+ - Added UTM parameters
392
+
393
+ ## 0.0.3 (2014-02-26)
394
+
395
+ - Renamed `ahoy_visit` method to `current_visit`
396
+
397
+ ## 0.0.2 (2014-02-26)
398
+
399
+ - Added `ahoy_visit` method to controllers
400
+
401
+ ## 0.0.1 (2014-02-26)
402
+
403
+ - First release
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014-2024 Andrew Kane
1
+ Copyright (c) 2014-2026 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 5.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)
@@ -48,7 +46,7 @@ And restart your web server.
48
46
 
49
47
  ### JavaScript
50
48
 
51
- For Importmap (Rails 7 default), add to `config/importmap.rb`:
49
+ For Importmap (Rails default), add to `config/importmap.rb`:
52
50
 
53
51
  ```ruby
54
52
  pin "ahoy", to: "ahoy.js"
@@ -60,13 +58,15 @@ And add to `app/javascript/application.js`:
60
58
  import "ahoy"
61
59
  ```
62
60
 
63
- For Webpacker (Rails 6 default), run:
61
+ For Bun, esbuild, rollup.js, or Webpack, run:
64
62
 
65
63
  ```sh
64
+ bun add ahoy.js
65
+ # or
66
66
  yarn add ahoy.js
67
67
  ```
68
68
 
69
- And add to `app/javascript/packs/application.js`:
69
+ And add to `app/javascript/application.js`:
70
70
 
71
71
  ```javascript
72
72
  import ahoy from "ahoy.js"
@@ -197,7 +197,7 @@ Order.joins(:ahoy_visit).group("device_type").count
197
197
  Here’s what the migration to add the `ahoy_visit_id` column should look like:
198
198
 
199
199
  ```ruby
200
- class AddAhoyVisitToOrders < ActiveRecord::Migration[7.1]
200
+ class AddAhoyVisitToOrders < ActiveRecord::Migration[8.1]
201
201
  def change
202
202
  add_reference :orders, :ahoy_visit
203
203
  end
@@ -490,7 +490,7 @@ Ahoy can switch from cookies to [anonymity sets](https://privacypatterns.org/pat
490
490
  Ahoy.cookies = :none
491
491
  ```
492
492
 
493
- Note: If Ahoy was installed before v5, [add an index](#50) before making this change.
493
+ Note: If Ahoy was installed before v5, [add an index](https://github.com/ankane/ahoy/tree/v5.0.0?tab=readme-ov-file#50) before making this change.
494
494
 
495
495
  Previously set cookies are automatically deleted. If you use JavaScript tracking, also set:
496
496
 
@@ -765,38 +765,12 @@ Send a `POST` request to `/ahoy/events` with `Content-Type: application/json` an
765
765
  "properties": {
766
766
  "item_id": 123
767
767
  },
768
- "time": "2018-01-01T00:00:00-07:00"
768
+ "time": "2025-01-01T00:00:00-07:00"
769
769
  }
770
770
  ]
771
771
  }
772
772
  ```
773
773
 
774
- ## Upgrading
775
-
776
- ### 5.0
777
-
778
- Visits now expire with anonymity sets. If using `Ahoy.cookies = false`, a new index is needed.
779
-
780
- For Active Record, create a migration with:
781
-
782
- ```ruby
783
- add_index :ahoy_visits, [:visitor_token, :started_at]
784
- ```
785
-
786
- For Mongoid, set:
787
-
788
- ```ruby
789
- class Ahoy::Visit
790
- index({visitor_token: 1, started_at: 1})
791
- end
792
- ```
793
-
794
- Create the index before upgrading, and set:
795
-
796
- ```ruby
797
- Ahoy.cookies = :none
798
- ```
799
-
800
774
  ## History
801
775
 
802
776
  View the [changelog](https://github.com/ankane/ahoy/blob/master/CHANGELOG.md)
@@ -36,7 +36,8 @@ module Ahoy
36
36
  def verify_request_size
37
37
  if request.content_length > Ahoy.max_content_length
38
38
  logger.info "[ahoy] Payload too large"
39
- render plain: "Payload too large\n", status: :payload_too_large
39
+ status = Rack::RELEASE.to_f >= 3.1 ? :content_too_large : :payload_too_large
40
+ render plain: "Payload too large\n", status: status
40
41
  end
41
42
  end
42
43
  end
@@ -17,12 +17,23 @@ module Ahoy
17
17
  begin
18
18
  ActiveSupport::JSON.decode(data)
19
19
  rescue ActiveSupport::JSON.parse_error
20
- # do nothing
20
+ # TODO change to nil in Ahoy 6
21
21
  []
22
22
  end
23
23
  end
24
24
 
25
- events.first(Ahoy.max_events_per_request).each do |event|
25
+ max_events_per_request = Ahoy.max_events_per_request
26
+
27
+ # check before creating any events
28
+ unless events.is_a?(Array) && events.first(max_events_per_request).all? { |v| v.is_a?(Hash) }
29
+ logger.info "[ahoy] Invalid parameters"
30
+ # :unprocessable_entity is probably more correct
31
+ # but keep consistent with missing parameters for now
32
+ render plain: "Invalid parameters\n", status: :bad_request
33
+ return
34
+ end
35
+
36
+ events.first(max_events_per_request).each do |event|
26
37
  time = Time.zone.parse(event["time"]) rescue nil
27
38
 
28
39
  # timestamp is deprecated
data/lib/ahoy/engine.rb CHANGED
@@ -29,7 +29,7 @@ module Ahoy
29
29
 
30
30
  # for importmap
31
31
  initializer "ahoy.importmap" do |app|
32
- if defined?(Importmap)
32
+ if app.config.respond_to?(:assets) && defined?(Importmap) && defined?(Sprockets)
33
33
  app.config.assets.precompile << "ahoy.js"
34
34
  end
35
35
  end
@@ -10,13 +10,13 @@ module Ahoy
10
10
  def where_props(properties)
11
11
  return all if properties.empty?
12
12
 
13
- adapter_name = respond_to?(:connection) ? connection.adapter_name.downcase : "mongoid"
13
+ adapter_name = respond_to?(:connection_db_config) ? connection_db_config.adapter.to_s : "mongoid"
14
14
  case adapter_name
15
15
  when "mongoid"
16
16
  where(properties.to_h { |k, v| ["properties.#{k}", v] })
17
- when /mysql|trilogy/
17
+ when /mysql|trilogy/i
18
18
  where("JSON_CONTAINS(properties, ?, '$') = 1", properties.to_json)
19
- when /postgres|postgis/
19
+ when /postg/i
20
20
  case columns_hash["properties"].type
21
21
  when :hstore
22
22
  properties.inject(all) do |relation, (k, v)|
@@ -31,7 +31,7 @@ module Ahoy
31
31
  else
32
32
  where("properties::jsonb @> ?", properties.to_json)
33
33
  end
34
- when /sqlite/
34
+ when /sqlite/i
35
35
  properties.inject(all) do |relation, (k, v)|
36
36
  if v.nil?
37
37
  relation.where("JSON_EXTRACT(properties, ?) IS NULL", "$.#{k}")
@@ -50,16 +50,16 @@ module Ahoy
50
50
  props.flatten!
51
51
 
52
52
  relation = all
53
- adapter_name = respond_to?(:connection) ? connection.adapter_name.downcase : "mongoid"
53
+ adapter_name = respond_to?(:connection_db_config) ? connection_db_config.adapter.to_s : "mongoid"
54
54
  case adapter_name
55
55
  when "mongoid"
56
56
  raise "Adapter not supported: #{adapter_name}"
57
- when /mysql|trilogy/
57
+ when /mysql|trilogy/i
58
58
  props.each do |prop|
59
- quoted_prop = connection.quote("$.#{prop}")
59
+ quoted_prop = connection_pool.with_connection { |c| c.quote("$.#{prop}") }
60
60
  relation = relation.group("JSON_UNQUOTE(JSON_EXTRACT(properties, #{quoted_prop}))")
61
61
  end
62
- when /postgres|postgis/
62
+ when /postg/i
63
63
  # convert to jsonb to fix
64
64
  # could not identify an equality operator for type json
65
65
  # and for text columns
@@ -67,12 +67,12 @@ module Ahoy
67
67
  cast = [:jsonb, :hstore].include?(column_type) ? "" : "::jsonb"
68
68
 
69
69
  props.each do |prop|
70
- quoted_prop = connection.quote(prop)
70
+ quoted_prop = connection_pool.with_connection { |c| c.quote(prop) }
71
71
  relation = relation.group("properties#{cast} -> #{quoted_prop}")
72
72
  end
73
- when /sqlite/
73
+ when /sqlite/i
74
74
  props.each do |prop|
75
- quoted_prop = connection.quote("$.#{prop}")
75
+ quoted_prop = connection_pool.with_connection { |c| c.quote("$.#{prop}") }
76
76
  relation = relation.group("JSON_EXTRACT(properties, #{quoted_prop})")
77
77
  end
78
78
  else
data/lib/ahoy/tracker.rb CHANGED
@@ -43,13 +43,13 @@ module Ahoy
43
43
  if defer
44
44
  set_cookie("ahoy_track", true, nil, false)
45
45
  else
46
- delete_cookie("ahoy_track")
46
+ delete_cookie("ahoy_track", false)
47
47
 
48
48
  data = {
49
49
  visit_token: visit_token,
50
50
  visitor_token: visitor_token,
51
51
  user_id: user.try(:id),
52
- started_at: trusted_time(started_at),
52
+ started_at: trusted_time(started_at)
53
53
  }.merge(visit_properties).select { |_, v| v }
54
54
 
55
55
  @store.track_visit(data)
@@ -142,7 +142,7 @@ module Ahoy
142
142
  def reset_visit
143
143
  delete_cookie("ahoy_visit")
144
144
  delete_cookie("ahoy_events")
145
- delete_cookie("ahoy_track")
145
+ delete_cookie("ahoy_track", false)
146
146
  end
147
147
 
148
148
  def exclude?
@@ -179,8 +179,15 @@ module Ahoy
179
179
  request.cookie_jar[name] = cookie
180
180
  end
181
181
 
182
- def delete_cookie(name)
183
- request.cookie_jar.delete(name) if request && request.cookie_jar[name]
182
+ def delete_cookie(name, use_domain = true)
183
+ if request && request.cookie_jar[name]
184
+ options = Ahoy.cookie_options.slice(:path)
185
+ if use_domain
186
+ domain = Ahoy.cookie_options[:domain] || Ahoy.cookie_domain
187
+ options[:domain] = domain if domain
188
+ end
189
+ request.cookie_jar.delete(name, **options)
190
+ end
184
191
  end
185
192
 
186
193
  def trusted_time(time = nil)
@@ -241,7 +248,7 @@ module Ahoy
241
248
  end
242
249
 
243
250
  def visitor_anonymity_set
244
- @visitor_anonymity_set ||= Digest::UUID.uuid_v5(UUID_NAMESPACE, ["visitor", Ahoy.mask_ip(request.remote_ip), request.user_agent].join("/"))
251
+ @visitor_anonymity_set ||= request && Digest::UUID.uuid_v5(UUID_NAMESPACE, ["visitor", Ahoy.mask_ip(request.remote_ip), request.user_agent].join("/"))
245
252
  end
246
253
 
247
254
  def visit_cookie
data/lib/ahoy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Ahoy
2
- VERSION = "5.1.0"
2
+ VERSION = "5.5.0"
3
3
  end
@@ -33,10 +33,6 @@ module Ahoy
33
33
  properties_type == "text" || (properties_type == "json" && ActiveRecord::Base.connection.try(:mariadb?))
34
34
  end
35
35
 
36
- def serialize_options
37
- ActiveRecord::VERSION::STRING.to_f >= 7.1 ? "coder: JSON" : "JSON"
38
- end
39
-
40
36
  # use connection_db_config instead of connection.adapter
41
37
  # so database connection isn't needed
42
38
  def adapter
@@ -11,12 +11,12 @@ module Ahoy
11
11
 
12
12
  selection =
13
13
  if activerecord && mongoid
14
- puts <<-MSG
14
+ puts <<~MSG
15
15
 
16
- Which data store would you like to use?
17
- 1. ActiveRecord (default)
18
- 2. Mongoid
19
- 3. Neither
16
+ Which data store would you like to use?
17
+ 1. ActiveRecord (default)
18
+ 2. Mongoid
19
+ 3. Neither
20
20
  MSG
21
21
 
22
22
  ask(">")
@@ -6,5 +6,5 @@ class Ahoy::Event < ApplicationRecord
6
6
  belongs_to :visit
7
7
  belongs_to :user, optional: true<% if serialize_properties? %>
8
8
 
9
- serialize :properties, <%= serialize_options %><% end %>
9
+ serialize :properties, coder: JSON<% end %>
10
10
  end
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Ahoy.js v0.4.4
2
+ * Ahoy.js v0.4.5
3
3
  * Simple, powerful JavaScript analytics
4
4
  * https://github.com/ankane/ahoy.js
5
5
  * MIT License
@@ -119,7 +119,7 @@
119
119
  }
120
120
 
121
121
  function destroyCookie(name) {
122
- Cookies.set(name, "", -1);
122
+ Cookies.set(name, "", -1, config.cookieDomain || config.domain);
123
123
  }
124
124
 
125
125
  function log(message) {
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ahoy_matey
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.0
4
+ version: 5.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-03-26 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activesupport
@@ -16,14 +15,28 @@ dependencies:
16
15
  requirements:
17
16
  - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: '6.1'
18
+ version: '7.2'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
- version: '6.1'
25
+ version: '7.2'
26
+ - !ruby/object:Gem::Dependency
27
+ name: cgi
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
27
40
  - !ruby/object:Gem::Dependency
28
41
  name: device_detector
29
42
  requirement: !ruby/object:Gem::Requirement
@@ -52,7 +65,6 @@ dependencies:
52
65
  - - ">="
53
66
  - !ruby/object:Gem::Version
54
67
  version: '0.4'
55
- description:
56
68
  email: andrew@ankane.org
57
69
  executables: []
58
70
  extensions: []
@@ -97,7 +109,6 @@ homepage: https://github.com/ankane/ahoy
97
109
  licenses:
98
110
  - MIT
99
111
  metadata: {}
100
- post_install_message:
101
112
  rdoc_options: []
102
113
  require_paths:
103
114
  - lib
@@ -105,15 +116,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
105
116
  requirements:
106
117
  - - ">="
107
118
  - !ruby/object:Gem::Version
108
- version: '3'
119
+ version: '3.3'
109
120
  required_rubygems_version: !ruby/object:Gem::Requirement
110
121
  requirements:
111
122
  - - ">="
112
123
  - !ruby/object:Gem::Version
113
124
  version: '0'
114
125
  requirements: []
115
- rubygems_version: 3.5.3
116
- signing_key:
126
+ rubygems_version: 4.0.6
117
127
  specification_version: 4
118
128
  summary: Simple, powerful, first-party analytics for Rails
119
129
  test_files: []