inquery 1.0.11 → 1.1.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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rubocop.yml +1 -1
  3. data/.github/workflows/ruby.yml +24 -8
  4. data/.gitignore +2 -2
  5. data/.rubocop.yml +4 -0
  6. data/Appraisals +24 -4
  7. data/CHANGELOG.md +38 -0
  8. data/Gemfile +17 -1
  9. data/Gemfile.lock +125 -0
  10. data/LICENSE +1 -1
  11. data/MIGRATION.md +260 -0
  12. data/README.md +14 -8
  13. data/RUBY_VERSION +1 -1
  14. data/Rakefile +4 -11
  15. data/VERSION +1 -1
  16. data/doc/Inquery/Exceptions/Base.html +4 -4
  17. data/doc/Inquery/Exceptions/InvalidRelation.html +4 -4
  18. data/doc/Inquery/Exceptions/UnknownCallSignature.html +4 -4
  19. data/doc/Inquery/Exceptions.html +4 -4
  20. data/doc/Inquery/MethodAccessibleHash.html +431 -0
  21. data/doc/Inquery/Mixins/RawSqlUtils.html +17 -4
  22. data/doc/Inquery/Mixins/RelationValidation/ClassMethods.html +8 -7
  23. data/doc/Inquery/Mixins/RelationValidation.html +9 -8
  24. data/doc/Inquery/Mixins/SchemaValidation/ClassMethods.html +4 -4
  25. data/doc/Inquery/Mixins/SchemaValidation.html +4 -4
  26. data/doc/Inquery/Mixins.html +4 -4
  27. data/doc/Inquery/Query/Chainable.html +207 -90
  28. data/doc/Inquery/Query.html +401 -73
  29. data/doc/Inquery.html +12 -9
  30. data/doc/_index.html +12 -5
  31. data/doc/class_list.html +6 -3
  32. data/doc/css/full_list.css +3 -3
  33. data/doc/css/style.css +6 -0
  34. data/doc/file.README.html +102 -16
  35. data/doc/file_list.html +5 -2
  36. data/doc/frames.html +10 -5
  37. data/doc/index.html +102 -16
  38. data/doc/js/app.js +294 -264
  39. data/doc/js/full_list.js +30 -4
  40. data/doc/method_list.html +48 -21
  41. data/doc/top-level-namespace.html +4 -4
  42. data/gemfiles/rails_5.2.gemfile +1 -0
  43. data/gemfiles/rails_6.0.gemfile +1 -0
  44. data/gemfiles/rails_6.1.gemfile +1 -0
  45. data/gemfiles/rails_7.0.gemfile +1 -0
  46. data/gemfiles/{rails_5.1.gemfile → rails_7.1.gemfile} +2 -1
  47. data/gemfiles/rails_7.2.gemfile +8 -0
  48. data/gemfiles/rails_8.0.gemfile +8 -0
  49. data/gemfiles/rails_8.1.gemfile +8 -0
  50. data/inquery.gemspec +11 -34
  51. data/lib/inquery/method_accessible_hash.rb +45 -0
  52. data/lib/inquery/mixins/raw_sql_utils.rb +32 -6
  53. data/lib/inquery/mixins/relation_validation.rb +1 -1
  54. data/lib/inquery/query/chainable.rb +69 -27
  55. data/lib/inquery/query.rb +67 -14
  56. data/lib/inquery.rb +2 -0
  57. data/test/inquery/error_handling_test.rb +117 -0
  58. data/test/inquery/method_accessible_hash_test.rb +85 -0
  59. data/test/inquery/mixins/raw_sql_utils_test.rb +67 -0
  60. data/test/inquery/query/chainable_test.rb +78 -0
  61. data/test/inquery/query_test.rb +86 -0
  62. data/test/test_helper.rb +11 -0
  63. metadata +30 -129
  64. data/.yardopts +0 -1
data/doc/js/full_list.js CHANGED
@@ -62,8 +62,25 @@ function enableToggles() {
62
62
  evt.stopPropagation();
63
63
  evt.preventDefault();
64
64
  $(this).parent().parent().toggleClass('collapsed');
65
+ $(this).attr('aria-expanded', function (i, attr) {
66
+ return attr == 'true' ? 'false' : 'true'
67
+ });
65
68
  highlight();
66
69
  });
70
+
71
+ // navigation of nested classes using keyboard
72
+ $('#full_list a.toggle').on('keypress',function(evt) {
73
+ // enter key is pressed
74
+ if (evt.which == 13) {
75
+ evt.stopPropagation();
76
+ evt.preventDefault();
77
+ $(this).parent().parent().toggleClass('collapsed');
78
+ $(this).attr('aria-expanded', function (i, attr) {
79
+ return attr == 'true' ? 'false' : 'true'
80
+ });
81
+ highlight();
82
+ }
83
+ });
67
84
  }
68
85
 
69
86
  function populateSearchCache() {
@@ -91,7 +108,7 @@ function enableSearch() {
91
108
  }
92
109
  });
93
110
 
94
- $('#full_list').after("<div id='noresults' style='display:none'></div>");
111
+ $('#full_list').after("<div id='noresults' role='status' style='display: none'></div>");
95
112
  }
96
113
 
97
114
  function ignoredKeyPress(event) {
@@ -154,11 +171,14 @@ function partialSearch(searchString, offset) {
154
171
  function searchDone() {
155
172
  searchTimeout = null;
156
173
  highlight();
157
- if ($('#full_list li:visible').size() === 0) {
158
- $('#noresults').text('No results were found.').hide().fadeIn();
174
+ var found = $('#full_list li:visible').size();
175
+ if (found === 0) {
176
+ $('#noresults').text('No results were found.');
159
177
  } else {
160
- $('#noresults').text('').hide();
178
+ // This is read out to screen readers
179
+ $('#noresults').text('There are ' + found + ' results.');
161
180
  }
181
+ $('#noresults').show();
162
182
  $('#content').removeClass('insearch');
163
183
  }
164
184
 
@@ -188,6 +208,12 @@ function expandTo(path) {
188
208
  $target.addClass('clicked');
189
209
  $target.removeClass('collapsed');
190
210
  $target.parentsUntil('#full_list', 'li').removeClass('collapsed');
211
+
212
+ $target.find('a.toggle').attr('aria-expanded', 'true')
213
+ $target.parentsUntil('#full_list', 'li').each(function(i, el) {
214
+ $(el).find('> div > a.toggle').attr('aria-expanded', 'true');
215
+ });
216
+
191
217
  if($target[0]) {
192
218
  window.scrollTo(window.scrollX, $target.offset().top - 250);
193
219
  highlight();
data/doc/method_list.html CHANGED
@@ -1,5 +1,5 @@
1
1
  <!DOCTYPE html>
2
- <html>
2
+ <html >
3
3
  <head>
4
4
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
5
5
  <meta charset="utf-8" />
@@ -38,7 +38,10 @@
38
38
 
39
39
  </div>
40
40
 
41
- <div id="search">Search: <input type="text" /></div>
41
+ <div id="search">
42
+ <label for="search-class">Search:</label>
43
+ <input id="search-class" type="text" />
44
+ </div>
42
45
  </div>
43
46
 
44
47
  <ul id="full_list" class="method">
@@ -46,7 +49,7 @@
46
49
 
47
50
  <li class="odd ">
48
51
  <div class="item">
49
- <span class='object_link'><a href="Inquery/Query.html#call-instance_method" title="Inquery::Query#call (method)">#call</a></span>
52
+ <span class='object_link'><a href="Inquery/Query.html#call-class_method" title="Inquery::Query.call (method)">call</a></span>
50
53
  <small>Inquery::Query</small>
51
54
  </div>
52
55
  </li>
@@ -54,8 +57,8 @@
54
57
 
55
58
  <li class="even ">
56
59
  <div class="item">
57
- <span class='object_link'><a href="Inquery/Query/Chainable.html#call-instance_method" title="Inquery::Query::Chainable#call (method)">#call</a></span>
58
- <small>Inquery::Query::Chainable</small>
60
+ <span class='object_link'><a href="Inquery/Query.html#call-instance_method" title="Inquery::Query#call (method)">#call</a></span>
61
+ <small>Inquery::Query</small>
59
62
  </div>
60
63
  </li>
61
64
 
@@ -70,7 +73,7 @@
70
73
 
71
74
  <li class="even ">
72
75
  <div class="item">
73
- <span class='object_link'><a href="Inquery/Query.html#call-class_method" title="Inquery::Query.call (method)">call</a></span>
76
+ <span class='object_link'><a href="Inquery/Query.html#connection-instance_method" title="Inquery::Query#connection (method)">#connection</a></span>
74
77
  <small>Inquery::Query</small>
75
78
  </div>
76
79
  </li>
@@ -78,15 +81,15 @@
78
81
 
79
82
  <li class="odd ">
80
83
  <div class="item">
81
- <span class='object_link'><a href="Inquery/Query.html#connection-instance_method" title="Inquery::Query#connection (method)">#connection</a></span>
82
- <small>Inquery::Query</small>
84
+ <span class='object_link'><a href="Inquery/Query/Chainable.html#connection-instance_method" title="Inquery::Query::Chainable#connection (method)">#connection</a></span>
85
+ <small>Inquery::Query::Chainable</small>
83
86
  </div>
84
87
  </li>
85
88
 
86
89
 
87
90
  <li class="even ">
88
91
  <div class="item">
89
- <span class='object_link'><a href="Inquery/Query/Chainable.html#connection-instance_method" title="Inquery::Query::Chainable#connection (method)">#connection</a></span>
92
+ <span class='object_link'><a href="Inquery/Query/Chainable.html#initialize-instance_method" title="Inquery::Query::Chainable#initialize (method)">#initialize</a></span>
90
93
  <small>Inquery::Query::Chainable</small>
91
94
  </div>
92
95
  </li>
@@ -94,8 +97,8 @@
94
97
 
95
98
  <li class="odd ">
96
99
  <div class="item">
97
- <span class='object_link'><a href="Inquery/Query/Chainable.html#initialize-instance_method" title="Inquery::Query::Chainable#initialize (method)">#initialize</a></span>
98
- <small>Inquery::Query::Chainable</small>
100
+ <span class='object_link'><a href="Inquery/MethodAccessibleHash.html#initialize-instance_method" title="Inquery::MethodAccessibleHash#initialize (method)">#initialize</a></span>
101
+ <small>Inquery::MethodAccessibleHash</small>
99
102
  </div>
100
103
  </li>
101
104
 
@@ -108,6 +111,22 @@
108
111
  </li>
109
112
 
110
113
 
114
+ <li class="odd ">
115
+ <div class="item">
116
+ <span class='object_link'><a href="Inquery/MethodAccessibleHash.html#merge-instance_method" title="Inquery::MethodAccessibleHash#merge (method)">#merge</a></span>
117
+ <small>Inquery::MethodAccessibleHash</small>
118
+ </div>
119
+ </li>
120
+
121
+
122
+ <li class="even ">
123
+ <div class="item">
124
+ <span class='object_link'><a href="Inquery/MethodAccessibleHash.html#method_missing-instance_method" title="Inquery::MethodAccessibleHash#method_missing (method)">#method_missing</a></span>
125
+ <small>Inquery::MethodAccessibleHash</small>
126
+ </div>
127
+ </li>
128
+
129
+
111
130
  <li class="odd ">
112
131
  <div class="item">
113
132
  <span class='object_link'><a href="Inquery/Query.html#osparams-instance_method" title="Inquery::Query#osparams (method)">#osparams</a></span>
@@ -134,21 +153,29 @@
134
153
 
135
154
  <li class="even ">
136
155
  <div class="item">
137
- <span class='object_link'><a href="Inquery/Mixins/RelationValidation/ClassMethods.html#relation-instance_method" title="Inquery::Mixins::RelationValidation::ClassMethods#relation (method)">#relation</a></span>
138
- <small>Inquery::Mixins::RelationValidation::ClassMethods</small>
156
+ <span class='object_link'><a href="Inquery/Query/Chainable.html#relation-instance_method" title="Inquery::Query::Chainable#relation (method)">#relation</a></span>
157
+ <small>Inquery::Query::Chainable</small>
139
158
  </div>
140
159
  </li>
141
160
 
142
161
 
143
162
  <li class="odd ">
144
163
  <div class="item">
145
- <span class='object_link'><a href="Inquery/Query/Chainable.html#relation-instance_method" title="Inquery::Query::Chainable#relation (method)">#relation</a></span>
146
- <small>Inquery::Query::Chainable</small>
164
+ <span class='object_link'><a href="Inquery/Mixins/RelationValidation/ClassMethods.html#relation-instance_method" title="Inquery::Mixins::RelationValidation::ClassMethods#relation (method)">#relation</a></span>
165
+ <small>Inquery::Mixins::RelationValidation::ClassMethods</small>
147
166
  </div>
148
167
  </li>
149
168
 
150
169
 
151
170
  <li class="even ">
171
+ <div class="item">
172
+ <span class='object_link'><a href="Inquery/MethodAccessibleHash.html#respond_to_missing%3F-instance_method" title="Inquery::MethodAccessibleHash#respond_to_missing? (method)">#respond_to_missing?</a></span>
173
+ <small>Inquery::MethodAccessibleHash</small>
174
+ </div>
175
+ </li>
176
+
177
+
178
+ <li class="odd ">
152
179
  <div class="item">
153
180
  <span class='object_link'><a href="Inquery/Query.html#run-instance_method" title="Inquery::Query#run (method)">#run</a></span>
154
181
  <small>Inquery::Query</small>
@@ -156,7 +183,7 @@
156
183
  </li>
157
184
 
158
185
 
159
- <li class="odd ">
186
+ <li class="even ">
160
187
  <div class="item">
161
188
  <span class='object_link'><a href="Inquery/Query.html#run-class_method" title="Inquery::Query.run (method)">run</a></span>
162
189
  <small>Inquery::Query</small>
@@ -164,7 +191,7 @@
164
191
  </li>
165
192
 
166
193
 
167
- <li class="even ">
194
+ <li class="odd ">
168
195
  <div class="item">
169
196
  <span class='object_link'><a href="Inquery/Mixins/SchemaValidation/ClassMethods.html#schema-instance_method" title="Inquery::Mixins::SchemaValidation::ClassMethods#schema (method)">#schema</a></span>
170
197
  <small>Inquery::Mixins::SchemaValidation::ClassMethods</small>
@@ -172,7 +199,7 @@
172
199
  </li>
173
200
 
174
201
 
175
- <li class="odd ">
202
+ <li class="even ">
176
203
  <div class="item">
177
204
  <span class='object_link'><a href="Inquery/Mixins/SchemaValidation/ClassMethods.html#schema2-instance_method" title="Inquery::Mixins::SchemaValidation::ClassMethods#schema2 (method)">#schema2</a></span>
178
205
  <small>Inquery::Mixins::SchemaValidation::ClassMethods</small>
@@ -180,7 +207,7 @@
180
207
  </li>
181
208
 
182
209
 
183
- <li class="even ">
210
+ <li class="odd ">
184
211
  <div class="item">
185
212
  <span class='object_link'><a href="Inquery/Mixins/SchemaValidation/ClassMethods.html#schema3-instance_method" title="Inquery::Mixins::SchemaValidation::ClassMethods#schema3 (method)">#schema3</a></span>
186
213
  <small>Inquery::Mixins::SchemaValidation::ClassMethods</small>
@@ -188,7 +215,7 @@
188
215
  </li>
189
216
 
190
217
 
191
- <li class="odd ">
218
+ <li class="even ">
192
219
  <div class="item">
193
220
  <span class='object_link'><a href="Inquery.html#setup-class_method" title="Inquery.setup (method)">setup</a></span>
194
221
  <small>Inquery</small>
@@ -196,7 +223,7 @@
196
223
  </li>
197
224
 
198
225
 
199
- <li class="even ">
226
+ <li class="odd ">
200
227
  <div class="item">
201
228
  <span class='object_link'><a href="Inquery/Mixins/RelationValidation.html#validate_relation!-instance_method" title="Inquery::Mixins::RelationValidation#validate_relation! (method)">#validate_relation!</a></span>
202
229
  <small>Inquery::Mixins::RelationValidation</small>
@@ -6,7 +6,7 @@
6
6
  <title>
7
7
  Top Level Namespace
8
8
 
9
- &mdash; Documentation by YARD 0.9.27
9
+ &mdash; Documentation by YARD 0.9.37
10
10
 
11
11
  </title>
12
12
 
@@ -100,9 +100,9 @@
100
100
  </div>
101
101
 
102
102
  <div id="footer">
103
- Generated on Thu Aug 24 11:11:23 2023 by
104
- <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
105
- 0.9.27 (ruby-3.0.1).
103
+ Generated on Mon Jan 5 14:06:48 2026 by
104
+ <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
105
+ 0.9.37 (ruby-3.3.5).
106
106
  </div>
107
107
 
108
108
  </div>
@@ -3,5 +3,6 @@
3
3
  source 'https://rubygems.org'
4
4
 
5
5
  gem 'rails', '~> 5.2.6'
6
+ gem 'sqlite3', '~> 1.3.13'
6
7
 
7
8
  gemspec path: '../'
@@ -3,5 +3,6 @@
3
3
  source 'https://rubygems.org'
4
4
 
5
5
  gem 'rails', '~> 6.0.4'
6
+ gem 'sqlite3', '~> 1.4.0'
6
7
 
7
8
  gemspec path: '../'
@@ -3,5 +3,6 @@
3
3
  source 'https://rubygems.org'
4
4
 
5
5
  gem 'rails', '~> 6.1.4'
6
+ gem 'sqlite3', '~> 1.4.0'
6
7
 
7
8
  gemspec path: '../'
@@ -3,5 +3,6 @@
3
3
  source 'https://rubygems.org'
4
4
 
5
5
  gem 'rails', '~> 7.0.1'
6
+ gem 'sqlite3', '~> 1.4.0'
6
7
 
7
8
  gemspec path: '../'
@@ -2,6 +2,7 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- gem 'rails', '~> 5.1.7'
5
+ gem 'rails', '~> 7.1.0'
6
+ gem 'sqlite3', '>= 1.4'
6
7
 
7
8
  gemspec path: '../'
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gem 'rails', '~> 7.2.0'
6
+ gem 'sqlite3', '>= 2.5'
7
+
8
+ gemspec path: '../'
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gem 'rails', '~> 8.0.0'
6
+ gem 'sqlite3', '>= 2.5'
7
+
8
+ gemspec path: '../'
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gem 'rails', '~> 8.1.0'
6
+ gem 'sqlite3', '>= 2.5'
7
+
8
+ gemspec path: '../'
data/inquery.gemspec CHANGED
@@ -1,46 +1,23 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: inquery 1.0.11 ruby lib
2
+ # stub: inquery 1.1.0 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "inquery".freeze
6
- s.version = "1.0.11"
6
+ s.version = "1.1.0".freeze
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib".freeze]
10
10
  s.authors = ["Sitrox".freeze]
11
- s.date = "2023-08-24"
12
- s.files = [".github/workflows/rubocop.yml".freeze, ".github/workflows/ruby.yml".freeze, ".gitignore".freeze, ".releaser_config".freeze, ".rubocop.yml".freeze, ".yardopts".freeze, "Appraisals".freeze, "CHANGELOG.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "RUBY_VERSION".freeze, "Rakefile".freeze, "VERSION".freeze, "doc/Inquery.html".freeze, "doc/Inquery/Exceptions.html".freeze, "doc/Inquery/Exceptions/Base.html".freeze, "doc/Inquery/Exceptions/InvalidRelation.html".freeze, "doc/Inquery/Exceptions/UnknownCallSignature.html".freeze, "doc/Inquery/Mixins.html".freeze, "doc/Inquery/Mixins/RawSqlUtils.html".freeze, "doc/Inquery/Mixins/RelationValidation.html".freeze, "doc/Inquery/Mixins/RelationValidation/ClassMethods.html".freeze, "doc/Inquery/Mixins/SchemaValidation.html".freeze, "doc/Inquery/Mixins/SchemaValidation/ClassMethods.html".freeze, "doc/Inquery/Query.html".freeze, "doc/Inquery/Query/Chainable.html".freeze, "doc/_index.html".freeze, "doc/class_list.html".freeze, "doc/css/common.css".freeze, "doc/css/full_list.css".freeze, "doc/css/style.css".freeze, "doc/file.README.html".freeze, "doc/file_list.html".freeze, "doc/frames.html".freeze, "doc/index.html".freeze, "doc/js/app.js".freeze, "doc/js/full_list.js".freeze, "doc/js/jquery.js".freeze, "doc/method_list.html".freeze, "doc/top-level-namespace.html".freeze, "gemfiles/rails_5.1.gemfile".freeze, "gemfiles/rails_5.2.gemfile".freeze, "gemfiles/rails_6.0.gemfile".freeze, "gemfiles/rails_6.1.gemfile".freeze, "gemfiles/rails_7.0.gemfile".freeze, "inquery.gemspec".freeze, "lib/inquery.rb".freeze, "lib/inquery/exceptions.rb".freeze, "lib/inquery/mixins/raw_sql_utils.rb".freeze, "lib/inquery/mixins/relation_validation.rb".freeze, "lib/inquery/mixins/schema_validation.rb".freeze, "lib/inquery/query.rb".freeze, "lib/inquery/query/chainable.rb".freeze, "test/db/models.rb".freeze, "test/db/schema.rb".freeze, "test/inquery/query/chainable_test.rb".freeze, "test/inquery/query_test.rb".freeze, "test/queries/group/fetch_as_json.rb".freeze, "test/queries/group/fetch_green.rb".freeze, "test/queries/group/fetch_red.rb".freeze, "test/queries/group/filter_with_color.rb".freeze, "test/queries/user/fetch_all.rb".freeze, "test/queries/user/fetch_in_group.rb".freeze, "test/queries/user/fetch_in_group_rel.rb".freeze, "test/test_helper.rb".freeze]
13
- s.rubygems_version = "3.2.16".freeze
11
+ s.date = "2026-01-05"
12
+ s.files = [".github/workflows/rubocop.yml".freeze, ".github/workflows/ruby.yml".freeze, ".gitignore".freeze, ".releaser_config".freeze, ".rubocop.yml".freeze, "Appraisals".freeze, "CHANGELOG.md".freeze, "Gemfile".freeze, "Gemfile.lock".freeze, "LICENSE".freeze, "MIGRATION.md".freeze, "README.md".freeze, "RUBY_VERSION".freeze, "Rakefile".freeze, "VERSION".freeze, "doc/Inquery.html".freeze, "doc/Inquery/Exceptions.html".freeze, "doc/Inquery/Exceptions/Base.html".freeze, "doc/Inquery/Exceptions/InvalidRelation.html".freeze, "doc/Inquery/Exceptions/UnknownCallSignature.html".freeze, "doc/Inquery/MethodAccessibleHash.html".freeze, "doc/Inquery/Mixins.html".freeze, "doc/Inquery/Mixins/RawSqlUtils.html".freeze, "doc/Inquery/Mixins/RelationValidation.html".freeze, "doc/Inquery/Mixins/RelationValidation/ClassMethods.html".freeze, "doc/Inquery/Mixins/SchemaValidation.html".freeze, "doc/Inquery/Mixins/SchemaValidation/ClassMethods.html".freeze, "doc/Inquery/Query.html".freeze, "doc/Inquery/Query/Chainable.html".freeze, "doc/_index.html".freeze, "doc/class_list.html".freeze, "doc/css/common.css".freeze, "doc/css/full_list.css".freeze, "doc/css/style.css".freeze, "doc/file.README.html".freeze, "doc/file_list.html".freeze, "doc/frames.html".freeze, "doc/index.html".freeze, "doc/js/app.js".freeze, "doc/js/full_list.js".freeze, "doc/js/jquery.js".freeze, "doc/method_list.html".freeze, "doc/top-level-namespace.html".freeze, "gemfiles/rails_5.2.gemfile".freeze, "gemfiles/rails_6.0.gemfile".freeze, "gemfiles/rails_6.1.gemfile".freeze, "gemfiles/rails_7.0.gemfile".freeze, "gemfiles/rails_7.1.gemfile".freeze, "gemfiles/rails_7.2.gemfile".freeze, "gemfiles/rails_8.0.gemfile".freeze, "gemfiles/rails_8.1.gemfile".freeze, "inquery.gemspec".freeze, "lib/inquery.rb".freeze, "lib/inquery/exceptions.rb".freeze, "lib/inquery/method_accessible_hash.rb".freeze, "lib/inquery/mixins/raw_sql_utils.rb".freeze, "lib/inquery/mixins/relation_validation.rb".freeze, "lib/inquery/mixins/schema_validation.rb".freeze, "lib/inquery/query.rb".freeze, "lib/inquery/query/chainable.rb".freeze, "test/db/models.rb".freeze, "test/db/schema.rb".freeze, "test/inquery/error_handling_test.rb".freeze, "test/inquery/method_accessible_hash_test.rb".freeze, "test/inquery/mixins/raw_sql_utils_test.rb".freeze, "test/inquery/query/chainable_test.rb".freeze, "test/inquery/query_test.rb".freeze, "test/queries/group/fetch_as_json.rb".freeze, "test/queries/group/fetch_green.rb".freeze, "test/queries/group/fetch_red.rb".freeze, "test/queries/group/filter_with_color.rb".freeze, "test/queries/user/fetch_all.rb".freeze, "test/queries/user/fetch_in_group.rb".freeze, "test/queries/user/fetch_in_group_rel.rb".freeze, "test/test_helper.rb".freeze]
13
+ s.homepage = "https://github.com/sitrox/inquery".freeze
14
+ s.rubygems_version = "3.5.18".freeze
14
15
  s.summary = "A skeleton that allows extracting queries into atomic, reusable classes.".freeze
15
- s.test_files = ["test/db/models.rb".freeze, "test/db/schema.rb".freeze, "test/inquery/query/chainable_test.rb".freeze, "test/inquery/query_test.rb".freeze, "test/queries/group/fetch_as_json.rb".freeze, "test/queries/group/fetch_green.rb".freeze, "test/queries/group/fetch_red.rb".freeze, "test/queries/group/filter_with_color.rb".freeze, "test/queries/user/fetch_all.rb".freeze, "test/queries/user/fetch_in_group.rb".freeze, "test/queries/user/fetch_in_group_rel.rb".freeze, "test/test_helper.rb".freeze]
16
+ s.test_files = ["test/db/models.rb".freeze, "test/db/schema.rb".freeze, "test/inquery/error_handling_test.rb".freeze, "test/inquery/method_accessible_hash_test.rb".freeze, "test/inquery/mixins/raw_sql_utils_test.rb".freeze, "test/inquery/query/chainable_test.rb".freeze, "test/inquery/query_test.rb".freeze, "test/queries/group/fetch_as_json.rb".freeze, "test/queries/group/fetch_green.rb".freeze, "test/queries/group/fetch_red.rb".freeze, "test/queries/group/filter_with_color.rb".freeze, "test/queries/user/fetch_all.rb".freeze, "test/queries/user/fetch_in_group.rb".freeze, "test/queries/user/fetch_in_group_rel.rb".freeze, "test/test_helper.rb".freeze]
16
17
 
17
- if s.respond_to? :specification_version then
18
- s.specification_version = 4
19
- end
18
+ s.specification_version = 4
20
19
 
21
- if s.respond_to? :add_runtime_dependency then
22
- s.add_development_dependency(%q<appraisal>.freeze, [">= 0"])
23
- s.add_development_dependency(%q<rake>.freeze, [">= 0"])
24
- s.add_development_dependency(%q<sqlite3>.freeze, [">= 0"])
25
- s.add_development_dependency(%q<haml>.freeze, [">= 0"])
26
- s.add_development_dependency(%q<yard>.freeze, [">= 0"])
27
- s.add_development_dependency(%q<rubocop>.freeze, ["= 1.25"])
28
- s.add_development_dependency(%q<redcarpet>.freeze, [">= 0"])
29
- s.add_runtime_dependency(%q<minitest>.freeze, [">= 0"])
30
- s.add_runtime_dependency(%q<activesupport>.freeze, [">= 0"])
31
- s.add_runtime_dependency(%q<activerecord>.freeze, [">= 0"])
32
- s.add_runtime_dependency(%q<schemacop>.freeze, ["~> 3.0.8"])
33
- else
34
- s.add_dependency(%q<appraisal>.freeze, [">= 0"])
35
- s.add_dependency(%q<rake>.freeze, [">= 0"])
36
- s.add_dependency(%q<sqlite3>.freeze, [">= 0"])
37
- s.add_dependency(%q<haml>.freeze, [">= 0"])
38
- s.add_dependency(%q<yard>.freeze, [">= 0"])
39
- s.add_dependency(%q<rubocop>.freeze, ["= 1.25"])
40
- s.add_dependency(%q<redcarpet>.freeze, [">= 0"])
41
- s.add_dependency(%q<minitest>.freeze, [">= 0"])
42
- s.add_dependency(%q<activesupport>.freeze, [">= 0"])
43
- s.add_dependency(%q<activerecord>.freeze, [">= 0"])
44
- s.add_dependency(%q<schemacop>.freeze, ["~> 3.0.8"])
45
- end
20
+ s.add_runtime_dependency(%q<activesupport>.freeze, [">= 5.1".freeze])
21
+ s.add_runtime_dependency(%q<activerecord>.freeze, [">= 5.1".freeze])
22
+ s.add_runtime_dependency(%q<schemacop>.freeze, [">= 3.0.8".freeze, "< 4.0".freeze])
46
23
  end
@@ -0,0 +1,45 @@
1
+ module Inquery
2
+ # A safe alternative for OpenStruct in Ruby. It behaves exactly the same, but
3
+ # does not define methods on-the-fly but uses `method_missing` instead.
4
+ #
5
+ # Usage example:
6
+ #
7
+ # ```ruby
8
+ # default_options = { foo: :bar }
9
+ # options = MethodAccessibleHash.new(default_options)
10
+ # options[:color] = :green
11
+ # options.foo # => :bar
12
+ # options.color # => green
13
+ # ```
14
+ class MethodAccessibleHash < ::Hash
15
+ # Takes an optional hash as argument and constructs a new
16
+ # MethodAccessibleHash.
17
+ def initialize(hash = {})
18
+ super()
19
+
20
+ hash.each do |key, value|
21
+ self[key.to_sym] = value
22
+ end
23
+ end
24
+
25
+ # @private
26
+ def merge(**hash)
27
+ super(hash.symbolize_keys)
28
+ end
29
+
30
+ # @private
31
+ def method_missing(method, *args, &_block)
32
+ if method.to_s.end_with?('=')
33
+ name = method.to_s.gsub(/=$/, '')
34
+ self[name.to_sym] = args.first
35
+ else
36
+ self[method.to_sym]
37
+ end
38
+ end
39
+
40
+ # @private
41
+ def respond_to_missing?(_method, _include_private = false)
42
+ true
43
+ end
44
+ end
45
+ end
@@ -1,19 +1,45 @@
1
1
  module Inquery
2
2
  module Mixins
3
+ # Provides utilities for working with raw SQL queries in a safe way.
4
+ #
5
+ # This mixin adds two helper methods for executing raw SQL queries:
6
+ # 'san' for sanitizing SQL with parameter substitution, and 'exec_query'
7
+ # for executing sanitized SQL and returning results.
3
8
  module RawSqlUtils
4
9
  extend ActiveSupport::Concern
5
10
 
6
11
  included do
7
- # Sanitizes the SQL and substitutes in the supplied variables. Relies on
8
- # `sanitize_sql_array` from ActiveRecord.
12
+ # Sanitizes SQL and substitutes variables using ActiveRecord's
13
+ # parameterized query mechanism.
14
+ #
15
+ # This method uses ActiveRecord's 'sanitize_sql_array' to safely
16
+ # escape values and prevent SQL injection. Always use this instead of
17
+ # string interpolation when building SQL queries.
18
+ #
19
+ # Example:
20
+ # sql = san("SELECT * FROM users WHERE age > ? AND city = ?", 18, 'NYC')
21
+ # # => "SELECT * FROM users WHERE age > 18 AND city = 'NYC'"
22
+ #
23
+ # @param sql [String] SQL query with '?' placeholders
24
+ # @param variables [Array] Values to substitute for placeholders
25
+ # @return [String] Sanitized SQL with values substituted
9
26
  def san(sql, *variables)
10
27
  ActiveRecord::Base.send(:sanitize_sql_array, [sql, *variables])
11
28
  end
12
29
 
13
- # Executes the sql on the connection provided by calling `connection`,
14
- # which means that the method needs to be defined where this mixin is
15
- # included. The sql passed in should be sanitized.
16
- # Returns an instance of `ActiveRecord::Result`.
30
+ # Executes sanitized SQL and returns the results.
31
+ #
32
+ # The SQL should already be sanitized using the 'san' method or
33
+ # ActiveRecord's query methods. Uses the connection from the 'connection'
34
+ # method, which must be defined in the including class.
35
+ #
36
+ # Example:
37
+ # sql = san("SELECT COUNT(*) as total FROM users WHERE active = ?", true)
38
+ # result = exec_query(sql)
39
+ # result.first['total'] # => 42
40
+ #
41
+ # @param sql [String] Sanitized SQL query to execute
42
+ # @return [ActiveRecord::Result] Query results
17
43
  def exec_query(sql)
18
44
  connection.exec_query(sql, self.class.to_s)
19
45
  end
@@ -91,7 +91,7 @@ module Inquery
91
91
  # ---------------------------------------------------------------
92
92
  fields_count = relation.select_values.size
93
93
 
94
- if fields_count.zero? && options[:default_select] && options[:fields] && (options[:fields]).positive?
94
+ if fields_count.zero? && options[:default_select] && options[:fields]&.positive?
95
95
  relation = relation.select(options[:default_select])
96
96
  fields_count = 1
97
97
  end