ams_lazy_relationships 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.travis.yml +1 -1
- data/CHANGELOG.md +8 -1
- data/Gemfile.lock +201 -0
- data/README.md +82 -12
- data/Rakefile +1 -1
- data/ams_lazy_relationships.gemspec +1 -1
- data/lib/ams_lazy_relationships/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a98cab560bd1120e26c240598acbe505250f486
|
4
|
+
data.tar.gz: 908ccee8070ca834715135833da3fb7e5e9faed9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32dcc6601a4f8670806f58617d5342f5d601ab3a1c40ef17016912667aa91d36993d90bd65107223bee4fa7bb4af14d7585f3e2455385f2d0e1cd1f4342cb970
|
7
|
+
data.tar.gz: '0779950cd56d399924d3f7bbd5439d95d2dcb16f5e37294962b64c27a176270c746dd8aacc454b8666f03b217185a31af059b63da4d46a50be2fbe28be8d8b92'
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -12,7 +12,7 @@ cache: bundler
|
|
12
12
|
rvm:
|
13
13
|
- 2.3.4
|
14
14
|
before_install:
|
15
|
-
- gem install bundler undercover --no-doc
|
15
|
+
- gem install bundler:1.17 undercover --no-doc
|
16
16
|
before_script:
|
17
17
|
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
18
18
|
- chmod +x ./cc-test-reporter
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [0.1.
|
3
|
+
## [0.1.1](https://github.com/Bajena/ams_lazy_relationships/tree/0.1.1) (2019-01-09)
|
4
|
+
[Full Changelog](https://github.com/Bajena/ams_lazy_relationships/compare/v0.1.0...0.1.1)
|
5
|
+
|
6
|
+
**Merged pull requests:**
|
7
|
+
|
8
|
+
- Relax batch-loader version [\#13](https://github.com/Bajena/ams_lazy_relationships/pull/13) ([Bajena](https://github.com/Bajena))
|
9
|
+
|
10
|
+
## [v0.1.0](https://github.com/Bajena/ams_lazy_relationships/tree/v0.1.0) (2018-12-30)
|
4
11
|
**Closed issues:**
|
5
12
|
|
6
13
|
- Add changelog [\#10](https://github.com/Bajena/ams_lazy_relationships/issues/10)
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
ams_lazy_relationships (0.1.1)
|
5
|
+
active_model_serializers
|
6
|
+
batch-loader (~> 1.2)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
actionpack (5.2.2)
|
12
|
+
actionview (= 5.2.2)
|
13
|
+
activesupport (= 5.2.2)
|
14
|
+
rack (~> 2.0)
|
15
|
+
rack-test (>= 0.6.3)
|
16
|
+
rails-dom-testing (~> 2.0)
|
17
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
18
|
+
actionview (5.2.2)
|
19
|
+
activesupport (= 5.2.2)
|
20
|
+
builder (~> 3.1)
|
21
|
+
erubi (~> 1.4)
|
22
|
+
rails-dom-testing (~> 2.0)
|
23
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
24
|
+
active_model_serializers (0.10.8)
|
25
|
+
actionpack (>= 4.1, < 6)
|
26
|
+
activemodel (>= 4.1, < 6)
|
27
|
+
case_transform (>= 0.2)
|
28
|
+
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
29
|
+
activemodel (5.2.2)
|
30
|
+
activesupport (= 5.2.2)
|
31
|
+
activerecord (5.2.2)
|
32
|
+
activemodel (= 5.2.2)
|
33
|
+
activesupport (= 5.2.2)
|
34
|
+
arel (>= 9.0)
|
35
|
+
activesupport (5.2.2)
|
36
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
37
|
+
i18n (>= 0.7, < 2)
|
38
|
+
minitest (~> 5.1)
|
39
|
+
tzinfo (~> 1.1)
|
40
|
+
addressable (2.5.2)
|
41
|
+
public_suffix (>= 2.0.2, < 4.0)
|
42
|
+
appraisal (2.2.0)
|
43
|
+
bundler
|
44
|
+
rake
|
45
|
+
thor (>= 0.14.0)
|
46
|
+
arel (9.0.0)
|
47
|
+
ast (2.4.0)
|
48
|
+
batch-loader (1.2.2)
|
49
|
+
builder (3.2.3)
|
50
|
+
case_transform (0.2)
|
51
|
+
activesupport
|
52
|
+
coderay (1.1.2)
|
53
|
+
concurrent-ruby (1.1.4)
|
54
|
+
crass (1.0.4)
|
55
|
+
db-query-matchers (0.9.0)
|
56
|
+
activesupport (>= 4.0, <= 6.0)
|
57
|
+
rspec (~> 3.0)
|
58
|
+
diff-lcs (1.3)
|
59
|
+
docile (1.3.1)
|
60
|
+
erubi (1.8.0)
|
61
|
+
faraday (0.15.4)
|
62
|
+
multipart-post (>= 1.2, < 3)
|
63
|
+
faraday-http-cache (2.0.0)
|
64
|
+
faraday (~> 0.8)
|
65
|
+
github_changelog_generator (1.14.3)
|
66
|
+
activesupport
|
67
|
+
faraday-http-cache
|
68
|
+
multi_json
|
69
|
+
octokit (~> 4.6)
|
70
|
+
rainbow (>= 2.1)
|
71
|
+
rake (>= 10.0)
|
72
|
+
retriable (~> 2.1)
|
73
|
+
i18n (1.5.1)
|
74
|
+
concurrent-ruby (~> 1.0)
|
75
|
+
imagen (0.1.5)
|
76
|
+
parser (>= 2.5, != 2.5.1.1)
|
77
|
+
jaro_winkler (1.5.2)
|
78
|
+
json (2.1.0)
|
79
|
+
jsonapi-renderer (0.2.0)
|
80
|
+
loofah (2.2.3)
|
81
|
+
crass (~> 1.0.2)
|
82
|
+
nokogiri (>= 1.5.9)
|
83
|
+
method_source (0.8.2)
|
84
|
+
mini_portile2 (2.4.0)
|
85
|
+
minitest (5.11.3)
|
86
|
+
multi_json (1.13.1)
|
87
|
+
multipart-post (2.0.0)
|
88
|
+
nokogiri (1.10.0)
|
89
|
+
mini_portile2 (~> 2.4.0)
|
90
|
+
octokit (4.13.0)
|
91
|
+
sawyer (~> 0.8.0, >= 0.5.3)
|
92
|
+
parallel (1.12.1)
|
93
|
+
parser (2.5.3.0)
|
94
|
+
ast (~> 2.4.0)
|
95
|
+
powerpack (0.1.2)
|
96
|
+
pry (0.10.4)
|
97
|
+
coderay (~> 1.1.0)
|
98
|
+
method_source (~> 0.8.1)
|
99
|
+
slop (~> 3.4)
|
100
|
+
pry-nav (0.2.4)
|
101
|
+
pry (>= 0.9.10, < 0.11.0)
|
102
|
+
public_suffix (3.0.3)
|
103
|
+
rack (2.0.6)
|
104
|
+
rack-test (1.1.0)
|
105
|
+
rack (>= 1.0, < 3)
|
106
|
+
rails-dom-testing (2.0.3)
|
107
|
+
activesupport (>= 4.2.0)
|
108
|
+
nokogiri (>= 1.6)
|
109
|
+
rails-html-sanitizer (1.0.4)
|
110
|
+
loofah (~> 2.2, >= 2.2.2)
|
111
|
+
railties (5.2.2)
|
112
|
+
actionpack (= 5.2.2)
|
113
|
+
activesupport (= 5.2.2)
|
114
|
+
method_source
|
115
|
+
rake (>= 0.8.7)
|
116
|
+
thor (>= 0.19.0, < 2.0)
|
117
|
+
rainbow (2.2.2)
|
118
|
+
rake
|
119
|
+
rake (10.5.0)
|
120
|
+
retriable (2.1.0)
|
121
|
+
rspec (3.8.0)
|
122
|
+
rspec-core (~> 3.8.0)
|
123
|
+
rspec-expectations (~> 3.8.0)
|
124
|
+
rspec-mocks (~> 3.8.0)
|
125
|
+
rspec-core (3.8.0)
|
126
|
+
rspec-support (~> 3.8.0)
|
127
|
+
rspec-expectations (3.8.2)
|
128
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
129
|
+
rspec-support (~> 3.8.0)
|
130
|
+
rspec-mocks (3.8.0)
|
131
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
132
|
+
rspec-support (~> 3.8.0)
|
133
|
+
rspec-rails (3.8.1)
|
134
|
+
actionpack (>= 3.0)
|
135
|
+
activesupport (>= 3.0)
|
136
|
+
railties (>= 3.0)
|
137
|
+
rspec-core (~> 3.8.0)
|
138
|
+
rspec-expectations (~> 3.8.0)
|
139
|
+
rspec-mocks (~> 3.8.0)
|
140
|
+
rspec-support (~> 3.8.0)
|
141
|
+
rspec-support (3.8.0)
|
142
|
+
rubocop (0.61.0)
|
143
|
+
jaro_winkler (~> 1.5.1)
|
144
|
+
parallel (~> 1.10)
|
145
|
+
parser (>= 2.5, != 2.5.1.1)
|
146
|
+
powerpack (~> 0.1)
|
147
|
+
rainbow (>= 2.2.2, < 4.0)
|
148
|
+
ruby-progressbar (~> 1.7)
|
149
|
+
unicode-display_width (~> 1.4.0)
|
150
|
+
rubocop-rspec (1.20.1)
|
151
|
+
rubocop (>= 0.51.0)
|
152
|
+
ruby-progressbar (1.10.0)
|
153
|
+
rugged (0.27.7)
|
154
|
+
sawyer (0.8.1)
|
155
|
+
addressable (>= 2.3.5, < 2.6)
|
156
|
+
faraday (~> 0.8, < 1.0)
|
157
|
+
simplecov (0.16.1)
|
158
|
+
docile (~> 1.1)
|
159
|
+
json (>= 1.8, < 3)
|
160
|
+
simplecov-html (~> 0.10.0)
|
161
|
+
simplecov-html (0.10.2)
|
162
|
+
simplecov-lcov (0.7.0)
|
163
|
+
slop (3.6.0)
|
164
|
+
sqlite3 (1.3.13)
|
165
|
+
thor (0.20.3)
|
166
|
+
thread_safe (0.3.6)
|
167
|
+
tzinfo (1.2.5)
|
168
|
+
thread_safe (~> 0.1)
|
169
|
+
undercover (0.3.0)
|
170
|
+
imagen (~> 0.1.5)
|
171
|
+
rainbow (~> 2.1)
|
172
|
+
rugged (~> 0.27.0)
|
173
|
+
unicode-display_width (1.4.1)
|
174
|
+
with_model (2.1.2)
|
175
|
+
activerecord (>= 4.2, < 6.0)
|
176
|
+
|
177
|
+
PLATFORMS
|
178
|
+
ruby
|
179
|
+
|
180
|
+
DEPENDENCIES
|
181
|
+
activerecord
|
182
|
+
ams_lazy_relationships!
|
183
|
+
appraisal
|
184
|
+
bundler (~> 1.17)
|
185
|
+
db-query-matchers
|
186
|
+
github_changelog_generator
|
187
|
+
pry
|
188
|
+
pry-nav
|
189
|
+
rake (~> 10.0)
|
190
|
+
rspec (~> 3.0)
|
191
|
+
rspec-rails (~> 3.5)
|
192
|
+
rubocop (= 0.61.0)
|
193
|
+
rubocop-rspec (= 1.20.1)
|
194
|
+
simplecov
|
195
|
+
simplecov-lcov
|
196
|
+
sqlite3 (~> 1.3)
|
197
|
+
undercover
|
198
|
+
with_model (~> 2.0)
|
199
|
+
|
200
|
+
BUNDLED WITH
|
201
|
+
1.17.1
|
data/README.md
CHANGED
@@ -18,22 +18,22 @@ In many cases it's fine to use [`includes`](https://apidock.com/rails/ActiveReco
|
|
18
18
|
There are a few problems with `includes` approach though:
|
19
19
|
- It loads all the records provided in the arguments hash. Often you may not need all the nested records to serialize the data you want. `AmsLazyRelationships` will load only the data you need thanks to lazy evaluation.
|
20
20
|
- When the app gets bigger and bigger you'd need to update all the `includes` statements across your app to prevent the N+1 queries problem which quickly becomes impossible.
|
21
|
+
- It lets you remove N+1s even when not all relationships are ActiveRecord models (e.g. some records are stored in a MySQL DB and other models are stored in Cassandra)
|
21
22
|
|
22
23
|
## Installation
|
23
24
|
|
24
|
-
Add this line to your application's Gemfile:
|
25
|
+
1. Add this line to your application's Gemfile:
|
25
26
|
|
26
27
|
```ruby
|
27
28
|
gem "ams_lazy_relationships"
|
28
29
|
```
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
## Installation
|
31
|
+
2. Execute:
|
32
|
+
```
|
33
|
+
$ bundle
|
34
|
+
```
|
35
35
|
|
36
|
-
Include `AmsLazyRelationships::Core` module in your base serializer
|
36
|
+
3. Include `AmsLazyRelationships::Core` module in your base serializer
|
37
37
|
|
38
38
|
```ruby
|
39
39
|
class BaseSerializer < ActiveModel::Serializer
|
@@ -41,19 +41,19 @@ class BaseSerializer < ActiveModel::Serializer
|
|
41
41
|
end
|
42
42
|
```
|
43
43
|
|
44
|
-
**Important:**
|
44
|
+
4. **Important:**
|
45
45
|
This gem uses `BatchLoader` heavily. I highly recommend to clear the batch loader's cache between HTTP requests.
|
46
46
|
To do so add a following middleware:
|
47
|
-
`use BatchLoader::Middleware`
|
47
|
+
`config.middleware.use BatchLoader::Middleware` to your app's `application.rb`.
|
48
48
|
|
49
49
|
For more info about the middleware check out BatchLoader gem docs: https://github.com/exAspArk/batch-loader#caching
|
50
50
|
|
51
|
-
|
51
|
+
## Usage
|
52
52
|
Adding the `AmsLazyRelationships::Core` module lets you define lazy relationships in your serializers:
|
53
53
|
```ruby
|
54
54
|
|
55
55
|
class UserSerializer < BaseSerializer
|
56
|
-
# Short version - preloads a specified ActiveRecord
|
56
|
+
# Short version - preloads a specified ActiveRecord relationship by default
|
57
57
|
lazy_has_many :blog_posts
|
58
58
|
|
59
59
|
# Works same as the previous one, but the loader option is specified explicitly
|
@@ -72,7 +72,7 @@ class UserSerializer < BaseSerializer
|
|
72
72
|
lazy_belongs_to :account, loader: AmsLazyRelationships::Loaders::SimpleBelongsTo.new("Account")
|
73
73
|
|
74
74
|
lazy_has_many :comment, loader: AmsLazyRelationships::Loaders::SimpleHasMany.new("Comment", foreign_key: :user_id)
|
75
|
-
|
75
|
+
end
|
76
76
|
```
|
77
77
|
|
78
78
|
As you may have already noticed the gem makes use of various loader classes.
|
@@ -93,6 +93,76 @@ You can use it like this: `AmsLazyRelationships::Loaders::Direct.new(:poro_model
|
|
93
93
|
The abovementioned loaders are mostly useful when using ActiveRecord, but there should be no problem building a new loader for different frameworks.
|
94
94
|
If you're missing a loader you can create an issue or create your own loader taking the existing ones as an example.
|
95
95
|
|
96
|
+
### More examples
|
97
|
+
Here are a few use cases for the lazy relationships. Hopefully they'll let you understand a bit more how the gem works.
|
98
|
+
|
99
|
+
#### Example 1: Basic ActiveRecord relationships
|
100
|
+
If the relationships in your serializers are plain old ActiveRecord relationships you're lucky, because ams_lazy_relationships by default assumes that the relationship is an ActiveRecord relationship, so you can use the simplest syntax.
|
101
|
+
Imagine you have an endpoint that renders a list of blog posts and includes their comments.
|
102
|
+
The N+1 prone way of defining the serializer would be:
|
103
|
+
```ruby
|
104
|
+
class BlogPostSerializer < BaseSerializer
|
105
|
+
has_many :comments
|
106
|
+
end
|
107
|
+
```
|
108
|
+
|
109
|
+
To prevent loading comments using a separate DB query for each post just change it to:
|
110
|
+
```ruby
|
111
|
+
class BlogPostSerializer < BaseSerializer
|
112
|
+
lazy_has_many :comments
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
#### Example 2: Modifying the relationship before rendering
|
117
|
+
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
|
+
|
119
|
+
```ruby
|
120
|
+
class BlogPostSerializer < BaseSerializer
|
121
|
+
lazy_has_many :comments do
|
122
|
+
lazy_comments.map(&:decorate)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
```
|
126
|
+
|
127
|
+
#### Example 3: Introducing loader classes
|
128
|
+
Under the hood ams_lazy_relationships uses special loader classes to batch load the relationships. By default the gem uses serializer class names and relationship names to instantiate correct loaders, but it may happen that e.g. your serializer's class name doesn't match the model name (e.g. your model's name is `BlogPost` but the serializer's name is `PostSerializer`).
|
129
|
+
|
130
|
+
In this case you can define the lazy relationship by passing a correct loader param:
|
131
|
+
```ruby
|
132
|
+
class PostSerializer < BaseSerializer
|
133
|
+
lazy_has_many :comments, serializer: CommentSerializer,
|
134
|
+
loader: AmsLazyRelationships::Loaders::Association.new(
|
135
|
+
"BlogPost", :comments
|
136
|
+
)
|
137
|
+
end
|
138
|
+
```
|
139
|
+
|
140
|
+
#### Example 4: Non ActiveRecord -> ActiveRecord relationships
|
141
|
+
This one is interesting. It may happen that the root record is not an ActiveRecord model (e.g. a Cequel model), however its relationship is an AR model.
|
142
|
+
Imagine that `BlogPost` is not an AR model and `Comment` is a standard AR model. The lazy relationship would look like this:
|
143
|
+
```ruby
|
144
|
+
class BlogPostSerializer < BaseSerializer
|
145
|
+
lazy_has_many :comments,
|
146
|
+
loader: AmsLazyRelationships::Loaders::SimpleHasMany.new(
|
147
|
+
"Comment", foreign_key: :blog_post_id
|
148
|
+
)
|
149
|
+
end
|
150
|
+
```
|
151
|
+
|
152
|
+
#### Example 5: Use lazy relationship without rendering it
|
153
|
+
Sometimes you may just want to make use of lazy relationship without rendering the whole nested record.
|
154
|
+
For example imagine that your `BlogPost` serializer is supposed to render `author_name` attribute. You can define the lazy relationship and just use it in other attribute evaluator:
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
class BlogPostSerializer < BaseSerializer
|
158
|
+
lazy_relationship :author
|
159
|
+
|
160
|
+
attribute :author_name do
|
161
|
+
lazy_author.name
|
162
|
+
end
|
163
|
+
end
|
164
|
+
```
|
165
|
+
|
96
166
|
## Development
|
97
167
|
|
98
168
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/Rakefile
CHANGED
@@ -34,7 +34,7 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.require_paths = ["lib"]
|
35
35
|
|
36
36
|
spec.add_dependency "active_model_serializers"
|
37
|
-
spec.add_dependency "batch-loader", "
|
37
|
+
spec.add_dependency "batch-loader", "~> 1.2"
|
38
38
|
|
39
39
|
spec.add_development_dependency "activerecord"
|
40
40
|
# A Ruby library for testing against different versions of dependencies
|
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.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Bajena
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: active_model_serializers
|
@@ -28,16 +28,16 @@ dependencies:
|
|
28
28
|
name: batch-loader
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.2
|
33
|
+
version: '1.2'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.2
|
40
|
+
version: '1.2'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: activerecord
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|