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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 90b648bcd4371a277e27841b52d173fa0951c49a8fa89e1e3894ce1e2c4a0a02
4
- data.tar.gz: effb7e1afb4b609ff812ca1aaf7803eb6e65b2729650399656335fc1adee35a9
3
+ metadata.gz: 6cb1e948873e81d15bbe96e4c15c485d8b2835e8cfb1862966bd99bb69d52f27
4
+ data.tar.gz: e6e726bae63cf87e702131f80984e8021a229b7cc2c54b21031298e7f819cc08
5
5
  SHA512:
6
- metadata.gz: 2d21c76feffd32cfb7950edd49027e0082a91a6473ad6713eb109fdf2285f42091f8bbbf034ab1c4b5a37c5119ae27ce678fd983a73dc99002cb8c832203ef83
7
- data.tar.gz: cac45499b8c4748a80bf91210538216764400ede85f84fcf9afc3f1308f73822edfa0c3cfb5a9dbbc1b45fc48b8bb7a8ea7f720a34a7731a0e19f2b5cb1c16ff
6
+ metadata.gz: 0420e35c4ee39866db944fa381ce731136389f9ab15e4597242a72d03d0fb9b65c904476aa86492c471e73b19bffaf84403986ef15dcf6cd8659b71588c7aa83
7
+ data.tar.gz: e53e6d4c19564899d1643826a158072ca217a4b50d8baf14a7aa38d82ac0097b246008134a18bf24a6dcf84f1f65a92f9a209cd04cb8c0874b5d81795e8c1354
data/.rubocop.yml CHANGED
@@ -1,5 +1,8 @@
1
+ inherit_gem:
2
+ rubocop-shopify: rubocop.yml
3
+
1
4
  AllCops:
2
- TargetRubyVersion: 3.0
5
+ TargetRubyVersion: 3.4
3
6
 
4
7
  Style/StringLiterals:
5
8
  EnforcedStyle: double_quotes
data/Appraisals CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  appraise "rails-7.0" do
2
4
  gem "rails", "~> 7.0.0"
3
5
  end
@@ -12,4 +14,4 @@ end
12
14
 
13
15
  appraise "rails-8" do
14
16
  gem "rails", ">= 8"
15
- end
17
+ end
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
@@ -9,4 +9,4 @@ require "rubocop/rake_task"
9
9
 
10
10
  RuboCop::RakeTask.new
11
11
 
12
- task default: %i[test rubocop]
12
+ task default: [:test, :rubocop]
@@ -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
- (current_selection & reflection.klass.column_names).tally
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
- # TODO describe Branch dedications
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
- !parent.nested_select_values.grep_v(Hash)
22
- .map(&:to_sym).include?(reflection.foreign_key.to_sym)
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
- ).tap do
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
- # nested_select_values = [:id, :title, comments: [:id, :body], cover: [:id, img: [:url]]]
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{_1.apply_nested_select_values(nested_select_values) } # <-- Patching code
35
- .call
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:)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NestedSelect
4
- VERSION = "0.4.4"
4
+ VERSION = "0.5.0"
5
5
  end
data/lib/nested_select.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "logger" # Fix concurrent-ruby removing logger dependency which Rails itself does not have
3
4
  require_relative "nested_select/version"
4
5
 
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.4
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-05-09 00:00:00.000000000 Z
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: minitest
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: rake
84
+ name: byebug
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - ">="
74
88
  - !ruby/object:Gem::Version
75
- version: '10.0'
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: '10.0'
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: sqlite3
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: byebug
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: stubberry
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: rails_sql_prettifier
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: amazing_print
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: rubocop-shopify
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: appraisal
224
+ name: mutex_m
183
225
  requirement: !ruby/object:Gem::Requirement
184
226
  requirements:
185
227
  - - ">="