ams_lazy_relationships 0.2.0 → 0.3.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: d299c4294fa21bc85d59919b153f88de9f78a4ed9a2f2d7f87cf98cdc8093706
4
- data.tar.gz: 9a66c679744b7e8128ce492209f3743e397cb0f3d1eec93097667c7c0e142863
3
+ metadata.gz: cf2c7b4fd222fcde15c3f1accd9784c421455d988bf4ec6bf2c76b4029cf2718
4
+ data.tar.gz: 306b361e74fa64697a046c9b67d0b5dd1bdbfc930c2a77df4e443fc65bb2de6a
5
5
  SHA512:
6
- metadata.gz: 2683f61c4107464423359aecb53193f6e5d9de727812916282e7eb6c3848541fc3212d4be773d288044582ef29ba7832d2558fd80e60fed0af2ef833dc2bb858
7
- data.tar.gz: c9c777b5d1d56ad21289db010206cc20aa61225eacd9041a29f68745942e72696bee19acfef86eca4d08dba34152ff3e6ba3a1d0833296a0759c91e6203583f2
6
+ metadata.gz: 36ed2e0404138db614928261d8dfd771b185fa9fd62dc6e091e5ee037b05bf3fec3d6a0e20fdd254ac100ffbbcc2ee175c9e16296d0a2120fa47968f2c15ef5d
7
+ data.tar.gz: 0eac844f0f061f4e9769cea6835de6eebc75415d3fefc5aff82c2b838bef9c22609188d24ba8bd2b33851e0ce2c0fc8e19fef4ebc00f92e217e980394529fd3d
@@ -6,8 +6,11 @@ env:
6
6
  language: ruby
7
7
  gemfile:
8
8
  - gemfiles/ams_0.10.0.rc4.gemfile
9
+ - gemfiles/ams_0.10.0.gemfile
9
10
  - gemfiles/ams_0.10.2.gemfile
11
+ - gemfiles/ams_0.10.3.gemfile
10
12
  - gemfiles/ams_0.10.8.gemfile
13
+ - gemfiles/ams_0.10.10.gemfile
11
14
  cache: bundler
12
15
  rvm:
13
16
  - 2.5.3
data/Appraisals CHANGED
@@ -2,10 +2,22 @@ appraise "ams-0.10.0.rc4" do
2
2
  gem "active_model_serializers", "0.10.0.rc4"
3
3
  end
4
4
 
5
+ appraise "ams-0.10.0" do
6
+ gem "active_model_serializers", "0.10.0"
7
+ end
8
+
5
9
  appraise "ams-0.10.2" do
6
10
  gem "active_model_serializers", "0.10.2"
7
11
  end
8
12
 
13
+ appraise "ams-0.10.3" do
14
+ gem "active_model_serializers", "0.10.3"
15
+ end
16
+
9
17
  appraise "ams-0.10.8" do
10
18
  gem "active_model_serializers", "0.10.8"
11
19
  end
20
+
21
+ appraise "ams-0.10.10" do
22
+ gem "active_model_serializers", "0.10.10"
23
+ end
@@ -1,5 +1,17 @@
1
1
  # Change Log
2
2
 
3
+ ## [v0.3.0](https://github.com/Bajena/ams_lazy_relationships/tree/v0.3.0) (2020-01-16)
4
+ [Full Changelog](https://github.com/Bajena/ams_lazy_relationships/compare/v0.2.0...v0.3.0)
5
+
6
+ **Merged pull requests:**
7
+
8
+ - Fix association duplicates after accepts\_nested\_attributes\_for assignation [\#50](https://github.com/Bajena/ams_lazy_relationships/pull/50) ([stokarenko](https://github.com/stokarenko))
9
+ - Skip active\_support as redundant dependency [\#49](https://github.com/Bajena/ams_lazy_relationships/pull/49) ([stokarenko](https://github.com/stokarenko))
10
+ - Test against AMS v0.10.0.rc4 [\#48](https://github.com/Bajena/ams_lazy_relationships/pull/48) ([stokarenko](https://github.com/stokarenko))
11
+ - Skip redundant queries when include\_data is disabled [\#47](https://github.com/Bajena/ams_lazy_relationships/pull/47) ([stokarenko](https://github.com/stokarenko))
12
+ - Adjust tested ams version [\#46](https://github.com/Bajena/ams_lazy_relationships/pull/46) ([stokarenko](https://github.com/stokarenko))
13
+ - Fix documentation for blocked relationships [\#45](https://github.com/Bajena/ams_lazy_relationships/pull/45) ([stokarenko](https://github.com/stokarenko))
14
+
3
15
  ## [v0.2.0](https://github.com/Bajena/ams_lazy_relationships/tree/v0.2.0) (2020-01-11)
4
16
  [Full Changelog](https://github.com/Bajena/ams_lazy_relationships/compare/v0.1.5...v0.2.0)
5
17
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ams_lazy_relationships (0.2.0)
4
+ ams_lazy_relationships (0.3.0)
5
5
  active_model_serializers
6
6
  batch-loader (~> 1)
7
7
 
data/README.md CHANGED
@@ -63,8 +63,10 @@ class UserSerializer < BaseSerializer
63
63
 
64
64
  # The previous one is a shorthand for the following lines:
65
65
  lazy_relationship :blog_posts, loader: AmsLazyRelationships::Loaders::Association.new("User", :blog_posts)
66
- has_many :blog_posts, serializer: BlogPostSerializer do
67
- lazy_blog_posts
66
+ has_many :blog_posts, serializer: BlogPostSerializer do |serializer|
67
+ # non-proc custom finder will work as well, but it can produce redundant sql
68
+ # queries, please see [Example 2: Modifying the relationship before rendering](#example-2-modifying-the-relationship-before-rendering)
69
+ -> { serializer.lazy_blog_posts }
68
70
  end
69
71
 
70
72
  lazy_has_one :poro_model, loader: AmsLazyRelationships::Loaders::Direct.new(:poro_model) { |object| PoroModel.new(object) }
@@ -116,10 +118,43 @@ end
116
118
  #### Example 2: Modifying the relationship before rendering
117
119
  Sometimes it may happen that you need to process the relationship before rendering, e.g. decorate the records. In this case the gem provides a special method (in our case `lazy_comments`) for each defined relationship. Check out the example - we'll decorate every comment before serializing:
118
120
 
121
+ ```ruby
122
+ class BlogPostSerializer < BaseSerializer
123
+ lazy_has_many :comments do |serializer|
124
+ -> { serializer.lazy_comments.map(&:decorate) }
125
+ end
126
+ end
127
+ ```
128
+
129
+ Despite the fact that non-block custom finder such as
130
+
131
+ ```ruby
132
+ class BlogPostSerializer < BaseSerializer
133
+ lazy_has_many :comments do |serializer|
134
+ serializer.lazy_comments.map(&:decorate)
135
+ end
136
+ end
137
+ ```
138
+
139
+ will work still, it's better to implement it in a form of lambda, in order to avoid redundant SQL queries when `include_data` AMS setting appears to be `false`:
140
+
141
+ ```ruby
142
+ class BlogPostSerializer < BaseSerializer
143
+ lazy_has_many :comments do |serializer|
144
+ include_data :if_sideloaded
145
+ -> { serializer.lazy_comments.map(&:decorate) }
146
+ end
147
+ end
148
+ ```
149
+
150
+ Feel free to skip custom lazy finder for association if your goal is just to define `include_data` setting and/or to specify some links and metas:
151
+
119
152
  ```ruby
120
153
  class BlogPostSerializer < BaseSerializer
121
154
  lazy_has_many :comments do
122
- lazy_comments.map(&:decorate)
155
+ include_data :if_sideloaded
156
+ link :self, 'a link'
157
+ meta name: 'Dan Brown'
123
158
  end
124
159
  end
125
160
  ```
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "active_model_serializers", "0.10.0"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "active_model_serializers", "0.10.10"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "active_model_serializers", "0.10.3"
6
+
7
+ gemspec path: "../"
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "batch-loader"
4
+ require "active_model_serializers"
4
5
 
5
6
  require "ams_lazy_relationships/version"
7
+ require "ams_lazy_relationships/extensions"
6
8
  require "ams_lazy_relationships/loaders"
7
9
  require "ams_lazy_relationships/core"
8
10
 
@@ -19,7 +19,7 @@ module AmsLazyRelationships::Core
19
19
  define_singleton_method(
20
20
  "lazy_#{relationship_type}"
21
21
  ) do |relationship_name, options = {}, &block|
22
- send(:define_lazy_association, relationship_type, relationship_name, options, block)
22
+ define_lazy_association(relationship_type, relationship_name, options, block)
23
23
  end
24
24
  end
25
25
  end
@@ -29,11 +29,20 @@ module AmsLazyRelationships::Core
29
29
 
30
30
  real_relationship_options = options.except(*lazy_relationship_option_keys)
31
31
 
32
- block ||= lambda do |serializer|
33
- serializer.public_send("lazy_#{name}")
34
- end
32
+ public_send(type, name.to_sym, real_relationship_options) do |serializer|
33
+ block_value = instance_exec(serializer, &block) if block
35
34
 
36
- public_send(type, name.to_sym, real_relationship_options, &block)
35
+ if block && block_value != :nil
36
+ # respect the custom finder for lazy association
37
+ # @see https://github.com/rails-api/active_model_serializers/blob/v0.10.10/lib/active_model/serializer/reflection.rb#L165-L168
38
+ block_value
39
+ else
40
+ # provide default lazy association finder in a form of lambda,
41
+ # in order to play nice with possible `include_data` setting.
42
+ # @see lib/ams_lazy_relationships/extensions/reflection.rb
43
+ serializer.method("lazy_#{name}")
44
+ end
45
+ end
37
46
 
38
47
  lazy_relationship(name, options.slice(*lazy_relationship_option_keys))
39
48
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ams_lazy_relationships/extensions/reflection"
4
+
5
+ module AmsLazyRelationships
6
+ module Extensions
7
+ end
8
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ # There is a general problem inside AMS related to custom association finder
4
+ # combined with `include_data` setting:
5
+ #
6
+ # class BlogPostSerializer < BaseSerializer
7
+ # belongs_to :category do
8
+ # include_data :if_sideloaded
9
+ # object.categories.last
10
+ # end
11
+ # end
12
+ #
13
+ # The problem is that `belongs_to` block will be fully evaluated each time for
14
+ # each object, and only after that AMS is able to take into account
15
+ # `include_data` mode -
16
+ # https://github.com/rails-api/active_model_serializers/blob/v0.10.10/lib/active_model/serializer/reflection.rb#L162-L163
17
+ #
18
+ # def value(serializer, include_slice)
19
+ # # ...
20
+ # block_value = instance_exec(serializer, &block) if block
21
+ # return unless include_data?(include_slice)
22
+ # # ...
23
+ # end
24
+ #
25
+ # That causing redundant (and so huge potentially!) SQL queries and AR objects
26
+ # allocation when `include_data` appears to be `false` but `belongs_to` block
27
+ # defines instant (not a kind of AR::Relation) custom association finder.
28
+ #
29
+ # Described problem is a very specific use case for pure AMS applications.
30
+ # The bad news is that `ams_lazy_relationships` always utilizes the
31
+ # association block -
32
+ # https://github.com/Bajena/ams_lazy_relationships/blob/v0.2.0/lib/ams_lazy_relationships/core/relationship_wrapper_methods.rb#L32-L36
33
+ #
34
+ # def define_lazy_association(type, name, options, block)
35
+ # #...
36
+ # block ||= lambda do |serializer|
37
+ # serializer.public_send("lazy_#{name}")
38
+ # end
39
+ #
40
+ # public_send(type, name.to_sym, real_relationship_options, &block)
41
+ # #...
42
+ # end
43
+ #
44
+ # This way we break `include_data` optimizations for the host application.
45
+ #
46
+ # In order to overcome that we are forced to monkey-patch
47
+ # `AmsLazyRelationships::Extensions::Reflection#value` method and make it to be
48
+ # ready for Proc returned by association block. This way we will use a kind of
49
+ #
50
+ # block ||= lambda do |serializer|
51
+ # -> { serializer.public_send("lazy_#{name}") }
52
+ # end
53
+ #
54
+ # as association block, then AMS will evaluate it, get the value of `include_data`
55
+ # setting, make a decision do we need to continue with that association, if so -
56
+ # will finally evaluate the proc with lazy relationship inside it.
57
+
58
+ module AmsLazyRelationships
59
+ module Extensions
60
+ module Reflection
61
+ def value(*)
62
+ case (block_value = super)
63
+ when Proc, Method then block_value.call
64
+ else block_value
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ ::ActiveModel::Serializer::Reflection.prepend AmsLazyRelationships::Extensions::Reflection
@@ -45,9 +45,19 @@ module AmsLazyRelationships
45
45
  # in a decorator and non-wrapped). In this case Associations::Preloader
46
46
  # stores duplicated records in has_many relationships for some reason.
47
47
  # Calling uniq(&:id) solves the problem.
48
- records.uniq(&:id).reject do |r|
49
- r.association(association_name).loaded?
50
- end
48
+ #
49
+ # One more case when duplicated records appear in has_many relationships
50
+ # is the recent assignation to `accept_nested_attributes_for` setter.
51
+ # ActiveRecord will not mark the association as `loaded` but in same
52
+ # time will keep internal representation of the nested records created
53
+ # by `accept_nested_attributes_for`. Then Associations::Preloader is
54
+ # going to merge internal state of associated records with the same
55
+ # records recently stored in DB. `r.association(association_name).reset`
56
+ # effectively fixes that.
57
+ records.
58
+ uniq(&:id).
59
+ reject { |r| r.association(association_name).loaded? }.
60
+ each { |r| r.association(association_name).reset }
51
61
  end
52
62
  end
53
63
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AmsLazyRelationships
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ams_lazy_relationships
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Bajena
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-01-11 00:00:00.000000000 Z
11
+ date: 2020-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_model_serializers
@@ -300,8 +300,11 @@ files:
300
300
  - bin/console
301
301
  - bin/setup
302
302
  - gemfiles/.bundle/config
303
+ - gemfiles/ams_0.10.0.gemfile
303
304
  - gemfiles/ams_0.10.0.rc4.gemfile
305
+ - gemfiles/ams_0.10.10.gemfile
304
306
  - gemfiles/ams_0.10.2.gemfile
307
+ - gemfiles/ams_0.10.3.gemfile
305
308
  - gemfiles/ams_0.10.8.gemfile
306
309
  - lib/ams_lazy_relationships.rb
307
310
  - lib/ams_lazy_relationships/core.rb
@@ -310,6 +313,8 @@ files:
310
313
  - lib/ams_lazy_relationships/core/lazy_relationship_meta.rb
311
314
  - lib/ams_lazy_relationships/core/lazy_relationship_method.rb
312
315
  - lib/ams_lazy_relationships/core/relationship_wrapper_methods.rb
316
+ - lib/ams_lazy_relationships/extensions.rb
317
+ - lib/ams_lazy_relationships/extensions/reflection.rb
313
318
  - lib/ams_lazy_relationships/loaders.rb
314
319
  - lib/ams_lazy_relationships/loaders/association.rb
315
320
  - lib/ams_lazy_relationships/loaders/base.rb