active_record-associated_object 0.1.0 → 0.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: '049c38f6aeb242c8ccfee9c15d3e29ace1c8f69eaf67619cdb38b09e5dd97514'
4
- data.tar.gz: 911ce88d3257b0db22169f325ca2059b12ecdd8bb7121d7a37368588dce37262
3
+ metadata.gz: d7a508d24fc9467600956a207ee83775b3618ccfc8be21a9c11e1caa72a11172
4
+ data.tar.gz: '0360292507cf0e901140b9fe4003bd33aca10aff9d91b01b759e4ce75497a61f'
5
5
  SHA512:
6
- metadata.gz: 0ee5964826318cb28a0a1d4c9e0a383b157e4ec0f2dd908b944c5eec68ddc7179d0d43be37bb65316c91e42318a6104b67eccd7d72194b99b4f3284312204692
7
- data.tar.gz: 61df4cf5bc61dd0109650ce1aa95bc1f9e79fd99c2da6e2757429b71cda10b1423d6dda7f29310390fa0c5d01b0a5b77563de4151c277316e7a3e57edf16c699
6
+ metadata.gz: '04940ddec3fc5446ba945df9f3daeff22550e81cf55f1e61e02b79af687adfc376f05e1148a6fb0e7ff17ab5df1a4539fe1d1c8bde456b986561df8ef4714e93'
7
+ data.tar.gz: 49ff34bb1945649479481ef7502585a124ee1464c67bc29f8ccb3335a53cfd0858790fbeebb976e3dfa1f055d12c085bb26ab2a7d054bed2ef51420f40cf83d5
data/CHANGELOG.md CHANGED
@@ -1,4 +1,20 @@
1
- ## [Unreleased]
1
+ ## [0.2.0] - 2022-04-21
2
+
3
+ - Require a `has_object` call on the record side to associate an object.
4
+
5
+ ```ruby
6
+ class Post < ActiveRecord::Base
7
+ has_object :publisher
8
+ end
9
+ ```
10
+
11
+ - Allow `has_object` to pass callbacks onto the associated object.
12
+
13
+ ```ruby
14
+ class Post < ActiveRecord::Base
15
+ has_object :publisher, after_touch: true, before_destroy: :prevent_errant_post_destroy
16
+ end
17
+ ```
2
18
 
3
19
  ## [0.1.0] - 2022-04-19
4
20
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- active_record-associated_object (0.1.0)
4
+ active_record-associated_object (0.2.0)
5
5
  activerecord (>= 6.1)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -7,6 +7,8 @@ Associate a Ruby PORO with an Active Record class and have it quack like one. Bu
7
7
  ```ruby
8
8
  # app/models/post.rb
9
9
  class Post < ActiveRecord::Base
10
+ # `has_object` defines a `publisher` method that calls Post::Publisher.new(post).
11
+ has_object :publisher, after_touch: true, before_destroy: :prevent_post_destroy
10
12
  end
11
13
 
12
14
  # Create a standard PORO, but derive attributes from the Post:: namespace and its primary key.
@@ -27,9 +29,6 @@ class Post::Publisher < ActiveRecord::AssociatedObject
27
29
  end
28
30
  end
29
31
 
30
- # Post now has a publisher too.
31
- Post.first.publisher # => Post::Publisher.new(self) # Where self is Post.first.
32
-
33
32
  class Post::Publisher::PublishJob < ActiveJob::Base
34
33
  def perform(publisher)
35
34
  # Automatic integration via GlobalID means you don't have to do `post.publisher`.
@@ -38,6 +37,32 @@ class Post::Publisher::PublishJob < ActiveJob::Base
38
37
  end
39
38
  ```
40
39
 
40
+ ### Passing callbacks onto the associated object
41
+
42
+ `has_object` accepts a hash of callbacks to pass.
43
+
44
+ ```ruby
45
+ class Post < ActiveRecord::Base
46
+ # Callbacks can be passed too to a specific method.
47
+ has_object :publisher, after_touch: true, before_destroy: :prevent_post_destroy
48
+
49
+ # The above is the same as writing:
50
+ after_touch { publisher.after_touch }
51
+ before_destroy { publisher.prevent_errant_post_destroy }
52
+ end
53
+
54
+ class Post::Publisher < ActiveRecord::AssociatedObject
55
+ def after_touch
56
+ # Respond to the after_touch on the Post.
57
+ end
58
+
59
+ def prevent_errant_post_destroy
60
+ # Passed callbacks can throw :abort too, and in this example prevent post.destroy.
61
+ throw :abort unless haha_business?
62
+ end
63
+ end
64
+ ```
65
+
41
66
  ## Installation
42
67
 
43
68
  Install the gem and add to the application's Gemfile by executing:
@@ -0,0 +1,17 @@
1
+ module ActiveRecord::AssociatedObject::ObjectAssociation
2
+ def has_object(*names, **callbacks)
3
+ methods = names.map do |name|
4
+ "def #{name}; @#{name} ||= #{self.name}::#{name.to_s.classify}.new(self); end"
5
+ end
6
+
7
+ class_eval methods.join("\n\n"), __FILE__, __LINE__ + 1
8
+
9
+ passes = names.flat_map do |name|
10
+ callbacks.map do |callback, method|
11
+ "#{callback} { #{name}.#{method == true ? callback : method} }"
12
+ end
13
+ end
14
+
15
+ class_eval passes.join("\n\n"), __FILE__, __LINE__ + 1
16
+ end
17
+ end
@@ -3,4 +3,11 @@ class ActiveRecord::AssociatedObject::Railtie < Rails::Railtie
3
3
  ActiveRecord::AssociatedObject.include Kredis::Attributes if defined?(Kredis)
4
4
  ActiveRecord::AssociatedObject.include GlobalID::Identification if defined?(GlobalID)
5
5
  end
6
+
7
+ initializer "object_association.setup" do
8
+ ActiveSupport.on_load :active_record do
9
+ require "active_record/associated_object/object_association"
10
+ ActiveRecord::Base.extend ActiveRecord::AssociatedObject::ObjectAssociation
11
+ end
12
+ end
6
13
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ActiveRecord
4
4
  class AssociatedObject
5
- VERSION = "0.1.0"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
@@ -13,12 +13,6 @@ class ActiveRecord::AssociatedObject
13
13
  define_singleton_method(:record_klass) { record_klass }
14
14
  define_singleton_method(:attribute_name) { attribute_name }
15
15
  delegate :record_klass, :attribute_name, to: :class
16
-
17
- record_klass.class_eval <<~RUBY, __FILE__, __LINE__ + 1
18
- def #{attribute_name}
19
- @#{attribute_name} ||= #{klass}.new(self)
20
- end
21
- RUBY
22
16
  end
23
17
 
24
18
  def respond_to_missing?(...) = record_klass.respond_to?(...) || super
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.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kasper Timm Hansen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-04-20 00:00:00.000000000 Z
11
+ date: 2022-04-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -39,6 +39,7 @@ files:
39
39
  - Rakefile
40
40
  - active_record-associated_object.gemspec
41
41
  - lib/active_record/associated_object.rb
42
+ - lib/active_record/associated_object/object_association.rb
42
43
  - lib/active_record/associated_object/railtie.rb
43
44
  - lib/active_record/associated_object/version.rb
44
45
  homepage: https://github.com/kaspth/active_record-associated_object