nested_select 0.4.4 → 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 +4 -4
- data/.rubocop.yml +4 -1
- data/Appraisals +3 -1
- data/CHANGELOG.md +4 -1
- data/Rakefile +1 -1
- data/lib/nested_select/deep_merger.rb +4 -3
- data/lib/nested_select/preloader/association.rb +5 -3
- data/lib/nested_select/preloader/branch.rb +9 -5
- data/lib/nested_select/preloader/through_association.rb +3 -3
- data/lib/nested_select/preloader.rb +5 -3
- data/lib/nested_select/relation.rb +20 -2
- data/lib/nested_select/version.rb +1 -1
- data/lib/nested_select.rb +1 -0
- metadata +55 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6cb1e948873e81d15bbe96e4c15c485d8b2835e8cfb1862966bd99bb69d52f27
|
|
4
|
+
data.tar.gz: e6e726bae63cf87e702131f80984e8021a229b7cc2c54b21031298e7f819cc08
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0420e35c4ee39866db944fa381ce731136389f9ab15e4597242a72d03d0fb9b65c904476aa86492c471e73b19bffaf84403986ef15dcf6cd8659b71588c7aa83
|
|
7
|
+
data.tar.gz: e53e6d4c19564899d1643826a158072ca217a4b50d8baf14a7aa38d82ac0097b246008134a18bf24a6dcf84f1f65a92f9a209cd04cb8c0874b5d81795e8c1354
|
data/.rubocop.yml
CHANGED
data/Appraisals
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
## [0.5.0] - 2025-11-22
|
|
2
|
+
- fixed issue with belongs_to as a root pf the preloading branch and multiple branches
|
|
3
|
+
- partially rubocoped
|
|
4
|
+
|
|
1
5
|
## [0.4.4] - 2025-05-09
|
|
2
6
|
- fixed appraisals and local docker compose
|
|
3
|
-
-
|
|
4
7
|
|
|
5
8
|
## [0.4.3] - 2025-05-09
|
|
6
9
|
- fixed regression on through scopes whenever nested_select_values are blank
|
data/Rakefile
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module NestedSelect
|
|
2
4
|
module DeepMerger
|
|
3
|
-
|
|
4
5
|
# {user_profile: [:zip_code]} + {user_profile: [:bio]} -> { user_profile: [:zip_code, :bio] }
|
|
5
6
|
refine Hash do
|
|
6
7
|
def deep_combine(other)
|
|
7
8
|
merge!(other.except(*keys))
|
|
8
|
-
merge!(other.slice(*keys).map{ |key, value| [key, [self[key], value].flatten.deep_combine_elements]}.to_h
|
|
9
|
+
merge!(other.slice(*keys).map { |key, value| [key, [self[key], value].flatten.deep_combine_elements] }.to_h)
|
|
9
10
|
end
|
|
10
11
|
end
|
|
11
12
|
|
|
@@ -15,4 +16,4 @@ module NestedSelect
|
|
|
15
16
|
end
|
|
16
17
|
end
|
|
17
18
|
end
|
|
18
|
-
end
|
|
19
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module NestedSelect
|
|
2
4
|
module Preloader
|
|
3
5
|
module Association
|
|
@@ -11,13 +13,14 @@ module NestedSelect
|
|
|
11
13
|
@nested_select_values = [*partial_select_values]
|
|
12
14
|
ensure_nesting_selection_integrity!(association_nested_select_values)
|
|
13
15
|
end
|
|
16
|
+
|
|
14
17
|
def reflection_relation_keys_attributes
|
|
15
18
|
foreign_key = reflection.foreign_key unless reflection.is_a?(ActiveRecord::Reflection::BelongsToReflection)
|
|
16
19
|
[*foreign_key, *reflection.klass.primary_key].map(&:to_s)
|
|
17
20
|
end
|
|
18
21
|
|
|
19
22
|
def association_nested_select_values
|
|
20
|
-
this_association_select_values = nested_select_values&.grep_v(Hash)&.map {_1.try(:to_s) }
|
|
23
|
+
this_association_select_values = nested_select_values&.grep_v(Hash)&.map { _1.try(:to_s) }
|
|
21
24
|
return if this_association_select_values.blank?
|
|
22
25
|
|
|
23
26
|
[*this_association_select_values, *reflection_relation_keys_attributes].uniq
|
|
@@ -38,7 +41,7 @@ module NestedSelect
|
|
|
38
41
|
current_selection = nested_select_final_values.grep_v(Hash).map(&:to_s)
|
|
39
42
|
|
|
40
43
|
basic_attributes_matched = (attributes_loaded & reflection.klass.column_names).tally ==
|
|
41
|
-
|
|
44
|
+
(current_selection & reflection.klass.column_names).tally
|
|
42
45
|
|
|
43
46
|
# this is not a 100% safe verification, but it will match cases with custom attributes selection for example:
|
|
44
47
|
# "(SELECT COUNT(*) FROM images) as IMG_count" =~ /img_count/
|
|
@@ -58,4 +61,3 @@ module NestedSelect
|
|
|
58
61
|
end
|
|
59
62
|
end
|
|
60
63
|
end
|
|
61
|
-
|
|
@@ -1,25 +1,29 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# TODO: describe Branch dedications
|
|
2
4
|
module NestedSelect
|
|
3
5
|
module Preloader
|
|
4
6
|
module Branch
|
|
5
7
|
attr_accessor :nested_select_values
|
|
8
|
+
|
|
6
9
|
def preloaders_for_reflection(reflection, reflection_records)
|
|
7
10
|
prevent_belongs_to_foreign_key_absence!(reflection)
|
|
8
11
|
|
|
9
12
|
super.tap do |ldrs|
|
|
10
13
|
# nested_select_values contains current level selection + nested relation selections
|
|
11
|
-
ldrs.each{ _1.apply_nested_select_values(nested_select_values) } if nested_select_values.present?
|
|
14
|
+
ldrs.each { _1.apply_nested_select_values(nested_select_values) } if nested_select_values.present?
|
|
12
15
|
end
|
|
13
16
|
end
|
|
14
17
|
|
|
15
18
|
private
|
|
19
|
+
|
|
16
20
|
def prevent_belongs_to_foreign_key_absence!(reflection)
|
|
17
21
|
return unless reflection.is_a?(ActiveRecord::Reflection::BelongsToReflection)
|
|
18
22
|
|
|
19
23
|
# ActiveRecord will not raise in case its missing, so we should prevent silent error here
|
|
20
24
|
if parent.nested_select_values.present? &&
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
!parent.nested_select_values.grep_v(Hash)
|
|
26
|
+
.map(&:to_sym).include?(reflection.foreign_key.to_sym)
|
|
23
27
|
|
|
24
28
|
raise ActiveModel::MissingAttributeError, <<~ERR
|
|
25
29
|
Parent reflection #{parent.association} was missing foreign key #{reflection.foreign_key} in nested selection,
|
|
@@ -30,4 +34,4 @@ module NestedSelect
|
|
|
30
34
|
end
|
|
31
35
|
end
|
|
32
36
|
end
|
|
33
|
-
end
|
|
37
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module NestedSelect
|
|
2
4
|
module Preloader
|
|
3
5
|
module ThroughAssociation
|
|
@@ -7,7 +9,7 @@ module NestedSelect
|
|
|
7
9
|
associations: through_reflection.name,
|
|
8
10
|
scope: through_scope,
|
|
9
11
|
associate_by_default: false,
|
|
10
|
-
|
|
12
|
+
).tap do
|
|
11
13
|
_1.apply_nested_select_values(nested_select_values&.grep(Hash))
|
|
12
14
|
end.loaders
|
|
13
15
|
end
|
|
@@ -16,8 +18,6 @@ module NestedSelect
|
|
|
16
18
|
foreign_key = reflection.foreign_key unless reflection.parent_reflection.is_a?(ActiveRecord::Reflection::HasAndBelongsToManyReflection)
|
|
17
19
|
[*foreign_key, *reflection.klass.primary_key].map(&:to_s)
|
|
18
20
|
end
|
|
19
|
-
|
|
20
21
|
end
|
|
21
22
|
end
|
|
22
23
|
end
|
|
23
|
-
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module NestedSelect
|
|
2
4
|
module Preloader
|
|
3
5
|
extend ActiveSupport::Autoload
|
|
@@ -13,13 +15,13 @@ module NestedSelect
|
|
|
13
15
|
ActiveRecord::Associations::Preloader::Association.prepend(Association)
|
|
14
16
|
end
|
|
15
17
|
|
|
16
|
-
# first one will start from the roots [included_1: [{}], included_2: [{}]
|
|
18
|
+
# first one will start from the roots [{included_1: [{}], included_2: [{}]}]
|
|
17
19
|
def apply_nested_select_values(nested_select_values)
|
|
18
20
|
distribute_nested_select_over_loading_tree(@tree, nested_select_values)
|
|
19
21
|
end
|
|
20
22
|
|
|
21
23
|
def distribute_nested_select_over_loading_tree(sub_tree, nested_select_values)
|
|
22
|
-
#
|
|
24
|
+
# Ex: nested_select_values = [:id, :title, comments: [:id, :body], cover: [:id, img: [:url]]]
|
|
23
25
|
return if nested_select_values.blank?
|
|
24
26
|
|
|
25
27
|
sub_tree.nested_select_values = [*nested_select_values.grep_v(Hash)]
|
|
@@ -40,4 +42,4 @@ module NestedSelect
|
|
|
40
42
|
end
|
|
41
43
|
end
|
|
42
44
|
end
|
|
43
|
-
end
|
|
45
|
+
end
|
|
@@ -25,16 +25,34 @@ module NestedSelect
|
|
|
25
25
|
# end
|
|
26
26
|
# end
|
|
27
27
|
|
|
28
|
+
# this is copy of the original ActiveRecord::Relation#preload_associations method
|
|
29
|
+
# the only patching I' doing -- streaming down nested_select_values over the preloading trees
|
|
28
30
|
def preload_associations(records) # :nodoc:
|
|
29
31
|
preload = preload_values
|
|
30
32
|
preload += includes_values unless eager_loading?
|
|
31
33
|
scope = strict_loading_value ? StrictLoadingScope : nil
|
|
32
34
|
preload.each do |associations|
|
|
33
35
|
ActiveRecord::Associations::Preloader.new(records:, associations:, scope:)
|
|
34
|
-
.tap
|
|
35
|
-
|
|
36
|
+
.tap do# <-- Patching code goes here
|
|
37
|
+
# at this moment nested_select_values will have a structure of an array of one hash element,
|
|
38
|
+
# with multiple keys matching those in associations, so we need to separate them per branch
|
|
39
|
+
if nested_select_values.present?
|
|
40
|
+
# associations will have a structure of either tree like hash or str/sym
|
|
41
|
+
# Ex: includes(:relation1, relation2: :nested_relation)
|
|
42
|
+
# associations will be either :relation1 or { relation2: :nested_relation }
|
|
43
|
+
root_association_name = (associations.try(:keys) || associations.try(:to_sym) || associations)
|
|
44
|
+
# nested_select_values, after deep_combine_elements
|
|
45
|
+
# will have structure of an array of single element at this moment:
|
|
46
|
+
# [{relation1: [columns..], relation2: [columns, nested_relation: [columns]] }]
|
|
47
|
+
# so we need to populate nested_select_values over associations branch
|
|
48
|
+
_1.apply_nested_select_values([nested_select_values.first.slice(*root_association_name)])
|
|
49
|
+
end
|
|
50
|
+
end.call
|
|
36
51
|
end
|
|
37
52
|
end
|
|
38
53
|
end
|
|
39
54
|
|
|
40
55
|
end
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# ActiveRecord::Associations::Preloader.new(records:, associations:, scope:)
|
data/lib/nested_select.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: nested_select
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- alekseyl
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-
|
|
11
|
+
date: 2025-11-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -39,7 +39,21 @@ dependencies:
|
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '7'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
42
|
+
name: amazing_print
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: appraisal
|
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
|
44
58
|
requirements:
|
|
45
59
|
- - ">="
|
|
@@ -67,19 +81,33 @@ dependencies:
|
|
|
67
81
|
- !ruby/object:Gem::Version
|
|
68
82
|
version: '1.11'
|
|
69
83
|
- !ruby/object:Gem::Dependency
|
|
70
|
-
name:
|
|
84
|
+
name: byebug
|
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
|
72
86
|
requirements:
|
|
73
87
|
- - ">="
|
|
74
88
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: '
|
|
89
|
+
version: '0'
|
|
76
90
|
type: :development
|
|
77
91
|
prerelease: false
|
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
93
|
requirements:
|
|
80
94
|
- - ">="
|
|
81
95
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '
|
|
96
|
+
version: '0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: minitest
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0'
|
|
83
111
|
- !ruby/object:Gem::Dependency
|
|
84
112
|
name: rails-i18n
|
|
85
113
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -95,7 +123,7 @@ dependencies:
|
|
|
95
123
|
- !ruby/object:Gem::Version
|
|
96
124
|
version: '4'
|
|
97
125
|
- !ruby/object:Gem::Dependency
|
|
98
|
-
name:
|
|
126
|
+
name: rails_sql_prettifier
|
|
99
127
|
requirement: !ruby/object:Gem::Requirement
|
|
100
128
|
requirements:
|
|
101
129
|
- - ">="
|
|
@@ -109,7 +137,21 @@ dependencies:
|
|
|
109
137
|
- !ruby/object:Gem::Version
|
|
110
138
|
version: '0'
|
|
111
139
|
- !ruby/object:Gem::Dependency
|
|
112
|
-
name:
|
|
140
|
+
name: rake
|
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
|
142
|
+
requirements:
|
|
143
|
+
- - ">="
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: '10.0'
|
|
146
|
+
type: :development
|
|
147
|
+
prerelease: false
|
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
149
|
+
requirements:
|
|
150
|
+
- - ">="
|
|
151
|
+
- !ruby/object:Gem::Version
|
|
152
|
+
version: '10.0'
|
|
153
|
+
- !ruby/object:Gem::Dependency
|
|
154
|
+
name: rubocop-shopify
|
|
113
155
|
requirement: !ruby/object:Gem::Requirement
|
|
114
156
|
requirements:
|
|
115
157
|
- - ">="
|
|
@@ -123,7 +165,7 @@ dependencies:
|
|
|
123
165
|
- !ruby/object:Gem::Version
|
|
124
166
|
version: '0'
|
|
125
167
|
- !ruby/object:Gem::Dependency
|
|
126
|
-
name:
|
|
168
|
+
name: sqlite3
|
|
127
169
|
requirement: !ruby/object:Gem::Requirement
|
|
128
170
|
requirements:
|
|
129
171
|
- - ">="
|
|
@@ -137,7 +179,7 @@ dependencies:
|
|
|
137
179
|
- !ruby/object:Gem::Version
|
|
138
180
|
version: '0'
|
|
139
181
|
- !ruby/object:Gem::Dependency
|
|
140
|
-
name:
|
|
182
|
+
name: stubberry
|
|
141
183
|
requirement: !ruby/object:Gem::Requirement
|
|
142
184
|
requirements:
|
|
143
185
|
- - ">="
|
|
@@ -151,7 +193,7 @@ dependencies:
|
|
|
151
193
|
- !ruby/object:Gem::Version
|
|
152
194
|
version: '0'
|
|
153
195
|
- !ruby/object:Gem::Dependency
|
|
154
|
-
name:
|
|
196
|
+
name: bigdecimal
|
|
155
197
|
requirement: !ruby/object:Gem::Requirement
|
|
156
198
|
requirements:
|
|
157
199
|
- - ">="
|
|
@@ -165,7 +207,7 @@ dependencies:
|
|
|
165
207
|
- !ruby/object:Gem::Version
|
|
166
208
|
version: '0'
|
|
167
209
|
- !ruby/object:Gem::Dependency
|
|
168
|
-
name:
|
|
210
|
+
name: drb
|
|
169
211
|
requirement: !ruby/object:Gem::Requirement
|
|
170
212
|
requirements:
|
|
171
213
|
- - ">="
|
|
@@ -179,7 +221,7 @@ dependencies:
|
|
|
179
221
|
- !ruby/object:Gem::Version
|
|
180
222
|
version: '0'
|
|
181
223
|
- !ruby/object:Gem::Dependency
|
|
182
|
-
name:
|
|
224
|
+
name: mutex_m
|
|
183
225
|
requirement: !ruby/object:Gem::Requirement
|
|
184
226
|
requirements:
|
|
185
227
|
- - ">="
|