ahoy_email 2.5.0 → 4.0.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: aa1850e7d07ec2fe43003f8e6c2046a10bd8229c6e5e8d12849cc8a2d819f670
4
- data.tar.gz: 4eefd3654e671eb6c65b064025d9ea5c7dd7810d73f12bbc8b34cafb2e5e00f4
3
+ metadata.gz: bd188dfb55eeecb5ff5b601ab679f04df570515a2176af9184192ea0cd8688bc
4
+ data.tar.gz: 176f9e44b50fc890e29d522e80bc68143739fcd5c14235977ec8c1f258d84043
5
5
  SHA512:
6
- metadata.gz: 0e021685e661cbb627a5d95fde8dfccbc0630398a391eea319d64ce268f3219918a6442a23f1ed9a2a06b69761a97f09aa8cb2a633e282affc200e4ac45b7d7b
7
- data.tar.gz: 104b6dfebf8f9d3bb3381e09b972708f539122ff2ca062cfc0aaf5a5af529661e06c196dfa35e862a8709b2ede56af3dcf13af9ee1bb15552ce036323ced9f39
6
+ metadata.gz: 6b375f8a1fbb1d78e6bf87b7092c40484ea889f3d71a7f9d2d7916e365161edb229e947aea7f2db517a430775cfc7b29881223efd00391232bb3cea7a859f4e3
7
+ data.tar.gz: c9fb82f641e3905f7039b81c6465df26a01d9ddc529a25e600d966eb58b4ed96017e8ff6ae0e2d135a4f7545eb9a9a6eea297f8e6c56edb1e4a632b1926325fb
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## 4.0.0 (2026-08-08)
2
+
3
+ See the [upgrade notes](https://github.com/ankane/ahoy_email?tab=readme-ov-file#40)
4
+
5
+ - Fixed change to key generator hash digest class
6
+ - Removed support for Ruby < 3.3 and Rails < 7.2
7
+
8
+ ## 3.0.0 (2025-07-02)
9
+
10
+ See the [upgrade notes](https://github.com/ankane/ahoy_email/blob/v3.0.0/README.md#upgrading)
11
+
12
+ - Switched to HTML5 parsing by default (when available)
13
+ - Removed support for legacy secret token generation
14
+
1
15
  ## 2.5.0 (2025-05-04)
2
16
 
3
17
  - Removed support for Ruby < 3.2 and Rails < 7.1
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014-2023 Andrew Kane
1
+ Copyright (c) 2014-2025 Andrew Kane
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  First-party email analytics for Rails
4
4
 
5
+ **Ahoy Email 4.0 was recently released** - see [how to upgrade](#upgrading)
6
+
5
7
  :fire: For web and native app analytics, check out [Ahoy](https://github.com/ankane/ahoy)
6
8
 
7
9
  :bullettrain_side: To manage email subscriptions, check out [Mailkick](https://github.com/ankane/mailkick)
@@ -106,7 +108,7 @@ user.messages
106
108
  Add extra data to messages. Create a migration like:
107
109
 
108
110
  ```ruby
109
- class AddCouponIdToAhoyMessages < ActiveRecord::Migration[8.0]
111
+ class AddCouponIdToAhoyMessages < ActiveRecord::Migration[8.1]
110
112
  def change
111
113
  add_column :ahoy_messages, :coupon_id, :integer
112
114
  end
@@ -324,14 +326,14 @@ Get stats for a campaign
324
326
  AhoyEmail.stats("my-campaign")
325
327
  ```
326
328
 
327
- ## HTML Parsing
329
+ ## Upgrading
328
330
 
329
- By default, Nokogiri’s default HTML parser is used to rewrite links for UTM tagging and click analytics. This currently uses HTML4, which [only allows inline elements inside links](https://github.com/sparklemotion/nokogiri/issues/1876#issuecomment-468276937).
331
+ ### 4.0
330
332
 
331
- To use HTML5 parsing, create `config/initializers/ahoy_email.rb` with:
333
+ Versions 2.3.0-3.0.0 cause applications to use SHA1 for the key generator hash digest class if `AhoyEmail.secret_token` is not manually set (due to [this behavior in Rails](https://github.com/rails/rails/issues/56736)). To avoid breakage when upgrading, add to `config/application.rb`:
332
334
 
333
335
  ```ruby
334
- AhoyEmail.default_options[:html5] = true
336
+ config.active_support.key_generator_hash_digest_class = OpenSSL::Digest::SHA1
335
337
  ```
336
338
 
337
339
  ## History
@@ -3,26 +3,8 @@ require "rails/engine"
3
3
  module AhoyEmail
4
4
  class Engine < ::Rails::Engine
5
5
  initializer "ahoy_email" do |app|
6
- AhoyEmail.secret_token ||= begin
7
- tokens = []
8
- tokens << app.key_generator.generate_key("ahoy_email")
9
-
10
- # TODO remove in 3.0
11
- creds =
12
- if app.respond_to?(:credentials) && app.credentials.secret_key_base
13
- app.credentials
14
- elsif app.respond_to?(:secrets) && app.config.paths["config/secrets"].existent.any?
15
- app.secrets
16
- else
17
- app.config
18
- end
19
-
20
- token = creds.respond_to?(:secret_key_base) ? creds.secret_key_base : creds.secret_token
21
- token ||= app.secret_key_base # should come first, but need to maintain backward compatibility
22
- tokens << token
23
-
24
- tokens
25
- end
6
+ # avoid app.key_generator due to https://github.com/ankane/ahoy_email/pull/168
7
+ AhoyEmail.secret_token ||= ActiveSupport::KeyGenerator.new(app.secret_key_base, iterations: 1000, hash_digest_class: OpenSSL::Digest::SHA1).generate_key("ahoy_email")
26
8
  end
27
9
  end
28
10
  end
@@ -101,7 +101,11 @@ module AhoyEmail
101
101
  when false
102
102
  Nokogiri::HTML4::Document
103
103
  else
104
- Nokogiri::HTML::Document
104
+ if defined?(Nokogiri::HTML5::Document)
105
+ Nokogiri::HTML5::Document
106
+ else
107
+ Nokogiri::HTML4::Document
108
+ end
105
109
  end
106
110
  end
107
111
 
@@ -20,6 +20,7 @@ module AhoyEmail
20
20
  secret_tokens.any? do |secret_token|
21
21
  expected_signature =
22
22
  if legacy
23
+ # TODO remove legacy support in 5.0
23
24
  OpenSSL::HMAC.hexdigest("SHA1", secret_token, url)
24
25
  else
25
26
  signature(token: token, campaign: campaign, url: url, secret_token: secret_token)
@@ -1,3 +1,3 @@
1
1
  module AhoyEmail
2
- VERSION = "2.5.0"
2
+ VERSION = "4.0.0"
3
3
  end
@@ -14,6 +14,14 @@ module Ahoy
14
14
  def migration_version
15
15
  "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
16
16
  end
17
+
18
+ def primary_key_type
19
+ ", id: :#{key_type}" if key_type
20
+ end
21
+
22
+ def key_type
23
+ Rails.configuration.generators.options.dig(:active_record, :primary_key_type)
24
+ end
17
25
  end
18
26
  end
19
27
  end
@@ -1,6 +1,6 @@
1
1
  class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
2
2
  def change
3
- create_table :ahoy_clicks do |t|
3
+ create_table :ahoy_clicks<%= primary_key_type %> do |t|
4
4
  t.string :campaign, index: true
5
5
  t.string :token
6
6
  end
@@ -9,11 +9,11 @@ module Ahoy
9
9
 
10
10
  selection =
11
11
  if activerecord && mongoid
12
- puts <<-MSG
12
+ puts <<~MSG
13
13
 
14
- Which data store would you like to use?
15
- 1. Active Record (default)
16
- 2. Mongoid
14
+ Which data store would you like to use?
15
+ 1. Active Record (default)
16
+ 2. Mongoid
17
17
  MSG
18
18
 
19
19
  ask(">")
@@ -42,18 +42,10 @@ module Ahoy
42
42
  end
43
43
  end
44
44
 
45
- # TODO remove default
46
45
  def encryption
47
46
  case options[:encryption]
48
47
  when "lockbox", "activerecord", "none"
49
48
  options[:encryption]
50
- when nil
51
- if options[:unencrypted]
52
- # TODO deprecation warning
53
- "none"
54
- else
55
- "lockbox"
56
- end
57
49
  else
58
50
  abort "Error: encryption must be lockbox, activerecord, or none"
59
51
  end
@@ -74,6 +66,18 @@ module Ahoy
74
66
  def adapter
75
67
  ActiveRecord::Base.connection_db_config.adapter.to_s
76
68
  end
69
+
70
+ def primary_key_type
71
+ ", id: :#{key_type}" if key_type
72
+ end
73
+
74
+ def foreign_key_type
75
+ ", type: :#{key_type}" if key_type
76
+ end
77
+
78
+ def key_type
79
+ Rails.configuration.generators.options.dig(:active_record, :primary_key_type)
80
+ end
77
81
  end
78
82
  end
79
83
  end
@@ -19,18 +19,10 @@ module Ahoy
19
19
  end
20
20
  end
21
21
 
22
- # TODO remove default
23
22
  def encryption
24
23
  case options[:encryption]
25
24
  when "lockbox", "none"
26
25
  options[:encryption]
27
- when nil
28
- if options[:unencrypted]
29
- # TODO deprecation warning
30
- "none"
31
- else
32
- "lockbox"
33
- end
34
26
  else
35
27
  abort "Error: encryption must be lockbox or none"
36
28
  end
@@ -1,7 +1,7 @@
1
1
  class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
2
2
  def change
3
- create_table :ahoy_messages do |t|
4
- t.references :user, polymorphic: true
3
+ create_table :ahoy_messages<%= primary_key_type %> do |t|
4
+ t.references :user<%= foreign_key_type %>, polymorphic: true
5
5
  <%= to_column %>
6
6
  t.string :mailer
7
7
  t.text :subject
@@ -13,11 +13,11 @@ module Ahoy
13
13
 
14
14
  selection =
15
15
  if activerecord && mongoid
16
- puts <<-MSG
16
+ puts <<~MSG
17
17
 
18
- Which data store would you like to use?
19
- 1. Active Record (default)
20
- 2. Mongoid
18
+ Which data store would you like to use?
19
+ 1. Active Record (default)
20
+ 2. Mongoid
21
21
  MSG
22
22
 
23
23
  ask(">")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ahoy_email
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
@@ -15,56 +15,56 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '7.1'
18
+ version: '7.2'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: '7.1'
25
+ version: '7.2'
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: addressable
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 2.3.2
32
+ version: '2.8'
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
- version: 2.3.2
39
+ version: '2.8'
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: nokogiri
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: '0'
46
+ version: '1.15'
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: '0'
53
+ version: '1.15'
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: safely_block
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: '0.4'
60
+ version: '0.5'
61
61
  type: :runtime
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - ">="
66
66
  - !ruby/object:Gem::Version
67
- version: '0.4'
67
+ version: '0.5'
68
68
  email: andrew@ankane.org
69
69
  executables: []
70
70
  extensions: []
@@ -113,14 +113,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - ">="
115
115
  - !ruby/object:Gem::Version
116
- version: '3.2'
116
+ version: '3.3'
117
117
  required_rubygems_version: !ruby/object:Gem::Requirement
118
118
  requirements:
119
119
  - - ">="
120
120
  - !ruby/object:Gem::Version
121
121
  version: '0'
122
122
  requirements: []
123
- rubygems_version: 3.6.7
123
+ rubygems_version: 4.0.16
124
124
  specification_version: 4
125
125
  summary: First-party email analytics for Rails
126
126
  test_files: []