active_record-associated_object 0.8.2 → 0.8.3

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: 5816013890fc0f6868149661030643f47028edbb6a188d5014e7fd699e0138bd
4
- data.tar.gz: ef0c4be8afb96727e5f379c988632ec44f0f77d105b8aadde944ac48362b7385
3
+ metadata.gz: 4212b6fcecceb21ae133688c2a3332d29b8c0f5760f5a22a8ba3450037a95b20
4
+ data.tar.gz: 4b96fde3db82d00a3c94153cb9b212f1091bd0040d7d9771d300f2a0a0147d6f
5
5
  SHA512:
6
- metadata.gz: 5f80f20322bf4661515fb6235c9d034e7ac68a22bc17e269971c8b2a1f5782affb28471316b65402bab66deedc9f63f322032fa216100c6966cd514c7421a100
7
- data.tar.gz: 9def815025bf60d33b06ba6f7c9c185a59fca016f3e88a72d65fb64408dd0b4e7a34aea63c5a75de61004a64a80b86bd26e368ed021d105ed32bf6cca3a3f037
6
+ metadata.gz: 262b75fdf718925e7772b7c1dd4e49ab6b73f6706be97081433712a4f3efef524b1677194ff5376415fe32e770bfa080afd5b347c2ccf78786517dfe5a21a9fb
7
+ data.tar.gz: 47c40f2a351cd49fe9bc5e0488d37ce79bcb3d30332b3aabbaff681ef7ac7f937d81d01c60d6b7f8393d3fc28f7fa92fb9b4d5eb99ae607d95d0389deea12764
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- active_record-associated_object (0.8.2)
4
+ active_record-associated_object (0.8.3)
5
5
  activerecord (>= 6.1)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -60,7 +60,7 @@ We've fixed this so you don't need to care, but this is what's happening.
60
60
  > `has_object` only requires a namespace and an initializer that takes a single argument. The above `Post::Publisher` is perfectly valid as an Associated Object — same goes for `class Post::Publisher < Data.define(:post); end`.
61
61
 
62
62
  > [!TIP]
63
- > You can pass multiple names too: `has_object :publisher, :classified, :fortification`. I recommend `-[i]er`, `-[i]ed` and `-ion` as the general naming conventions for your Associated Objects.
63
+ > You can pass multiple names too: `has_object :seats, :entitlements, :publisher, :classified, :fortification`. I recommend `-s`, `-[i]er`, `-[i]ed` and `-ion` as the general naming conventions for your Associated Objects.
64
64
 
65
65
  > [!TIP]
66
66
  > Plural Associated Object names are also supported: `Account.has_object :seats` will look up `Account::Seats`.
@@ -87,6 +87,17 @@ end
87
87
 
88
88
  ### See Associated Objects in action
89
89
 
90
+ #### RubyVideo.dev
91
+
92
+ The team at https://www.rubyvideo.dev has been using Associated Objects to clarify the boundaries of their Active Records and collaborator Associated Objects.
93
+
94
+ See the usage in the source here:
95
+
96
+ - [`ActiveRecord::AssociatedObject` instances](https://github.com/search?q=repo%3Aadrienpoly%2Frubyvideo%20ActiveRecord%3A%3AAssociatedObject&type=code)
97
+ - [`has_object` calls](https://github.com/search?q=repo%3Aadrienpoly%2Frubyvideo+has_object&type=code)
98
+
99
+ #### Flipper
100
+
90
101
  The team at [Flipper](https://www.flippercloud.io) used Associated Objects to help keep their new billing structure clean.
91
102
 
92
103
  You can see real life examples in these blog posts:
@@ -240,6 +251,68 @@ class Post::PublisherTest < ActiveSupport::TestCase
240
251
  end
241
252
  ```
242
253
 
254
+ ### Polymorphic Associated Objects
255
+
256
+ If you want to share logic between associated objects, you can do so via standard Ruby modules:
257
+
258
+ ```ruby
259
+ # app/models/pricing.rb
260
+ module Pricing
261
+ # If you need to share an `extension` across associated objects you can override `Module::included` like this:
262
+ def self.included(object) = object.extension do
263
+ # Add common integration methods onto `Account`/`User` when the module is included.
264
+ # See the `extension` block in the `Extending` section above for an example.
265
+ end
266
+
267
+ def price_set?
268
+ # Instead of referring to `account` or `user`, use the `record` method to target either.
269
+ record.price_cents.positive?
270
+ end
271
+ end
272
+
273
+ # app/models/account/pricing.rb
274
+ class Account::Pricing < ActiveRecord::AssociatedObject
275
+ include ::Pricing
276
+ end
277
+
278
+ # app/models/user/pricing.rb
279
+ class User::Pricing < ActiveRecord::AssociatedObject
280
+ include ::Pricing
281
+ end
282
+ ```
283
+
284
+ Now we can call `account.pricing.price_set?` & `user.pricing.price_set?`.
285
+
286
+ > [!NOTE]
287
+ > Polymorphic Associated Objects are definitely a more advanced topic,
288
+ > so you need to know your Ruby module hierarchy and how to track what `self` changes to fairly well.
289
+
290
+ #### Using `ActiveSupport::Concern` as an alternative
291
+
292
+ If you prefer the look of Active Support concerns, here's the equivalent to the above Ruby module:
293
+
294
+ ```ruby
295
+ # app/models/pricing.rb
296
+ module Pricing
297
+ extend ActiveSupport::Concern
298
+
299
+ included do
300
+ extension do
301
+ # Add common integration methods onto `Account`/`User` when the concern is included.
302
+ end
303
+ end
304
+
305
+ def price_set?
306
+ # Instead of referring to `account` or `user`, use the `record` method to target either.
307
+ record.price_cents.positive?
308
+ end
309
+ end
310
+ ```
311
+
312
+ Active Support concerns have some extra features that standard Ruby modules don't, like support for deeply-nested concerns and `class_methods do`.
313
+
314
+ In this case, if you're reaching for those, you're probably building something too intricate and potentially brittle.
315
+
243
316
  ### Active Job integration via GlobalID
244
317
 
245
318
  Associated Objects include `GlobalID::Identification` and have automatic Active Job serialization support that looks like this:
@@ -6,14 +6,14 @@ class ActiveRecord::AssociatedObject::Railtie < Rails::Railtie
6
6
  end
7
7
  end
8
8
 
9
- initializer "object_association.setup" do
10
- ActiveSupport.on_load :active_job do
11
- require "active_job/performs"
12
- ActiveRecord::AssociatedObject.extend ActiveJob::Performs
13
- rescue LoadError
14
- # We haven't bundled active_job-performs, so we're continuing without it.
15
- end
9
+ initializer "active_job.performs" do
10
+ require "active_job/performs"
11
+ ActiveRecord::AssociatedObject.extend ActiveJob::Performs if defined?(ActiveJob::Performs)
12
+ rescue LoadError
13
+ # We haven't bundled active_job-performs, so we're continuing without it.
14
+ end
16
15
 
16
+ initializer "object_association.setup" do
17
17
  ActiveSupport.on_load :active_record do
18
18
  require "active_record/associated_object/object_association"
19
19
  include ActiveRecord::AssociatedObject::ObjectAssociation
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ActiveRecord
4
4
  class AssociatedObject
5
- VERSION = "0.8.2"
5
+ VERSION = "0.8.3"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record-associated_object
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.8.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kasper Timm Hansen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-11 00:00:00.000000000 Z
11
+ date: 2024-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord