inquery 1.0.10 → 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.
- checksums.yaml +4 -4
- data/.github/workflows/rubocop.yml +1 -1
- data/.github/workflows/ruby.yml +24 -8
- data/.gitignore +2 -2
- data/.rubocop.yml +4 -0
- data/Appraisals +24 -4
- data/CHANGELOG.md +47 -1
- data/Gemfile +17 -1
- data/Gemfile.lock +125 -0
- data/LICENSE +1 -1
- data/MIGRATION.md +260 -0
- data/README.md +31 -9
- data/RUBY_VERSION +1 -1
- data/Rakefile +4 -11
- data/VERSION +1 -1
- data/doc/Inquery/Exceptions/Base.html +4 -4
- data/doc/Inquery/Exceptions/InvalidRelation.html +4 -4
- data/doc/Inquery/Exceptions/UnknownCallSignature.html +4 -4
- data/doc/Inquery/Exceptions.html +4 -4
- data/doc/Inquery/MethodAccessibleHash.html +431 -0
- data/doc/Inquery/Mixins/RawSqlUtils.html +17 -4
- data/doc/Inquery/Mixins/RelationValidation/ClassMethods.html +8 -7
- data/doc/Inquery/Mixins/RelationValidation.html +9 -8
- data/doc/Inquery/Mixins/SchemaValidation/ClassMethods.html +20 -6
- data/doc/Inquery/Mixins/SchemaValidation.html +4 -4
- data/doc/Inquery/Mixins.html +4 -4
- data/doc/Inquery/Query/Chainable.html +207 -90
- data/doc/Inquery/Query.html +401 -73
- data/doc/Inquery.html +121 -6
- data/doc/_index.html +12 -5
- data/doc/class_list.html +6 -3
- data/doc/css/full_list.css +3 -3
- data/doc/css/style.css +6 -0
- data/doc/file.README.html +118 -17
- data/doc/file_list.html +5 -2
- data/doc/frames.html +10 -5
- data/doc/index.html +118 -17
- data/doc/js/app.js +294 -264
- data/doc/js/full_list.js +30 -4
- data/doc/method_list.html +52 -17
- data/doc/top-level-namespace.html +4 -4
- data/gemfiles/rails_5.2.gemfile +1 -0
- data/gemfiles/rails_6.0.gemfile +1 -0
- data/gemfiles/rails_6.1.gemfile +1 -0
- data/gemfiles/rails_7.0.gemfile +1 -0
- data/gemfiles/{rails_5.1.gemfile → rails_7.1.gemfile} +2 -1
- data/gemfiles/rails_7.2.gemfile +8 -0
- data/gemfiles/rails_8.0.gemfile +8 -0
- data/gemfiles/rails_8.1.gemfile +8 -0
- data/inquery.gemspec +11 -34
- data/lib/inquery/method_accessible_hash.rb +45 -0
- data/lib/inquery/mixins/raw_sql_utils.rb +32 -6
- data/lib/inquery/mixins/relation_validation.rb +1 -1
- data/lib/inquery/mixins/schema_validation.rb +8 -1
- data/lib/inquery/query/chainable.rb +69 -27
- data/lib/inquery/query.rb +67 -14
- data/lib/inquery.rb +9 -0
- data/test/inquery/error_handling_test.rb +117 -0
- data/test/inquery/method_accessible_hash_test.rb +85 -0
- data/test/inquery/mixins/raw_sql_utils_test.rb +67 -0
- data/test/inquery/query/chainable_test.rb +78 -0
- data/test/inquery/query_test.rb +86 -0
- data/test/test_helper.rb +11 -0
- metadata +30 -129
- data/.yardopts +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 45b9f4f89d241cb824f7de46f3b84049091ff579853165562df4341765c9e536
|
|
4
|
+
data.tar.gz: '028f2cd61072b3ffbfd31b2b626380d056805670483fad333f22da17ebe8e5c1'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c52b88733d60d5db5c071464bba3e80658c9bb2653e8624df96637c74dcfbde157cd59444e2a34fce8b971ba5267b9c70aaacc12e76c51d0ffabe5869f7c122b
|
|
7
|
+
data.tar.gz: fee01595c30949c3dc6889d8b9d7c9e931f05ae45857476a7af3ec4bf88dbce19f3faeae666505d1ccb09eee04f6a615ce993f47b2373987f6fa18d3d6ee59b6
|
data/.github/workflows/ruby.yml
CHANGED
|
@@ -13,20 +13,12 @@ jobs:
|
|
|
13
13
|
fail-fast: false
|
|
14
14
|
matrix:
|
|
15
15
|
include:
|
|
16
|
-
- rails-version: '5.1'
|
|
17
|
-
ruby-version: '2.5.1'
|
|
18
|
-
- rails-version: '5.2'
|
|
19
|
-
ruby-version: '2.5.1'
|
|
20
16
|
- rails-version: '5.2'
|
|
21
17
|
ruby-version: '2.6.2'
|
|
22
|
-
- rails-version: '6.0'
|
|
23
|
-
ruby-version: '2.5.1'
|
|
24
18
|
- rails-version: '6.0'
|
|
25
19
|
ruby-version: '2.6.2'
|
|
26
20
|
- rails-version: '6.0'
|
|
27
21
|
ruby-version: '2.7.1'
|
|
28
|
-
- rails-version: '6.1'
|
|
29
|
-
ruby-version: '2.5.1'
|
|
30
22
|
- rails-version: '6.1'
|
|
31
23
|
ruby-version: '2.6.2'
|
|
32
24
|
- rails-version: '6.1'
|
|
@@ -39,6 +31,30 @@ jobs:
|
|
|
39
31
|
ruby-version: '3.0.1'
|
|
40
32
|
- rails-version: '7.0'
|
|
41
33
|
ruby-version: '3.1.0'
|
|
34
|
+
- rails-version: '7.0'
|
|
35
|
+
ruby-version: '3.2.0'
|
|
36
|
+
- rails-version: '7.0'
|
|
37
|
+
ruby-version: '3.3.0'
|
|
38
|
+
- rails-version: '7.1'
|
|
39
|
+
ruby-version: '3.1.0'
|
|
40
|
+
- rails-version: '7.1'
|
|
41
|
+
ruby-version: '3.2.0'
|
|
42
|
+
- rails-version: '7.1'
|
|
43
|
+
ruby-version: '3.3.0'
|
|
44
|
+
- rails-version: '7.2'
|
|
45
|
+
ruby-version: '3.2.0'
|
|
46
|
+
- rails-version: '7.2'
|
|
47
|
+
ruby-version: '3.3.0'
|
|
48
|
+
- rails-version: '7.2'
|
|
49
|
+
ruby-version: '3.4.1'
|
|
50
|
+
- rails-version: '8.0'
|
|
51
|
+
ruby-version: '3.3.0'
|
|
52
|
+
- rails-version: '8.0'
|
|
53
|
+
ruby-version: '3.4.1'
|
|
54
|
+
- rails-version: '8.1'
|
|
55
|
+
ruby-version: '3.3.0'
|
|
56
|
+
- rails-version: '8.1'
|
|
57
|
+
ruby-version: '3.4.1'
|
|
42
58
|
name: Test against Ruby ${{ matrix.ruby-version }} / Rails ${{ matrix.rails-version }}
|
|
43
59
|
env:
|
|
44
60
|
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/rails_${{ matrix.rails-version }}.gemfile
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
|
@@ -5,6 +5,7 @@ AllCops:
|
|
|
5
5
|
- 'vendor/**/*'
|
|
6
6
|
- 'tmp/**/*'
|
|
7
7
|
- 'inquery.gemspec'
|
|
8
|
+
- 'gemfiles/**/*'
|
|
8
9
|
SuggestExtensions: false
|
|
9
10
|
|
|
10
11
|
DisplayCopNames: true
|
|
@@ -105,3 +106,6 @@ Style/CaseLikeIf:
|
|
|
105
106
|
|
|
106
107
|
Style/OpenStructUse:
|
|
107
108
|
Enabled: false
|
|
109
|
+
|
|
110
|
+
Style/ArgumentsForwarding:
|
|
111
|
+
Enabled: false
|
data/Appraisals
CHANGED
|
@@ -1,19 +1,39 @@
|
|
|
1
|
+
appraise 'rails-8.1' do
|
|
2
|
+
gem 'rails', '~> 8.1.0'
|
|
3
|
+
gem 'sqlite3', '>= 2.5'
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
appraise 'rails-8.0' do
|
|
7
|
+
gem 'rails', '~> 8.0.0'
|
|
8
|
+
gem 'sqlite3', '>= 2.5'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
appraise 'rails-7.2' do
|
|
12
|
+
gem 'rails', '~> 7.2.0'
|
|
13
|
+
gem 'sqlite3', '>= 2.5'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
appraise 'rails-7.1' do
|
|
17
|
+
gem 'rails', '~> 7.1.0'
|
|
18
|
+
gem 'sqlite3', '>= 1.4'
|
|
19
|
+
end
|
|
20
|
+
|
|
1
21
|
appraise 'rails-7.0' do
|
|
2
22
|
gem 'rails', '~> 7.0.1'
|
|
23
|
+
gem 'sqlite3', '~> 1.4.0'
|
|
3
24
|
end
|
|
4
25
|
|
|
5
26
|
appraise 'rails-6.1' do
|
|
6
27
|
gem 'rails', '~> 6.1.4'
|
|
28
|
+
gem 'sqlite3', '~> 1.4.0'
|
|
7
29
|
end
|
|
8
30
|
|
|
9
31
|
appraise 'rails-6.0' do
|
|
10
32
|
gem 'rails', '~> 6.0.4'
|
|
33
|
+
gem 'sqlite3', '~> 1.4.0'
|
|
11
34
|
end
|
|
12
35
|
|
|
13
36
|
appraise 'rails-5.2' do
|
|
14
37
|
gem 'rails', '~> 5.2.6'
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
appraise 'rails-5.1' do
|
|
18
|
-
gem 'rails', '~> 5.1.7'
|
|
38
|
+
gem 'sqlite3', '~> 1.3.13'
|
|
19
39
|
end
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
# Change log
|
|
2
2
|
|
|
3
|
+
## 1.1.0 (2026-01-05)
|
|
4
|
+
|
|
5
|
+
* **Drop support for Ruby 2.5.1 and Rails 5.1**: The minimum supported versions
|
|
6
|
+
are now Ruby 2.6.2 and Rails 5.2. Ruby 2.5.1 reached end-of-life in March
|
|
7
|
+
2021 and is no longer available on modern CI infrastructure (Ubuntu 24.04).
|
|
8
|
+
* Fix Ruby 2.6 compatibility in `MethodAccessibleHash` by converting method
|
|
9
|
+
symbol to string before calling `end_with?` (`Symbol#end_with?` was added
|
|
10
|
+
in Ruby 2.7)
|
|
11
|
+
* Fix Ruby 2.5/2.6 compatibility by replacing argument forwarding syntax (`...`)
|
|
12
|
+
with explicit `*args, &block` in schema validation mixin
|
|
13
|
+
* Add inline documentation to Query, Query::Chainable, and RawSqlUtils classes
|
|
14
|
+
* Add MIGRATION.md guide with examples for migrating from raw ActiveRecord
|
|
15
|
+
queries and upgrading between Inquery versions
|
|
16
|
+
* Refactor argument parsing in `Query::Chainable` for improved readability and
|
|
17
|
+
maintainability while preserving backward compatibility
|
|
18
|
+
* Increase test coverage from 87.1% to 90.97% by adding tests for error
|
|
19
|
+
handling, relation validation edge cases, and schema validation
|
|
20
|
+
* Add integration tests for RawSqlUtils mixin (`san` and `exec_query` methods)
|
|
21
|
+
* Move all development dependencies from gemspec to Gemfile for cleaner
|
|
22
|
+
separation of runtime and development dependencies
|
|
23
|
+
* Remove unused dependencies: `yard`, `haml`, and `redcarpet`
|
|
24
|
+
* Remove YARD documentation files and configuration
|
|
25
|
+
* Update RuboCop from version 1.25 to ~> 1.60 and fix new style violations
|
|
26
|
+
* Replace deprecated `OpenStruct` with `MethodAccessibleHash` to ensure
|
|
27
|
+
compatibility with Ruby 3.5+
|
|
28
|
+
* Remove debug code from `Query::Chainable#call` method
|
|
29
|
+
* Fix Ruby 3.0+ compatibility by explicitly requiring `logger`
|
|
30
|
+
* Constrain `sqlite3` to version `~> 1.4.0` for Rails 6.1 and 7.0 to avoid
|
|
31
|
+
version conflicts
|
|
32
|
+
* Update `RUBY_VERSION` to `ruby-3.3.5`
|
|
33
|
+
* Add support for Rails 7.1, 7.2, 8.0, and 8.1
|
|
34
|
+
* Add support for Ruby 3.2, 3.3, and 3.4
|
|
35
|
+
* Update sqlite3 gem requirement to `>= 2.5` for Rails 7.2+ to ensure Ruby
|
|
36
|
+
3.4 compatibility
|
|
37
|
+
* Add explicit version constraints for runtime dependencies: `activesupport`
|
|
38
|
+
and `activerecord` now require `>= 5.1`, `schemacop` allows `>= 3.0.8, < 4.0`
|
|
39
|
+
for better dependency resolution and compatibility
|
|
40
|
+
|
|
41
|
+
## 1.0.11 (2023-08-24)
|
|
42
|
+
|
|
43
|
+
* Add configuration option `config.default_schema_version` that allows you to
|
|
44
|
+
specify the schema version in effect when using the `schema` DSL method. For
|
|
45
|
+
backwards compatibility, this new setting defaults to `2`.
|
|
46
|
+
|
|
47
|
+
Internal reference: `#115859`.
|
|
48
|
+
|
|
3
49
|
## 1.0.10 (2022-05-19)
|
|
4
50
|
|
|
5
51
|
* Update gem-internal ruby version and remove `bundler` from gemspec
|
|
@@ -38,7 +84,7 @@
|
|
|
38
84
|
|
|
39
85
|
## 1.0.3 (2020-05-12)
|
|
40
86
|
|
|
41
|
-
- Overwrite parameter hash with the casted version if using
|
|
87
|
+
- Overwrite parameter hash with the casted version if using
|
|
42
88
|
casting inside the schemacop `schema` block
|
|
43
89
|
|
|
44
90
|
## 1.0.2 (2019-10-09)
|
data/Gemfile
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
source 'https://rubygems.org'
|
|
2
2
|
|
|
3
|
-
# Specify
|
|
3
|
+
# Specify runtime dependencies in the .gemspec file
|
|
4
4
|
gemspec
|
|
5
|
+
|
|
6
|
+
# Development dependencies
|
|
7
|
+
group :development do
|
|
8
|
+
gem 'appraisal'
|
|
9
|
+
gem 'rake'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
group :test do
|
|
13
|
+
gem 'minitest'
|
|
14
|
+
gem 'simplecov'
|
|
15
|
+
gem 'sqlite3'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
group :lint do
|
|
19
|
+
gem 'rubocop', '~> 1.60'
|
|
20
|
+
end
|
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
inquery (1.1.0)
|
|
5
|
+
activerecord (>= 5.1)
|
|
6
|
+
activesupport (>= 5.1)
|
|
7
|
+
schemacop (>= 3.0.8, < 4.0)
|
|
8
|
+
|
|
9
|
+
GEM
|
|
10
|
+
remote: https://rubygems.org/
|
|
11
|
+
specs:
|
|
12
|
+
activemodel (8.1.1)
|
|
13
|
+
activesupport (= 8.1.1)
|
|
14
|
+
activerecord (8.1.1)
|
|
15
|
+
activemodel (= 8.1.1)
|
|
16
|
+
activesupport (= 8.1.1)
|
|
17
|
+
timeout (>= 0.4.0)
|
|
18
|
+
activesupport (8.1.1)
|
|
19
|
+
base64
|
|
20
|
+
bigdecimal
|
|
21
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
22
|
+
connection_pool (>= 2.2.5)
|
|
23
|
+
drb
|
|
24
|
+
i18n (>= 1.6, < 2)
|
|
25
|
+
json
|
|
26
|
+
logger (>= 1.4.2)
|
|
27
|
+
minitest (>= 5.1)
|
|
28
|
+
securerandom (>= 0.3)
|
|
29
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
|
30
|
+
uri (>= 0.13.1)
|
|
31
|
+
appraisal (2.5.0)
|
|
32
|
+
bundler
|
|
33
|
+
rake
|
|
34
|
+
thor (>= 0.14.0)
|
|
35
|
+
ast (2.4.3)
|
|
36
|
+
base64 (0.3.0)
|
|
37
|
+
bigdecimal (3.3.1)
|
|
38
|
+
concurrent-ruby (1.3.5)
|
|
39
|
+
connection_pool (2.5.5)
|
|
40
|
+
docile (1.4.1)
|
|
41
|
+
drb (2.2.3)
|
|
42
|
+
i18n (1.14.7)
|
|
43
|
+
concurrent-ruby (~> 1.0)
|
|
44
|
+
json (2.16.0)
|
|
45
|
+
language_server-protocol (3.17.0.5)
|
|
46
|
+
lint_roller (1.1.0)
|
|
47
|
+
logger (1.7.0)
|
|
48
|
+
minitest (5.26.2)
|
|
49
|
+
parallel (1.27.0)
|
|
50
|
+
parser (3.3.10.0)
|
|
51
|
+
ast (~> 2.4.1)
|
|
52
|
+
racc
|
|
53
|
+
prism (1.6.0)
|
|
54
|
+
racc (1.8.1)
|
|
55
|
+
rainbow (3.1.1)
|
|
56
|
+
rake (13.3.1)
|
|
57
|
+
regexp_parser (2.11.3)
|
|
58
|
+
rubocop (1.81.7)
|
|
59
|
+
json (~> 2.3)
|
|
60
|
+
language_server-protocol (~> 3.17.0.2)
|
|
61
|
+
lint_roller (~> 1.1.0)
|
|
62
|
+
parallel (~> 1.10)
|
|
63
|
+
parser (>= 3.3.0.2)
|
|
64
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
65
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
66
|
+
rubocop-ast (>= 1.47.1, < 2.0)
|
|
67
|
+
ruby-progressbar (~> 1.7)
|
|
68
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
69
|
+
rubocop-ast (1.48.0)
|
|
70
|
+
parser (>= 3.3.7.2)
|
|
71
|
+
prism (~> 1.4)
|
|
72
|
+
ruby-progressbar (1.13.0)
|
|
73
|
+
ruby2_keywords (0.0.5)
|
|
74
|
+
schemacop (3.0.35)
|
|
75
|
+
activesupport (>= 4.0)
|
|
76
|
+
ruby2_keywords (>= 0.0.4)
|
|
77
|
+
securerandom (0.4.1)
|
|
78
|
+
simplecov (0.22.0)
|
|
79
|
+
docile (~> 1.1)
|
|
80
|
+
simplecov-html (~> 0.11)
|
|
81
|
+
simplecov_json_formatter (~> 0.1)
|
|
82
|
+
simplecov-html (0.13.2)
|
|
83
|
+
simplecov_json_formatter (0.1.4)
|
|
84
|
+
sqlite3 (2.8.1-aarch64-linux-gnu)
|
|
85
|
+
sqlite3 (2.8.1-aarch64-linux-musl)
|
|
86
|
+
sqlite3 (2.8.1-arm-linux-gnu)
|
|
87
|
+
sqlite3 (2.8.1-arm-linux-musl)
|
|
88
|
+
sqlite3 (2.8.1-arm64-darwin)
|
|
89
|
+
sqlite3 (2.8.1-x86-linux-gnu)
|
|
90
|
+
sqlite3 (2.8.1-x86-linux-musl)
|
|
91
|
+
sqlite3 (2.8.1-x86_64-darwin)
|
|
92
|
+
sqlite3 (2.8.1-x86_64-linux-gnu)
|
|
93
|
+
sqlite3 (2.8.1-x86_64-linux-musl)
|
|
94
|
+
thor (1.4.0)
|
|
95
|
+
timeout (0.4.4)
|
|
96
|
+
tzinfo (2.0.6)
|
|
97
|
+
concurrent-ruby (~> 1.0)
|
|
98
|
+
unicode-display_width (3.2.0)
|
|
99
|
+
unicode-emoji (~> 4.1)
|
|
100
|
+
unicode-emoji (4.1.0)
|
|
101
|
+
uri (1.1.1)
|
|
102
|
+
|
|
103
|
+
PLATFORMS
|
|
104
|
+
aarch64-linux-gnu
|
|
105
|
+
aarch64-linux-musl
|
|
106
|
+
arm-linux-gnu
|
|
107
|
+
arm-linux-musl
|
|
108
|
+
arm64-darwin
|
|
109
|
+
x86-linux-gnu
|
|
110
|
+
x86-linux-musl
|
|
111
|
+
x86_64-darwin
|
|
112
|
+
x86_64-linux-gnu
|
|
113
|
+
x86_64-linux-musl
|
|
114
|
+
|
|
115
|
+
DEPENDENCIES
|
|
116
|
+
appraisal
|
|
117
|
+
inquery!
|
|
118
|
+
minitest
|
|
119
|
+
rake
|
|
120
|
+
rubocop (~> 1.60)
|
|
121
|
+
simplecov
|
|
122
|
+
sqlite3
|
|
123
|
+
|
|
124
|
+
BUNDLED WITH
|
|
125
|
+
2.5.18
|
data/LICENSE
CHANGED
data/MIGRATION.md
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# Migration Guide
|
|
2
|
+
|
|
3
|
+
This guide helps you migrate from raw ActiveRecord queries to Inquery query classes, and between different versions of Inquery.
|
|
4
|
+
|
|
5
|
+
## Migrating from Raw ActiveRecord Queries
|
|
6
|
+
|
|
7
|
+
### Simple Query
|
|
8
|
+
|
|
9
|
+
**Before (raw ActiveRecord):**
|
|
10
|
+
```ruby
|
|
11
|
+
# In controller or service
|
|
12
|
+
def active_users
|
|
13
|
+
User.where(active: true).order(:name)
|
|
14
|
+
end
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**After (Inquery):**
|
|
18
|
+
```ruby
|
|
19
|
+
# app/queries/fetch_active_users.rb
|
|
20
|
+
class FetchActiveUsers < Inquery::Query
|
|
21
|
+
def call
|
|
22
|
+
User.where(active: true).order(:name)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# In controller or service
|
|
27
|
+
def active_users
|
|
28
|
+
FetchActiveUsers.run
|
|
29
|
+
end
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Benefits:**
|
|
33
|
+
- Reusable across controllers, services, and background jobs
|
|
34
|
+
- Testable in isolation
|
|
35
|
+
- Named and documented
|
|
36
|
+
|
|
37
|
+
### Parameterized Query
|
|
38
|
+
|
|
39
|
+
**Before (raw ActiveRecord):**
|
|
40
|
+
```ruby
|
|
41
|
+
def users_by_status(status)
|
|
42
|
+
User.where(status: status).order(:created_at)
|
|
43
|
+
end
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**After (Inquery with schema validation):**
|
|
47
|
+
```ruby
|
|
48
|
+
class FetchUsersByStatus < Inquery::Query
|
|
49
|
+
schema3 do
|
|
50
|
+
str! :status
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def call
|
|
54
|
+
User.where(status: osparams.status).order(:created_at)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Usage
|
|
59
|
+
FetchUsersByStatus.run(status: 'active')
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Benefits:**
|
|
63
|
+
- Automatic parameter validation
|
|
64
|
+
- Type checking
|
|
65
|
+
- Clear API documentation through schema
|
|
66
|
+
|
|
67
|
+
### Complex Query with Post-Processing
|
|
68
|
+
|
|
69
|
+
**Before:**
|
|
70
|
+
```ruby
|
|
71
|
+
def user_statistics
|
|
72
|
+
users = User.where(active: true)
|
|
73
|
+
{
|
|
74
|
+
total: users.count,
|
|
75
|
+
premium: users.where(plan: 'premium').count
|
|
76
|
+
}
|
|
77
|
+
end
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**After:**
|
|
81
|
+
```ruby
|
|
82
|
+
class FetchUserStatistics < Inquery::Query
|
|
83
|
+
def call
|
|
84
|
+
User.where(active: true)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def process(users)
|
|
88
|
+
{
|
|
89
|
+
total: users.count,
|
|
90
|
+
premium: users.where(plan: 'premium').count
|
|
91
|
+
}
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Benefits:**
|
|
97
|
+
- Separation of query logic and data transformation
|
|
98
|
+
- Can call with 'call' to get raw results or 'run' for processed results
|
|
99
|
+
|
|
100
|
+
### Scope to Chainable Query
|
|
101
|
+
|
|
102
|
+
**Before:**
|
|
103
|
+
```ruby
|
|
104
|
+
class User < ActiveRecord::Base
|
|
105
|
+
scope :active, -> { where(active: true) }
|
|
106
|
+
scope :premium, -> { where(plan: 'premium') }
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Usage
|
|
110
|
+
User.active.premium
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**After:**
|
|
114
|
+
```ruby
|
|
115
|
+
class FetchActiveUsers < Inquery::Query::Chainable
|
|
116
|
+
relation class: 'User'
|
|
117
|
+
|
|
118
|
+
def call
|
|
119
|
+
relation.where(active: true)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
class FetchPremiumUsers < Inquery::Query::Chainable
|
|
124
|
+
relation class: 'User'
|
|
125
|
+
|
|
126
|
+
def call
|
|
127
|
+
relation.where(plan: 'premium')
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Usage as query classes
|
|
132
|
+
FetchPremiumUsers.run(FetchActiveUsers.run)
|
|
133
|
+
|
|
134
|
+
# Or register as scopes
|
|
135
|
+
class User < ActiveRecord::Base
|
|
136
|
+
scope :active, FetchActiveUsers
|
|
137
|
+
scope :premium, FetchPremiumUsers
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
User.active.premium
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Benefits:**
|
|
144
|
+
- Full Ruby classes instead of lambdas
|
|
145
|
+
- Can add tests, documentation, and complex logic
|
|
146
|
+
- Chainable and composable
|
|
147
|
+
|
|
148
|
+
## Schema Validation: Schemacop v2 vs v3
|
|
149
|
+
|
|
150
|
+
Inquery supports both Schemacop v2 and v3 schemas. The default is v2 for backward compatibility.
|
|
151
|
+
|
|
152
|
+
### Using Schemacop v2 (default)
|
|
153
|
+
|
|
154
|
+
```ruby
|
|
155
|
+
class FetchUsers < Inquery::Query
|
|
156
|
+
schema do
|
|
157
|
+
req :status, :string
|
|
158
|
+
opt :limit, :integer
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def call
|
|
162
|
+
User.where(status: osparams.status)
|
|
163
|
+
.limit(osparams.limit || 10)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Using Schemacop v3 (recommended)
|
|
169
|
+
|
|
170
|
+
```ruby
|
|
171
|
+
class FetchUsers < Inquery::Query
|
|
172
|
+
schema3 do
|
|
173
|
+
str! :status
|
|
174
|
+
int? :limit
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def call
|
|
178
|
+
User.where(status: osparams.status)
|
|
179
|
+
.limit(osparams.limit || 10)
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Configuring Default Schema Version
|
|
185
|
+
|
|
186
|
+
To use Schemacop v3 by default for all queries:
|
|
187
|
+
|
|
188
|
+
```ruby
|
|
189
|
+
# config/initializers/inquery.rb
|
|
190
|
+
Inquery.setup do |config|
|
|
191
|
+
config.default_schema_version = 3
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# Now you can use 'schema' instead of 'schema3'
|
|
195
|
+
class FetchUsers < Inquery::Query
|
|
196
|
+
schema do
|
|
197
|
+
str! :status
|
|
198
|
+
int? :limit
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def call
|
|
202
|
+
User.where(status: osparams.status)
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Best Practices
|
|
208
|
+
|
|
209
|
+
### Query Organization
|
|
210
|
+
|
|
211
|
+
Organize queries by domain:
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
app/queries/
|
|
215
|
+
├── user/
|
|
216
|
+
│ ├── fetch_active.rb
|
|
217
|
+
│ ├── fetch_by_email.rb
|
|
218
|
+
│ └── search.rb
|
|
219
|
+
├── order/
|
|
220
|
+
│ ├── fetch_recent.rb
|
|
221
|
+
│ └── fetch_by_status.rb
|
|
222
|
+
└── base_query.rb
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Testing
|
|
226
|
+
|
|
227
|
+
Test queries in isolation:
|
|
228
|
+
|
|
229
|
+
```ruby
|
|
230
|
+
# test/queries/fetch_active_users_test.rb
|
|
231
|
+
class FetchActiveUsersTest < ActiveSupport::TestCase
|
|
232
|
+
test 'returns only active users' do
|
|
233
|
+
active_user = create(:user, active: true)
|
|
234
|
+
inactive_user = create(:user, active: false)
|
|
235
|
+
|
|
236
|
+
result = FetchActiveUsers.run
|
|
237
|
+
|
|
238
|
+
assert_includes result, active_user
|
|
239
|
+
refute_includes result, inactive_user
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Naming Conventions
|
|
245
|
+
|
|
246
|
+
- Use descriptive names: `FetchActiveUsers`, not `Users`
|
|
247
|
+
- Prefix with verb: `Fetch`, `Create`, `Update`, `Delete`
|
|
248
|
+
- Organize in modules: `User::FetchActive`, `Order::FetchRecent`
|
|
249
|
+
|
|
250
|
+
### When to Use Query vs. Chainable
|
|
251
|
+
|
|
252
|
+
**Use `Inquery::Query` when:**
|
|
253
|
+
- Query doesn't need to be chained
|
|
254
|
+
- Result needs post-processing
|
|
255
|
+
- Query uses raw SQL
|
|
256
|
+
|
|
257
|
+
**Use `Inquery::Query::Chainable` when:**
|
|
258
|
+
- Query needs to be chainable
|
|
259
|
+
- Using as ActiveRecord scope
|
|
260
|
+
- Input and output are both relations
|
data/README.md
CHANGED
|
@@ -23,14 +23,21 @@ gem 'inquery'
|
|
|
23
23
|
|
|
24
24
|
## Compatibility
|
|
25
25
|
|
|
26
|
-
Inquery is tested
|
|
26
|
+
Inquery is tested against multiple Ruby and Rails version combinations. The following table shows the compatibility matrix:
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
| Ruby Version | Rails 5.2 | Rails 6.0 | Rails 6.1 | Rails 7.0 | Rails 7.1 | Rails 7.2 | Rails 8.0 | Rails 8.1 |
|
|
29
|
+
|--------------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
|
|
30
|
+
| 2.6.2 | ✓ | ✓ | ✓ | - | - | - | - | - |
|
|
31
|
+
| 2.7.1 | - | ✓ | ✓ | ✓ | - | - | - | - |
|
|
32
|
+
| 3.0.1 | - | - | ✓ | ✓ | - | - | - | - |
|
|
33
|
+
| 3.1.0 | - | - | - | ✓ | ✓ | - | - | - |
|
|
34
|
+
| 3.2.0 | - | - | - | ✓ | ✓ | ✓ | - | - |
|
|
35
|
+
| 3.3.0 | - | - | - | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
36
|
+
| 3.4.1 | - | - | - | - | - | ✓ | ✓ | ✓ |
|
|
32
37
|
|
|
33
|
-
|
|
38
|
+
**Minimum supported versions:** Ruby 2.6.2 and Rails 5.2
|
|
39
|
+
|
|
40
|
+
Other Ruby/Rails version combinations might work but are not covered by our automated tests.
|
|
34
41
|
|
|
35
42
|
## Basic usage
|
|
36
43
|
|
|
@@ -297,7 +304,9 @@ end
|
|
|
297
304
|
```
|
|
298
305
|
|
|
299
306
|
Inquery supports both schemacop specification versions 2 and 3 using the methods
|
|
300
|
-
`
|
|
307
|
+
`schema2` for version 2 and method `schema3` for version 3. You can also use the
|
|
308
|
+
method `schema`, which defaults to the schema version configured using
|
|
309
|
+
`config.default_schema_version` (see [Configuration](#Configuration)).
|
|
301
310
|
|
|
302
311
|
## Rails integration
|
|
303
312
|
|
|
@@ -306,6 +315,18 @@ perfectly integrated into any Rails application. It has proven to be a winning
|
|
|
306
315
|
concept to extract all complex queries into separate classes that are
|
|
307
316
|
independently executable and testable.
|
|
308
317
|
|
|
318
|
+
## Configuration
|
|
319
|
+
|
|
320
|
+
Inquery can be configured globally using an optional initializer:
|
|
321
|
+
|
|
322
|
+
```ruby
|
|
323
|
+
# config/initializers/inquery.rb
|
|
324
|
+
Inquery.setup do |config|
|
|
325
|
+
# Specify the default schemacop schema version. Can be one of 2 or 3.
|
|
326
|
+
# config.default_schema_version = 2
|
|
327
|
+
end
|
|
328
|
+
```
|
|
329
|
+
|
|
309
330
|
### Directory structure
|
|
310
331
|
|
|
311
332
|
While not enforced, it is encouraged to use the following structure for storing
|
|
@@ -333,8 +354,9 @@ There are some key benefits to this approach:
|
|
|
333
354
|
## Contributors
|
|
334
355
|
|
|
335
356
|
Thanks to Jeroen Weeink for his insights regarding using query classes as scopes
|
|
336
|
-
in his [blog
|
|
357
|
+
in his [blog
|
|
358
|
+
post](http://craftingruby.com/posts/2015/06/29/query-objects-through-scopes.html).
|
|
337
359
|
|
|
338
360
|
## Copyright
|
|
339
361
|
|
|
340
|
-
Copyright © 2016 -
|
|
362
|
+
Copyright © 2016 - 2026 Sitrox. See `LICENSE` for further details.
|
data/RUBY_VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
ruby-3.
|
|
1
|
+
ruby-3.3.5
|