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 +4 -4
- data/.travis.yml +3 -0
- data/Appraisals +12 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile.lock +1 -1
- data/README.md +38 -3
- data/gemfiles/ams_0.10.0.gemfile +7 -0
- data/gemfiles/ams_0.10.10.gemfile +7 -0
- data/gemfiles/ams_0.10.3.gemfile +7 -0
- data/lib/ams_lazy_relationships.rb +2 -0
- data/lib/ams_lazy_relationships/core/relationship_wrapper_methods.rb +14 -5
- data/lib/ams_lazy_relationships/extensions.rb +8 -0
- data/lib/ams_lazy_relationships/extensions/reflection.rb +71 -0
- data/lib/ams_lazy_relationships/loaders/association.rb +13 -3
- data/lib/ams_lazy_relationships/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf2c7b4fd222fcde15c3f1accd9784c421455d988bf4ec6bf2c76b4029cf2718
|
4
|
+
data.tar.gz: 306b361e74fa64697a046c9b67d0b5dd1bdbfc930c2a77df4e443fc65bb2de6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36ed2e0404138db614928261d8dfd771b185fa9fd62dc6e091e5ee037b05bf3fec3d6a0e20fdd254ac100ffbbcc2ee175c9e16296d0a2120fa47968f2c15ef5d
|
7
|
+
data.tar.gz: 0eac844f0f061f4e9769cea6835de6eebc75415d3fefc5aff82c2b838bef9c22609188d24ba8bd2b33851e0ce2c0fc8e19fef4ebc00f92e217e980394529fd3d
|
data/.travis.yml
CHANGED
@@ -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
|
data/CHANGELOG.md
CHANGED
@@ -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
|
|
data/Gemfile.lock
CHANGED
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
|
-
|
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
|
-
|
155
|
+
include_data :if_sideloaded
|
156
|
+
link :self, 'a link'
|
157
|
+
meta name: 'Dan Brown'
|
123
158
|
end
|
124
159
|
end
|
125
160
|
```
|
@@ -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
|
-
|
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
|
-
|
33
|
-
serializer
|
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
|
-
|
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,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
|
-
|
49
|
-
|
50
|
-
|
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
|
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.
|
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
|
+
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
|