api-blocks 0.4.11 → 0.5.0

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: 213ea14d1ace477c4e700647a5574a5a9024c62185a9a2e5b656a2ed7b2f3eb0
4
- data.tar.gz: 74cf4dd8fb59ff2441e0effa5217b200e6cb4bf4e2539c3882709e93bb46a7d4
3
+ metadata.gz: 710664013c6c921b9bdfe46c1598143edd489eddcdfc1519f13fb2625462640a
4
+ data.tar.gz: 245c76d099c43ffa562ed68bbc387deb49d7fd96814ed294eee1eccbf1b3adad
5
5
  SHA512:
6
- metadata.gz: 648bc25b3c823f66c65edf674e283eb24803d9f9af7afc00e6a8b6683c66099b00510c775d4a66658a4fea2b01f8cd47a380b61e1870889815dd76f0f6523f99
7
- data.tar.gz: 87e3687c96f08d74ff264761a89f2642277e58d73da5acf910e035347aa89b62358a0f687ddd4aab3a177a8dd39b0a99bb4cc7ee1b2019895a96d14c304fbe44
6
+ metadata.gz: 471441ab9dab08080f516f2a8427938f739154b91f24dd0378f48634f9b4bf444e9103af4c6d49905002d847d9b03a2dab1f0f87edafa7661ad2163f00e12272
7
+ data.tar.gz: 3273523f2ecc5997e7cc0ea04eb8bfc7e88b75723293cd1268b7cf21fd6c07ff45daf969402c0245ddde8eb33753fc25546ca851163f946bd233fddbdbb63c1d
data/lib/api_blocks.rb CHANGED
@@ -3,6 +3,8 @@
3
3
  require 'rubygems'
4
4
  require 'bundler/setup'
5
5
 
6
+ require 'dry/configurable'
7
+
6
8
  require 'api_blocks/version'
7
9
  require 'active_support/concern'
8
10
  require 'active_support/dependencies/autoload'
@@ -15,6 +17,12 @@ module ApiBlocks
15
17
  autoload :Responder
16
18
  autoload :Interactor
17
19
  autoload :Doorkeeper
20
+
21
+ extend Dry::Configurable
22
+
23
+ setting :blueprinter do
24
+ setting :use_batch_loader, false
25
+ end
18
26
  end
19
27
 
20
28
  require 'api_blocks/railtie' if defined?(Rails)
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Monkey-patch Blueprinter::AssociationExtractor to use `batch-loader` gem in
4
+ # order to avoid n+1 queries when serializing associations.
5
+ #
6
+ # This does not support associations defined using a `proc` as
7
+ # `options[:blueprint]`
8
+ #
9
+ class Blueprinter::AssociationExtractor < Blueprinter::Extractor
10
+ def extract(association_name, object, local_options, options = {})
11
+ if options[:blueprint].is_a?(Proc)
12
+ raise "Cannot load blueprints with a `proc` blueprint option with batch-loader"
13
+ end
14
+
15
+ association = object.association(association_name)
16
+
17
+ join_key = association.reflection.join_keys
18
+ association_id = object.send(join_key.foreign_key)
19
+ association_klass = association.reflection.class_name
20
+
21
+ default_value = case association
22
+ when ActiveRecord::Associations::HasManyAssociation
23
+ []
24
+ end
25
+
26
+ view = options[:view] || :default
27
+
28
+ BatchLoader.for(association_id).batch(
29
+ default_value: default_value,
30
+ key: [association_name, association_klass, view, options[:blueprint]],
31
+ ) do |ids, loader, _args|
32
+ model = association_klass.safe_constantize
33
+
34
+ case association
35
+ when ActiveRecord::Associations::HasManyAssociation
36
+ model.where(join_key.key => ids).each do |record|
37
+ loader.call(record.send(join_key.key)) do |memo|
38
+ memo << render_blueprint(record, local_options, options)
39
+ end
40
+ end
41
+ when ActiveRecord::Associations::HasOneAssociation
42
+ model.where(join_key.key => ids).each do |record|
43
+ loader.call(
44
+ record.send(join_key.key),
45
+ render_blueprint(record, local_options, options)
46
+ )
47
+ end
48
+ when ActiveRecord::Associations::BelongsToAssociation
49
+ model.where(join_key.key => ids).each do |record|
50
+ loader.call(
51
+ record.id,
52
+ render_blueprint(record, local_options, options)
53
+ )
54
+ end
55
+ else
56
+ raise "unsupported association kind #{association.class.name}"
57
+ end
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def render_blueprint(value, local_options, options = {})
64
+ return default_value(options) if value.nil?
65
+
66
+ view = options[:view] || :default
67
+ blueprint = association_blueprint(options[:blueprint], value)
68
+ blueprint.prepare(value, view_name: view, local_options: local_options)
69
+ end
70
+ end
@@ -11,4 +11,12 @@ class ApiBlocks::Railtie < Rails::Railtie
11
11
  require_relative 'doorkeeper/passwords/migration_generator'
12
12
  require_relative 'doorkeeper/invitations/migration_generator'
13
13
  end
14
+
15
+ initializer "blueprinter.batch_loader_integration" do |app|
16
+ app.config.after_initialize do
17
+ next unless ApiBlocks.config.blueprinter.use_batch_loader
18
+
19
+ require_relative "blueprinter/association_extractor"
20
+ end
21
+ end
14
22
  end
@@ -67,7 +67,7 @@ class ApiBlocks::Responder < ActionController::Responder
67
67
  super
68
68
  end
69
69
 
70
- def json_resource_errors
70
+ def json_sesource_errors
71
71
  [{ errors: resource.errors }, :unprocessable_entity]
72
72
  end
73
73
 
@@ -2,5 +2,5 @@
2
2
 
3
3
  module ApiBlocks
4
4
  # Current version of ApiBlocks
5
- VERSION = "0.4.11"
5
+ VERSION = "0.5.0"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api-blocks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.11
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul d'Hubert
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: 3.0.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: dry-configurable
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.8'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.8'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: bundler
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -256,6 +270,7 @@ extra_rdoc_files: []
256
270
  files:
257
271
  - lib/api-blocks.rb
258
272
  - lib/api_blocks.rb
273
+ - lib/api_blocks/blueprinter/association_extractor.rb
259
274
  - lib/api_blocks/controller.rb
260
275
  - lib/api_blocks/doorkeeper.rb
261
276
  - lib/api_blocks/doorkeeper/invitations.rb