missive 0.0.3 → 0.0.4

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: '06220491a9066084b07838222a15676c94543dcec8d6d7a9e3c84137e8efab14'
4
- data.tar.gz: cd08afa7a073de913d16f3ffe6251c31c196696420a2f5ccd51d8c1d6bff48f0
3
+ metadata.gz: 2524889a76072d9a0c8a32bcbcf644a47b53ef388eeb5937ab2d643f9f7943e9
4
+ data.tar.gz: 27050e567ac00cbf4a1d784a2495601b68fe8bfb481c14d3d822d99a33d0d086
5
5
  SHA512:
6
- metadata.gz: d32d340f9c5c473f320f3590339455b83408fc5854022bb4ad5888f59ee002a08cca4f8ec95bfec9b022d4557af3bad45554f44db137778c5337683c842cfbd2
7
- data.tar.gz: d15612829c698aa1f4bfa5f2177033da4745a9f4d2b835972d24dea1023a186c7bfe6227b9b2fe61cdecc78cee62b955977089d7f57d775a0ab326063b992072
6
+ metadata.gz: 6d58ad49167ba5a32acc92dd1e74e69c74ccd83748465f48497eef9a1d212bd092c5938a3fa1f3fa9357f3bdb8e5cc29c82152ac10cca3b89b094b51cd4ac94e
7
+ data.tar.gz: 5292722bfed62d90c92d6d61ec831c46fa495bb29609469da887711557e3e8f60a9ceb3bc4084a4fdf04c3b99cbbcf041cd7945100550a7bfbe20c1481ea4f82
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.0.4] - 2026-02-04
4
+
5
+ - Fix associations collision checks and configuration
6
+
3
7
  ## [0.0.3] - 2026-02-04
4
8
 
5
9
  - Add associations collision checks and configuration
data/README.md CHANGED
@@ -91,21 +91,21 @@ This is equivalent to:
91
91
  ```rb
92
92
  class User < ApplicationRecord
93
93
  # Missive::UserAsSender
94
- has_one :sender # ...
95
- has_many :sent_dispatches # ...
96
- has_many :sent_lists # ...
97
- has_many :sent_messages # ...
94
+ has_one :missive_sender # ...
95
+ has_many :missive_sent_dispatches # ...
96
+ has_many :missive_sent_lists # ...
97
+ has_many :missive_sent_messages # ...
98
98
 
99
99
  def init_sender(attributes = {});
100
100
  # ...
101
101
  end
102
102
 
103
103
  # Missive::UserAsSubscriber
104
- has_one :subscriber # ...
105
- has_many :dispatches # ...
106
- has_many :subscriptions # ...
107
- has_many :subscribed_lists # ...
108
- has_many :unsubscribed_lists # ...
104
+ has_one :missive_subscriber # ...
105
+ has_many :missive_dispatches # ...
106
+ has_many :missive_subscriptions # ...
107
+ has_many :missive_subscribed_lists # ...
108
+ has_many :missive_unsubscribed_lists # ...
109
109
 
110
110
  def init_subscriber(attributes = {})
111
111
  # ...
@@ -115,23 +115,24 @@ end
115
115
 
116
116
  #### Customizing association names
117
117
 
118
- If your User model already has associations named `sender` or `subscriber`, you can customize the association names:
118
+ By default, association names are prefixed with `missive_` to avoid collisions with existing associations. If you want to use shorter names (e.g., `sender` instead of `missive_sender`), you can customize them using the `.with` method:
119
119
 
120
120
  ```rb
121
121
  class User < ApplicationRecord
122
- include Missive::User
123
- configure_missive_sender(
124
- sender: :missive_sender,
125
- sent_dispatches: :missive_sent_dispatches,
126
- sent_lists: :missive_sent_lists,
127
- sent_messages: :missive_sent_messages
128
- )
129
- configure_missive_subscriber(
130
- subscriber: :missive_subscriber,
131
- dispatches: :missive_dispatches,
132
- subscriptions: :missive_subscriptions,
133
- subscribed_lists: :missive_subscribed_lists,
134
- unsubscribed_lists: :missive_unsubscribed_lists
122
+ include Missive::User.with(
123
+ sender: {
124
+ sender: :sender,
125
+ sent_dispatches: :sent_dispatches,
126
+ sent_lists: :sent_lists,
127
+ sent_messages: :sent_messages
128
+ },
129
+ subscriber: {
130
+ subscriber: :subscriber,
131
+ dispatches: :dispatches,
132
+ subscriptions: :subscriptions,
133
+ subscribed_lists: :subscribed_lists,
134
+ unsubscribed_lists: :unsubscribed_lists
135
+ }
135
136
  )
136
137
  end
137
138
  ```
@@ -140,26 +141,24 @@ Or, if including the concerns separately:
140
141
 
141
142
  ```rb
142
143
  class User < ApplicationRecord
143
- include Missive::UserAsSender
144
- configure_missive_sender(
145
- sender: :missive_sender,
146
- sent_dispatches: :missive_sent_dispatches,
147
- sent_lists: :missive_sent_lists,
148
- sent_messages: :missive_sent_messages
144
+ include Missive::UserAsSender.with(
145
+ sender: :sender,
146
+ sent_dispatches: :sent_dispatches,
147
+ sent_lists: :sent_lists,
148
+ sent_messages: :sent_messages
149
149
  )
150
150
 
151
- include Missive::UserAsSubscriber
152
- configure_missive_subscriber(
153
- subscriber: :missive_subscriber,
154
- dispatches: :missive_dispatches,
155
- subscriptions: :missive_subscriptions,
156
- subscribed_lists: :missive_subscribed_lists,
157
- unsubscribed_lists: :missive_unsubscribed_lists
151
+ include Missive::UserAsSubscriber.with(
152
+ subscriber: :subscriber,
153
+ dispatches: :dispatches,
154
+ subscriptions: :subscriptions,
155
+ subscribed_lists: :subscribed_lists,
156
+ unsubscribed_lists: :unsubscribed_lists
158
157
  )
159
158
  end
160
159
  ```
161
160
 
162
- You only need to customize the associations that conflict - any unconfigured associations will use their default names.
161
+ You only need to customize the associations you want to rename - any unconfigured associations will use their default `missive_` prefixed names.
163
162
 
164
163
  #### Manage subscriptions
165
164
 
@@ -173,17 +172,17 @@ list = Missive::List.first
173
172
  user.init_subscriber
174
173
 
175
174
  # List the subscriptions
176
- user.subscriptions # returns a `Missive::Subscription` collection
175
+ user.missive_subscriptions # returns a `Missive::Subscription` collection
177
176
 
178
177
  # List the (un)subscribed lists
179
- user.subscribed_lists # returns a `Missive::List` collection
180
- user.unsubscribed_lists # returns a `Missive::List` collection
178
+ user.missive_subscribed_lists # returns a `Missive::List` collection
179
+ user.missive_unsubscribed_lists # returns a `Missive::List` collection
181
180
 
182
181
  # Subscribe to an existing Missive::List
183
- user.subscriber.subscriptions.create!(list:)
182
+ user.missive_subscriber.subscriptions.create!(list:)
184
183
 
185
184
  # Unsubscribe from the list
186
- user.subscriptions.find_by(list:).suppress!(reason: :manual_suppression)
185
+ user.missive_subscriptions.find_by(list:).suppress!(reason: :manual_suppression)
187
186
  ```
188
187
 
189
188
  #### Manage senders
@@ -199,7 +198,7 @@ list = Missive::List.first
199
198
  user.init_sender(name: user.full_name)
200
199
 
201
200
  # Make them the default sender for a list
202
- user.sent_lists << list
201
+ user.missive_sent_lists << list
203
202
  ```
204
203
 
205
204
  #### Manage lists
@@ -2,6 +2,28 @@ module Missive
2
2
  module User
3
3
  extend ActiveSupport::Concern
4
4
 
5
+ def self.with(sender: {}, subscriber: {})
6
+ Module.new do
7
+ extend ActiveSupport::Concern
8
+
9
+ define_singleton_method(:inspect) { "Missive::User.with(sender: #{sender.inspect}, subscriber: #{subscriber.inspect})" }
10
+
11
+ included do
12
+ if sender.empty?
13
+ include Missive::UserAsSender
14
+ else
15
+ include Missive::UserAsSender.with(sender)
16
+ end
17
+
18
+ if subscriber.empty?
19
+ include Missive::UserAsSubscriber
20
+ else
21
+ include Missive::UserAsSubscriber.with(subscriber)
22
+ end
23
+ end
24
+ end
25
+ end
26
+
5
27
  included do
6
28
  include Missive::UserAsSender
7
29
  include Missive::UserAsSubscriber
@@ -4,16 +4,33 @@ module Missive
4
4
 
5
5
  class AssociationAlreadyDefinedError < StandardError; end
6
6
 
7
- ASSOCIATION_NAMES = %i[sender sent_dispatches sent_lists sent_messages].freeze
7
+ DEFAULT_ASSOCIATION_NAMES = {
8
+ sender: :missive_sender,
9
+ sent_dispatches: :missive_sent_dispatches,
10
+ sent_lists: :missive_sent_lists,
11
+ sent_messages: :missive_sent_messages
12
+ }.freeze
8
13
 
9
- class_methods do
10
- def missive_sender_config
11
- @missive_sender_config ||= ASSOCIATION_NAMES.index_with { |name| name }
14
+ def self.with(options = {})
15
+ config = DEFAULT_ASSOCIATION_NAMES.merge(options)
16
+
17
+ Module.new do
18
+ extend ActiveSupport::Concern
19
+
20
+ define_singleton_method(:inspect) { "Missive::UserAsSender.with(#{options.inspect})" }
21
+
22
+ included do |base|
23
+ base.instance_variable_set(:@missive_sender_config, config)
24
+ base.extend(ClassMethods)
25
+ base.include(InstanceMethods)
26
+ base._define_missive_sender_associations
27
+ end
12
28
  end
29
+ end
13
30
 
14
- def configure_missive_sender(options = {})
15
- missive_sender_config.merge!(options)
16
- _define_missive_sender_associations
31
+ module ClassMethods
32
+ def missive_sender_config
33
+ @missive_sender_config ||= DEFAULT_ASSOCIATION_NAMES.dup
17
34
  end
18
35
 
19
36
  def _define_missive_sender_associations
@@ -32,14 +49,12 @@ module Missive
32
49
 
33
50
  raise AssociationAlreadyDefinedError,
34
51
  "Association :#{name} is already defined on #{self.name}. " \
35
- "Use configure_missive_sender to specify a different name. " \
36
- "Example: configure_missive_sender(sender: :missive_sender)"
52
+ "Use Missive::UserAsSender.with to specify a different name. " \
53
+ "Example: include Missive::UserAsSender.with(sender: :missive_sender)"
37
54
  end
38
55
  end
39
56
 
40
- included do
41
- _define_missive_sender_associations
42
-
57
+ module InstanceMethods
43
58
  def init_sender(attributes = {})
44
59
  assoc = self.class.missive_sender_config[:sender]
45
60
  send("#{assoc}=", Missive::Sender.find_or_initialize_by(email:))
@@ -48,5 +63,11 @@ module Missive
48
63
  send(assoc)
49
64
  end
50
65
  end
66
+
67
+ included do |base|
68
+ base.extend(ClassMethods)
69
+ base.include(InstanceMethods)
70
+ base._define_missive_sender_associations
71
+ end
51
72
  end
52
73
  end
@@ -4,16 +4,34 @@ module Missive
4
4
 
5
5
  class AssociationAlreadyDefinedError < StandardError; end
6
6
 
7
- ASSOCIATION_NAMES = %i[subscriber dispatches subscriptions subscribed_lists unsubscribed_lists].freeze
7
+ DEFAULT_ASSOCIATION_NAMES = {
8
+ subscriber: :missive_subscriber,
9
+ dispatches: :missive_dispatches,
10
+ subscriptions: :missive_subscriptions,
11
+ subscribed_lists: :missive_subscribed_lists,
12
+ unsubscribed_lists: :missive_unsubscribed_lists
13
+ }.freeze
8
14
 
9
- class_methods do
10
- def missive_subscriber_config
11
- @missive_subscriber_config ||= ASSOCIATION_NAMES.index_with { |name| name }
15
+ def self.with(options = {})
16
+ config = DEFAULT_ASSOCIATION_NAMES.merge(options)
17
+
18
+ Module.new do
19
+ extend ActiveSupport::Concern
20
+
21
+ define_singleton_method(:inspect) { "Missive::UserAsSubscriber.with(#{options.inspect})" }
22
+
23
+ included do |base|
24
+ base.instance_variable_set(:@missive_subscriber_config, config)
25
+ base.extend(ClassMethods)
26
+ base.include(InstanceMethods)
27
+ base._define_missive_subscriber_associations
28
+ end
12
29
  end
30
+ end
13
31
 
14
- def configure_missive_subscriber(options = {})
15
- missive_subscriber_config.merge!(options)
16
- _define_missive_subscriber_associations
32
+ module ClassMethods
33
+ def missive_subscriber_config
34
+ @missive_subscriber_config ||= DEFAULT_ASSOCIATION_NAMES.dup
17
35
  end
18
36
 
19
37
  def _define_missive_subscriber_associations
@@ -22,8 +40,8 @@ module Missive
22
40
  _check_missive_association_collision!(config[:subscriber])
23
41
 
24
42
  has_one config[:subscriber], class_name: "Missive::Subscriber", foreign_key: :user_id, dependent: :destroy
25
- has_many config[:dispatches], class_name: "Missive::Dispatch", through: config[:subscriber]
26
- has_many config[:subscriptions], class_name: "Missive::Subscription", through: config[:subscriber]
43
+ has_many config[:dispatches], class_name: "Missive::Dispatch", through: config[:subscriber], source: :dispatches
44
+ has_many config[:subscriptions], class_name: "Missive::Subscription", through: config[:subscriber], source: :subscriptions
27
45
  has_many config[:subscribed_lists], class_name: "Missive::List", through: config[:subscriber], source: :lists
28
46
  has_many config[:unsubscribed_lists], -> { where.not(missive_subscriptions: {suppressed_at: nil}) },
29
47
  class_name: "Missive::List",
@@ -36,14 +54,12 @@ module Missive
36
54
 
37
55
  raise AssociationAlreadyDefinedError,
38
56
  "Association :#{name} is already defined on #{self.name}. " \
39
- "Use configure_missive_subscriber to specify a different name. " \
40
- "Example: configure_missive_subscriber(subscriber: :missive_subscriber)"
57
+ "Use Missive::UserAsSubscriber.with to specify a different name. " \
58
+ "Example: include Missive::UserAsSubscriber.with(subscriber: :missive_subscriber)"
41
59
  end
42
60
  end
43
61
 
44
- included do
45
- _define_missive_subscriber_associations
46
-
62
+ module InstanceMethods
47
63
  def init_subscriber(attributes = {})
48
64
  assoc = self.class.missive_subscriber_config[:subscriber]
49
65
  send("#{assoc}=", Missive::Subscriber.find_or_initialize_by(email:))
@@ -52,5 +68,11 @@ module Missive
52
68
  send(assoc)
53
69
  end
54
70
  end
71
+
72
+ included do |base|
73
+ base.extend(ClassMethods)
74
+ base.include(InstanceMethods)
75
+ base._define_missive_subscriber_associations
76
+ end
55
77
  end
56
78
  end
@@ -1,3 +1,3 @@
1
1
  module Missive
2
- VERSION = "0.0.3".freeze
2
+ VERSION = "0.0.4".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: missive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hans Lemuet