blueprinter-activerecord 1.1.0 → 1.3.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 +4 -4
- data/lib/blueprinter-activerecord/added_preloads_logger.rb +1 -1
- data/lib/blueprinter-activerecord/missing_preloads_logger.rb +1 -1
- data/lib/blueprinter-activerecord/preloader.rb +42 -10
- data/lib/blueprinter-activerecord/query_methods.rb +1 -1
- data/lib/blueprinter-activerecord/version.rb +1 -1
- data/lib/tasks/blueprinter_activerecord.rake +1 -1
- metadata +2 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dbbbb6e1ad95d2a01cfbea311786b853dbc9897b95e66aa7724f3c514d2c0c53
|
4
|
+
data.tar.gz: 1df369b58caf6f83b9c5779d3f111bb1484c5e1feb8e8738e494f20e6de25332
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f13e0c074ac8b7a3348aad0d80bdd98a37adc6505eb93bc2980992b93b6fc0f98c294c9800959a4820ed427e74b55b0ad991bc0ce33ef389ce68b763360e85c3
|
7
|
+
data.tar.gz: 9b3ebe8b99baba740f2fdfb369f9f8fe84d118506b72f9fc60253e2a61dce5ceb92078ddc490f9a59b3ef7e45b9969f62b1db6cd5f862d885c8985e46784f0c7
|
@@ -42,7 +42,7 @@ module BlueprinterActiveRecord
|
|
42
42
|
def pre_render(object, blueprint, view, options)
|
43
43
|
if object.is_a?(ActiveRecord::Relation) && object.before_preload_blueprint
|
44
44
|
from_code = object.before_preload_blueprint
|
45
|
-
from_blueprint = Preloader.preloads(blueprint, view, object.model)
|
45
|
+
from_blueprint = Preloader.preloads(blueprint, view, model: object.model)
|
46
46
|
info = PreloadInfo.new(object, from_code, from_blueprint, caller)
|
47
47
|
@log_proc&.call(info)
|
48
48
|
end
|
@@ -39,7 +39,7 @@ module BlueprinterActiveRecord
|
|
39
39
|
def pre_render(object, blueprint, view, options)
|
40
40
|
if object.is_a?(ActiveRecord::Relation) && !object.before_preload_blueprint
|
41
41
|
from_code = extract_preloads object
|
42
|
-
from_blueprint = Preloader.preloads(blueprint, view, object.model)
|
42
|
+
from_blueprint = Preloader.preloads(blueprint, view, model: object.model)
|
43
43
|
info = PreloadInfo.new(object, from_code, from_blueprint, caller)
|
44
44
|
@log_proc&.call(info)
|
45
45
|
end
|
@@ -4,6 +4,7 @@ module BlueprinterActiveRecord
|
|
4
4
|
# A Blueprinter extension to automatically preload a Blueprint view's ActiveRecord associations during render
|
5
5
|
class Preloader < Blueprinter::Extension
|
6
6
|
include Helpers
|
7
|
+
DEFAULT_MAX_RECURSION = 10
|
7
8
|
|
8
9
|
attr_reader :use, :auto, :auto_proc
|
9
10
|
|
@@ -37,11 +38,10 @@ module BlueprinterActiveRecord
|
|
37
38
|
# intelligently handles them. There are several unit tests which confirm this behavior.
|
38
39
|
#
|
39
40
|
def pre_render(object, blueprint, view, options)
|
40
|
-
|
41
|
-
when "ActiveRecord::Relation", "ActiveRecord::AssociationRelation"
|
41
|
+
if object.is_a?(ActiveRecord::Relation) && !object.loaded?
|
42
42
|
if object.preload_blueprint_method || auto || auto_proc&.call(object, blueprint, view, options) == true
|
43
43
|
object.before_preload_blueprint = extract_preloads object
|
44
|
-
blueprint_preloads = self.class.preloads(blueprint, view, object.model)
|
44
|
+
blueprint_preloads = self.class.preloads(blueprint, view, model: object.model)
|
45
45
|
loader = object.preload_blueprint_method || use
|
46
46
|
object.public_send(loader, blueprint_preloads)
|
47
47
|
else
|
@@ -63,22 +63,21 @@ module BlueprinterActiveRecord
|
|
63
63
|
#
|
64
64
|
# Example:
|
65
65
|
#
|
66
|
-
# preloads = BlueprinterActiveRecord::Preloader.preloads(WidgetBlueprint, :extended, Widget)
|
66
|
+
# preloads = BlueprinterActiveRecord::Preloader.preloads(WidgetBlueprint, :extended, model: Widget)
|
67
67
|
# q = Widget.where(...).order(...).preload(preloads)
|
68
68
|
#
|
69
69
|
# @param blueprint [Class] The Blueprint class
|
70
70
|
# @param view_name [Symbol] Name of the view in blueprint
|
71
|
-
# @param model [Class] The ActiveRecord model class that blueprint represents
|
71
|
+
# @param model [Class|:polymorphic] The ActiveRecord model class that blueprint represents
|
72
|
+
# @param cycles [Hash<String, Integer>] (internal) Preloading will halt if recursion/cycles gets too high
|
72
73
|
# @return [Hash] A Hash containing preload/eager_load/etc info for ActiveRecord
|
73
74
|
#
|
74
|
-
def self.preloads(blueprint, view_name, model
|
75
|
+
def self.preloads(blueprint, view_name, model:, cycles: {})
|
75
76
|
view = blueprint.reflections.fetch(view_name)
|
76
77
|
preload_vals = view.associations.each_with_object({}) { |(_name, assoc), acc|
|
77
78
|
# look for a matching association on the model
|
78
|
-
|
79
|
-
|
80
|
-
ref_model = ref && !(ref.belongs_to? && ref.polymorphic?) ? ref.klass : nil
|
81
|
-
acc[assoc.name] = preloads(assoc.blueprint, assoc.view, ref_model)
|
79
|
+
if (preload = association_preloads(assoc, model, cycles))
|
80
|
+
acc[assoc.name] = preload
|
82
81
|
end
|
83
82
|
|
84
83
|
# look for a :preload option on the association
|
@@ -94,5 +93,38 @@ module BlueprinterActiveRecord
|
|
94
93
|
end
|
95
94
|
}
|
96
95
|
end
|
96
|
+
|
97
|
+
def self.association_preloads(assoc, model, cycles)
|
98
|
+
max_cycles = assoc.options.fetch(:max_recursion, DEFAULT_MAX_RECURSION)
|
99
|
+
if model == :polymorphic
|
100
|
+
if assoc.blueprint.is_a? Proc
|
101
|
+
{}
|
102
|
+
else
|
103
|
+
cycles, count = count_cycles(assoc.blueprint, assoc.view, cycles)
|
104
|
+
count < max_cycles ? preloads(assoc.blueprint, assoc.view, model: model, cycles: cycles) : {}
|
105
|
+
end
|
106
|
+
elsif (ref = model.reflections[assoc.name.to_s])
|
107
|
+
if assoc.blueprint.is_a? Proc
|
108
|
+
{}
|
109
|
+
elsif ref.belongs_to? && ref.polymorphic?
|
110
|
+
cycles, count = count_cycles(assoc.blueprint, assoc.view, cycles)
|
111
|
+
count < max_cycles ? preloads(assoc.blueprint, assoc.view, model: :polymorphic, cycles: cycles) : {}
|
112
|
+
else
|
113
|
+
cycles, count = count_cycles(assoc.blueprint, assoc.view, cycles)
|
114
|
+
count < max_cycles ? preloads(assoc.blueprint, assoc.view, model: ref.klass, cycles: cycles) : {}
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.count_cycles(blueprint, view, cycles)
|
120
|
+
id = "#{blueprint.name || blueprint.inspect}/#{view}"
|
121
|
+
cycles = cycles.dup
|
122
|
+
if cycles[id].nil?
|
123
|
+
cycles[id] = 0
|
124
|
+
else
|
125
|
+
cycles[id] += 1
|
126
|
+
end
|
127
|
+
return cycles, cycles[id]
|
128
|
+
end
|
97
129
|
end
|
98
130
|
end
|
@@ -43,7 +43,7 @@ module BlueprinterActiveRecord
|
|
43
43
|
|
44
44
|
if blueprint and view
|
45
45
|
# preload right now
|
46
|
-
preloads = Preloader.preloads(blueprint, view, model)
|
46
|
+
preloads = Preloader.preloads(blueprint, view, model: model)
|
47
47
|
public_send(use, preloads)
|
48
48
|
else
|
49
49
|
# preload during render
|
@@ -14,7 +14,7 @@ namespace :blueprinter do
|
|
14
14
|
|
15
15
|
model = args[:model].constantize
|
16
16
|
blueprint = args[:blueprint].constantize
|
17
|
-
preloads = BlueprinterActiveRecord::Preloader.preloads(blueprint, args[:view].to_sym, model)
|
17
|
+
preloads = BlueprinterActiveRecord::Preloader.preloads(blueprint, args[:view].to_sym, model: model)
|
18
18
|
puts pretty preloads
|
19
19
|
end
|
20
20
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blueprinter-activerecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Procore Technologies, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-09-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -17,9 +17,6 @@ dependencies:
|
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '6.0'
|
20
|
-
- - "<"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '7.2'
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -27,9 +24,6 @@ dependencies:
|
|
27
24
|
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '6.0'
|
30
|
-
- - "<"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '7.2'
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: blueprinter
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|