pursuit 0.4.5 → 1.0.1
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/rubygem.yaml +46 -0
- data/Gemfile +14 -13
- data/Gemfile.lock +14 -13
- data/README.md +210 -27
- data/bin/console +10 -0
- data/lib/pursuit/aggregate_modifier_not_found.rb +20 -0
- data/lib/pursuit/aggregate_modifier_required.rb +20 -0
- data/lib/pursuit/aggregate_modifiers_not_available.rb +13 -0
- data/lib/pursuit/attribute_not_found.rb +20 -0
- data/lib/pursuit/constants.rb +1 -1
- data/lib/pursuit/error.rb +7 -0
- data/lib/pursuit/predicate_parser.rb +181 -0
- data/lib/pursuit/predicate_search.rb +83 -0
- data/lib/pursuit/predicate_transform.rb +231 -0
- data/lib/pursuit/query_error.rb +7 -0
- data/lib/pursuit/simple_search.rb +64 -0
- data/lib/pursuit/term_parser.rb +44 -0
- data/lib/pursuit/term_search.rb +69 -0
- data/lib/pursuit/term_transform.rb +35 -0
- data/lib/pursuit.rb +18 -4
- data/pursuit.gemspec +4 -3
- data/spec/internal/app/models/application_record.rb +5 -0
- data/spec/internal/app/models/product.rb +25 -9
- data/spec/internal/app/models/product_category.rb +23 -1
- data/spec/internal/app/models/product_variation.rb +26 -1
- data/spec/lib/pursuit/predicate_parser_spec.rb +1604 -0
- data/spec/lib/pursuit/predicate_search_spec.rb +80 -0
- data/spec/lib/pursuit/predicate_transform_spec.rb +624 -0
- data/spec/lib/pursuit/simple_search_spec.rb +59 -0
- data/spec/lib/pursuit/term_parser_spec.rb +271 -0
- data/spec/lib/pursuit/term_search_spec.rb +71 -0
- data/spec/lib/pursuit/term_transform_spec.rb +105 -0
- metadata +47 -25
- data/.travis.yml +0 -26
- data/lib/pursuit/dsl.rb +0 -28
- data/lib/pursuit/railtie.rb +0 -13
- data/lib/pursuit/search.rb +0 -172
- data/lib/pursuit/search_options.rb +0 -86
- data/lib/pursuit/search_term_parser.rb +0 -46
- data/spec/lib/pursuit/dsl_spec.rb +0 -22
- data/spec/lib/pursuit/search_options_spec.rb +0 -146
- data/spec/lib/pursuit/search_spec.rb +0 -516
- data/spec/lib/pursuit/search_term_parser_spec.rb +0 -34
- data/travis/gemfiles/5.2.gemfile +0 -8
- data/travis/gemfiles/6.0.gemfile +0 -8
- data/travis/gemfiles/6.1.gemfile +0 -8
- data/travis/gemfiles/7.0.gemfile +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48b4becb7e8e0e0d39335cd5172fd4870989a9e26033a882e082480431330285
|
4
|
+
data.tar.gz: 33265eafe36113d7e4f263a6f9a2dc9fd7d12cfda95073c29ea0866f627e4566
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01fba1c0d143f914d3a040620f618538f8e77396e7e9fa17f503a06ef6b419c2b9eb0a55950e60b16608d944535eb9a3bf70888615709d08f525938d25850bf6
|
7
|
+
data.tar.gz: b2d0106bc8ceea194d87f62dd8831c3cb4477c831c951f638038d6d94384ee91c64039891203783ee50a3bedf76672245641ba5206191b5350f72d46e1e462f3
|
@@ -0,0 +1,46 @@
|
|
1
|
+
name: RubyGem
|
2
|
+
|
3
|
+
on:
|
4
|
+
workflow_dispatch:
|
5
|
+
push:
|
6
|
+
|
7
|
+
jobs:
|
8
|
+
rubocop:
|
9
|
+
name: RuboCop
|
10
|
+
runs-on: ubuntu-latest
|
11
|
+
steps:
|
12
|
+
- name: Checkout Source Code
|
13
|
+
uses: actions/checkout@v3
|
14
|
+
- name: Setup Ruby
|
15
|
+
uses: ruby/setup-ruby@v1
|
16
|
+
- name: Setup RubyGems
|
17
|
+
run: |
|
18
|
+
bundle install
|
19
|
+
- name: RuboCop
|
20
|
+
run: |
|
21
|
+
bundle exec rubocop --parallel --format progress --format html --out rubocop-report.html
|
22
|
+
- name: Upload Report
|
23
|
+
uses: actions/upload-artifact@v3
|
24
|
+
with:
|
25
|
+
name: RuboCop Report
|
26
|
+
path: rubocop-report.html
|
27
|
+
|
28
|
+
rspec:
|
29
|
+
name: RSpec
|
30
|
+
runs-on: ubuntu-latest
|
31
|
+
steps:
|
32
|
+
- name: Checkout Source Code
|
33
|
+
uses: actions/checkout@v3
|
34
|
+
- name: Setup Ruby
|
35
|
+
uses: ruby/setup-ruby@v1
|
36
|
+
- name: Setup RubyGems
|
37
|
+
run: |
|
38
|
+
bundle install
|
39
|
+
- name: RSpec
|
40
|
+
run: |
|
41
|
+
bundle exec rspec --format progress --format html --out rspec-report.html
|
42
|
+
- name: Upload Report
|
43
|
+
uses: actions/upload-artifact@v3
|
44
|
+
with:
|
45
|
+
name: RSpec Report
|
46
|
+
path: rspec-report.html
|
data/Gemfile
CHANGED
@@ -4,16 +4,17 @@ source 'https://rubygems.org'
|
|
4
4
|
|
5
5
|
gemspec
|
6
6
|
|
7
|
-
|
8
|
-
gem 'combustion', '~> 1.3'
|
9
|
-
gem 'guard', '~> 2.18'
|
10
|
-
gem 'guard-rspec', '~> 4.7'
|
11
|
-
gem 'pry', '~> 0.14'
|
12
|
-
gem 'rake', '~> 13.0'
|
13
|
-
gem 'rspec', '~> 3.12'
|
14
|
-
gem 'rspec-rails', '~> 6.0'
|
15
|
-
gem 'rubocop', '~> 1.57'
|
16
|
-
gem 'rubocop-rake', '~> 0.6'
|
17
|
-
gem 'rubocop-rspec', '~> 2.25'
|
18
|
-
gem 'sqlite3', '~> 1.6'
|
19
|
-
gem 'yard', '~> 0.9'
|
7
|
+
group :development do
|
8
|
+
gem 'combustion', '~> 1.3'
|
9
|
+
gem 'guard', '~> 2.18'
|
10
|
+
gem 'guard-rspec', '~> 4.7'
|
11
|
+
gem 'pry', '~> 0.14'
|
12
|
+
gem 'rake', '~> 13.0'
|
13
|
+
gem 'rspec', '~> 3.12'
|
14
|
+
gem 'rspec-rails', '~> 6.0'
|
15
|
+
gem 'rubocop', '~> 1.57'
|
16
|
+
gem 'rubocop-rake', '~> 0.6'
|
17
|
+
gem 'rubocop-rspec', '~> 2.25'
|
18
|
+
gem 'sqlite3', '~> 1.6'
|
19
|
+
gem 'yard', '~> 0.9'
|
20
|
+
end
|
data/Gemfile.lock
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pursuit (0.
|
5
|
-
activerecord (>= 5.2.0,
|
6
|
-
activesupport (>= 5.2.0,
|
4
|
+
pursuit (1.0.1)
|
5
|
+
activerecord (>= 5.2.0, <= 8.0.0)
|
6
|
+
activesupport (>= 5.2.0, <= 8.0.0)
|
7
|
+
parslet (~> 2.0)
|
7
8
|
|
8
9
|
GEM
|
9
10
|
remote: https://rubygems.org/
|
@@ -90,7 +91,7 @@ GEM
|
|
90
91
|
minitest (5.20.0)
|
91
92
|
mutex_m (0.1.2)
|
92
93
|
nenv (0.3.0)
|
93
|
-
nokogiri (1.15.4-
|
94
|
+
nokogiri (1.15.4-arm-linux)
|
94
95
|
racc (~> 1.4)
|
95
96
|
nokogiri (1.15.4-arm64-darwin)
|
96
97
|
racc (~> 1.4)
|
@@ -105,12 +106,13 @@ GEM
|
|
105
106
|
parser (3.2.2.4)
|
106
107
|
ast (~> 2.4.1)
|
107
108
|
racc
|
109
|
+
parslet (2.0.0)
|
108
110
|
pry (0.14.2)
|
109
111
|
coderay (~> 1.1)
|
110
112
|
method_source (~> 1.0)
|
111
113
|
psych (5.1.1.1)
|
112
114
|
stringio
|
113
|
-
racc (1.7.
|
115
|
+
racc (1.7.2)
|
114
116
|
rack (3.0.8)
|
115
117
|
rack-session (2.0.0)
|
116
118
|
rack (>= 3.0.0)
|
@@ -135,7 +137,7 @@ GEM
|
|
135
137
|
thor (~> 1.0, >= 1.2.2)
|
136
138
|
zeitwerk (~> 2.6)
|
137
139
|
rainbow (3.1.1)
|
138
|
-
rake (13.0
|
140
|
+
rake (13.1.0)
|
139
141
|
rb-fsevent (0.11.2)
|
140
142
|
rb-inotify (0.10.1)
|
141
143
|
ffi (~> 1.0)
|
@@ -192,10 +194,10 @@ GEM
|
|
192
194
|
ruby-progressbar (1.13.0)
|
193
195
|
ruby2_keywords (0.0.5)
|
194
196
|
shellany (0.0.1)
|
195
|
-
sqlite3 (1.6.
|
196
|
-
sqlite3 (1.6.
|
197
|
-
sqlite3 (1.6.
|
198
|
-
sqlite3 (1.6.
|
197
|
+
sqlite3 (1.6.8-arm-linux)
|
198
|
+
sqlite3 (1.6.8-arm64-darwin)
|
199
|
+
sqlite3 (1.6.8-x86_64-darwin)
|
200
|
+
sqlite3 (1.6.8-x86_64-linux)
|
199
201
|
stringio (3.0.8)
|
200
202
|
thor (1.3.0)
|
201
203
|
timeout (0.4.0)
|
@@ -207,13 +209,12 @@ GEM
|
|
207
209
|
zeitwerk (2.6.12)
|
208
210
|
|
209
211
|
PLATFORMS
|
210
|
-
aarch64-linux
|
211
212
|
arm64-darwin-22
|
212
|
-
|
213
|
+
arm64-linux
|
214
|
+
x86_64-darwin-22
|
213
215
|
x86_64-linux
|
214
216
|
|
215
217
|
DEPENDENCIES
|
216
|
-
bundler (~> 2.4)
|
217
218
|
combustion (~> 1.3)
|
218
219
|
guard (~> 2.18)
|
219
220
|
guard-rspec (~> 4.7)
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Pursuit
|
2
2
|
|
3
|
-
|
3
|
+
Search your ActiveRecord objects with ease!
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -16,41 +16,224 @@ gem 'pursuit'
|
|
16
16
|
|
17
17
|
### Usage
|
18
18
|
|
19
|
-
|
19
|
+
Pursuit comes with three different strategies for interpreting queries:
|
20
|
+
|
21
|
+
- Simple
|
22
|
+
- Term
|
23
|
+
- Predicate
|
24
|
+
|
25
|
+
### Simple Search
|
26
|
+
|
27
|
+
Simple takes the entire query and generates a SQL `LIKE` (or `ILIKE` for *PostgreSQL*) statement for each attribute
|
28
|
+
added to the search instance. Here's an example of how you might use simple to search a hypothetical `Product` record:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
search = Pursuit::SimpleSearch.new(Product.all)
|
32
|
+
search.search_attribute(:title)
|
33
|
+
search.search_attribute(:subtitle)
|
34
|
+
search.apply('Green Shirt')
|
35
|
+
```
|
36
|
+
|
37
|
+
Which results in the following SQL query:
|
38
|
+
|
39
|
+
```sql
|
40
|
+
SELECT
|
41
|
+
"products".*
|
42
|
+
FROM
|
43
|
+
"products"
|
44
|
+
WHERE
|
45
|
+
"products"."title" LIKE '%Green Shirt%'
|
46
|
+
OR "products"."subtitle" LIKE '%Green Shirt%'
|
47
|
+
```
|
48
|
+
|
49
|
+
The initializer method also accepts a block, which is evaluated within the instance's context. This can make it cleaner
|
50
|
+
when declaring the searchable attributes:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
search = Pursuit::SimpleSearch.new(Product.all) do
|
54
|
+
search_attribute :title
|
55
|
+
search_attribute :subtitle
|
56
|
+
end
|
57
|
+
|
58
|
+
search.apply('Green Shirt')
|
59
|
+
```
|
60
|
+
|
61
|
+
You can also pass custom `Arel::Attribute::Attribute` objects, which are especially useful when using joins:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
search = Pursuit::SimpleSearch.new(
|
65
|
+
Product.left_outer_joins(:variations).group(:id)
|
66
|
+
) do
|
67
|
+
search_attribute :title
|
68
|
+
search_attribute ProductVariation.arel_table[:title]
|
69
|
+
end
|
70
|
+
|
71
|
+
search.apply('Green Shirt')
|
72
|
+
```
|
73
|
+
|
74
|
+
Which results in the following SQL query:
|
75
|
+
|
76
|
+
```sql
|
77
|
+
SELECT
|
78
|
+
"products".*
|
79
|
+
FROM
|
80
|
+
"products"
|
81
|
+
LEFT OUTER JOIN "product_variations" ON "product_variations"."product_id" = "products"."id"
|
82
|
+
WHERE
|
83
|
+
"products"."title" LIKE '%Green Shirt%'
|
84
|
+
OR "product_variations"."title" LIKE '%Green Shirt%'
|
85
|
+
GROUP BY
|
86
|
+
"products"."id"
|
87
|
+
```
|
88
|
+
|
89
|
+
### Term Search
|
90
|
+
|
91
|
+
Term searches break a query into individual terms on spaces, while providing double and single quoted strings as a
|
92
|
+
means to include spaces. Here's an example of using term searches on the same `Product` record from earlier:
|
20
93
|
|
21
94
|
```ruby
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
# Attributes can be used for both keyed and unkeyed searching by default, but you can pass either `keyed: false` or
|
27
|
-
# `unkeyed: false` to restrict when the attribute is searched.
|
28
|
-
o.attribute :title
|
29
|
-
o.attribute :description
|
30
|
-
o.attribute :rating, unkeyed: false
|
31
|
-
|
32
|
-
# You can shorten the search keyword by passing the desired search term first, and then the real attribute name
|
33
|
-
# as the second argument.
|
34
|
-
# => "category*=shirts"
|
35
|
-
o.attribute :category, :category_id
|
36
|
-
|
37
|
-
# It's also possible to query entirely custom Arel nodes by passing a block which returns the Arel node to query.
|
38
|
-
# You could use this to query a person's full name by concatenating their first and last name columns, for example.
|
39
|
-
o.attribute :title_length, unkeyed: false do
|
40
|
-
Arel::Nodes::NamedFunction.new('LENGTH', [
|
41
|
-
arel_table[:title]
|
42
|
-
])
|
43
|
-
end
|
44
|
-
end
|
95
|
+
search = Pursuit::TermSearch.new(Product.all) do
|
96
|
+
search_attribute :title
|
97
|
+
search_attribute :subtitle
|
45
98
|
end
|
99
|
+
|
100
|
+
search.apply('Green "Luxury Shirt"')
|
101
|
+
```
|
102
|
+
|
103
|
+
Which results in a SQL query similar to the following:
|
104
|
+
|
105
|
+
```sql
|
106
|
+
SELECT
|
107
|
+
"products".*
|
108
|
+
FROM
|
109
|
+
"products"
|
110
|
+
WHERE
|
111
|
+
(
|
112
|
+
"products"."title" LIKE '%Green%'
|
113
|
+
OR "products"."subtitle" LIKE '%Green%'
|
114
|
+
) AND (
|
115
|
+
"products"."title" LIKE '%Luxury Shirt%'
|
116
|
+
OR "products"."subtitle" LIKE '%Luxury Shirt%'
|
117
|
+
)
|
46
118
|
```
|
47
119
|
|
48
|
-
|
120
|
+
### Predicate Search
|
121
|
+
|
122
|
+
Predicate searches use a parser (implemented with the `parslet` gem) to provide a minimal query language.
|
123
|
+
This syntax is similar to the `WHERE` and `HAVING` clauses in SQL, but uses only symbols for operators and joins.
|
124
|
+
|
125
|
+
Attributes can only be used in predicate searches when they have been added to the list of permitted attributes.
|
126
|
+
You can also rename attributes, and add attributes for joined records.
|
127
|
+
|
128
|
+
Here's a more complex example of using predicate-based searches with joins on the `Product` record from earlier:
|
49
129
|
|
50
130
|
```ruby
|
51
|
-
|
131
|
+
search = Pursuit::PredicateSearch.new(
|
132
|
+
Product.left_outer_join(:category, :variations).group(:id)
|
133
|
+
) do
|
134
|
+
# Product Attributes
|
135
|
+
permit_attribute :title
|
136
|
+
|
137
|
+
# Product Category Attributes
|
138
|
+
permit_attribute :category_name, ProductCategory.arel_table[:name]
|
139
|
+
|
140
|
+
# Product Variation Attributes
|
141
|
+
permit_attribute :variation_title, ProductVariation.arel_table[:title]
|
142
|
+
permit_attribute :variation_currency, ProductVariation.arel_table[:currency]
|
143
|
+
permit_attribute :variation_amount, ProductVariation.arel_table[:amount]
|
144
|
+
end
|
145
|
+
|
146
|
+
search.apply('title = "Luxury Shirt" & (variation_amount = 0 | variation_amount > 1000)')
|
147
|
+
```
|
148
|
+
|
149
|
+
This translates to "a product whose title is 'Luxury Shirt' and has at least one variation with either an amount of 0,
|
150
|
+
or an amount greater than 1000", which could be expressed in SQL as:
|
151
|
+
|
152
|
+
```sql
|
153
|
+
SELECT
|
154
|
+
"products".*
|
155
|
+
FROM
|
156
|
+
"products"
|
157
|
+
LEFT OUTER JOIN "product_categories" ON "product_categories"."id" = "products"."category_id"
|
158
|
+
LEFT OUTER JOIN "product_variations" ON "product_variations"."product_id" = "products"."id"
|
159
|
+
WHERE
|
160
|
+
"products"."title" = 'Luxury Shirt'
|
161
|
+
AND (
|
162
|
+
"product_variations"."amount" = 0
|
163
|
+
OR "product_variations"."amount" > 1000
|
164
|
+
)
|
165
|
+
GROUP BY
|
166
|
+
"products"."id"
|
52
167
|
```
|
53
168
|
|
169
|
+
You can use any of the following operators in comparisons:
|
170
|
+
|
171
|
+
- `=` checks if the attribute is equal to the value.
|
172
|
+
- `!=` checks if the attributes is not equal to the value.
|
173
|
+
- `>` checks if the attribute is greater than the value.
|
174
|
+
- `<` checks if the attribute is less than the value.
|
175
|
+
- `>=` checks if the attribute is greater than or equal to the value.
|
176
|
+
- `<=` checks if the attribute is less than or equal to the value.
|
177
|
+
- `~` checks if the attribute matches the value (using `LIKE` or `ILIKE`).
|
178
|
+
- `!~` checks if the attribute does not match the value (using `LIKE` or `ILIKE`).
|
179
|
+
|
180
|
+
Predicate searches also support "aggregate modifiers" which enable the use of aggregate functions, however this feature
|
181
|
+
must be explicitly enabled and requires you to use a `GROUP BY` clause:
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
search = Pursuit::PredicateSearch.new(
|
185
|
+
Product.left_outer_join(:category, :variations).group(:id)
|
186
|
+
) do
|
187
|
+
# Product Attributes
|
188
|
+
permit_attribute :title
|
189
|
+
|
190
|
+
# Product Category Attributes
|
191
|
+
permit_attribute :category, ProductCategory.arel_table[:id]
|
192
|
+
permit_attribute :category_name, ProductCategory.arel_table[:name]
|
193
|
+
|
194
|
+
# Product Variation Attributes
|
195
|
+
permit_attribute :variation, ProductVariation.arel_table[:id]
|
196
|
+
permit_attribute :variation_title, ProductVariation.arel_table[:title]
|
197
|
+
permit_attribute :variation_currency, ProductVariation.arel_table[:currency]
|
198
|
+
permit_attribute :variation_amount, ProductVariation.arel_table[:amount]
|
199
|
+
end
|
200
|
+
|
201
|
+
search.apply('title = "Luxury Shirt" & #variation > 5')
|
202
|
+
```
|
203
|
+
|
204
|
+
And the resulting SQL from this query:
|
205
|
+
|
206
|
+
```sql
|
207
|
+
SELECT
|
208
|
+
"products".*
|
209
|
+
FROM
|
210
|
+
"products"
|
211
|
+
LEFT OUTER JOIN "product_categories" ON "product_categories"."id" = "products"."category_id"
|
212
|
+
LEFT OUTER JOIN "product_variations" ON "product_variations"."product_id" = "products"."id"
|
213
|
+
WHERE
|
214
|
+
"products"."title" = 'Luxury Shirt'
|
215
|
+
GROUP BY
|
216
|
+
"products"."id"
|
217
|
+
HAVING
|
218
|
+
COUNT("product_variations"."id") > 5
|
219
|
+
```
|
220
|
+
|
221
|
+
There's no distinction between the `WHERE` and `HAVING` clause in the predicate syntax, as it's intended to be easy to
|
222
|
+
use, but this does come with a caveat.
|
223
|
+
|
224
|
+
The query must have all aggregate-modified comparisons before or after non-aggregate-modified comparisons, you can't
|
225
|
+
mix both.
|
226
|
+
|
227
|
+
For example, this query would result in a parsing error: `title ~ Shirt & #variation > 5 & category_name = Shirts`
|
228
|
+
|
229
|
+
You can preceed any attribute with one of these aggregate modifier symbols:
|
230
|
+
|
231
|
+
- `#` uses the `COUNT` aggregate function
|
232
|
+
- `+` uses the `MAX` aggregate function
|
233
|
+
- `-` uses the `MIN` aggregate function
|
234
|
+
- `*` uses the `SUM` aggregate function
|
235
|
+
- `~` uses the `AVG` aggregate function
|
236
|
+
|
54
237
|
## Development
|
55
238
|
|
56
239
|
After checking out the repo, run `bundle exec rake spec` to run the tests.
|
data/bin/console
CHANGED
@@ -1,7 +1,17 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
3
5
|
require 'bundler/setup'
|
4
6
|
require 'pursuit'
|
5
7
|
require 'pry'
|
6
8
|
|
9
|
+
if ENV['AR'] == 'true'
|
10
|
+
require 'combustion'
|
11
|
+
Combustion.initialize!(:active_record)
|
12
|
+
|
13
|
+
require 'bundler'
|
14
|
+
Bundler.require(:default, :development)
|
15
|
+
end
|
16
|
+
|
7
17
|
Pry.start
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pursuit
|
4
|
+
# Raised when an aggregate modifier cannot be found.
|
5
|
+
#
|
6
|
+
class AggregateModifierNotFound < QueryError
|
7
|
+
# @return [String] The aggregate modifier which does not map to an aggregate function.
|
8
|
+
#
|
9
|
+
attr_reader :aggregate_modifier
|
10
|
+
|
11
|
+
# Creates a new error instance.
|
12
|
+
#
|
13
|
+
# @param aggregate_modifier [Symbol] The aggregate modifier which does not map to an aggregate function.
|
14
|
+
#
|
15
|
+
def initialize(aggregate_modifier)
|
16
|
+
@aggregate_modifier = aggregate_modifier
|
17
|
+
super("#{aggregate_modifier} is not a valid aggregate modifier")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pursuit
|
4
|
+
# Raised when an attribute that must be used with an aggregate modifier is used without one.
|
5
|
+
#
|
6
|
+
class AggregateModifierRequired < QueryError
|
7
|
+
# @return [Symbol] The name of the attribute which must be used with an aggregate modifier.
|
8
|
+
#
|
9
|
+
attr_reader :attribute
|
10
|
+
|
11
|
+
# Creates a new error instance.
|
12
|
+
#
|
13
|
+
# @param attribute [Symbol] The name of the attribute which must be used with an aggregate modifier.
|
14
|
+
#
|
15
|
+
def initialize(attribute)
|
16
|
+
@attribute = attribute
|
17
|
+
super("'#{attribute}' must be used with an aggregate modifier")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pursuit
|
4
|
+
# Raised when an aggregate modifier is used in a query, but aggregate modifiers are not available.
|
5
|
+
#
|
6
|
+
class AggregateModifiersNotAvailable < QueryError
|
7
|
+
# Creates a new error instance.
|
8
|
+
#
|
9
|
+
def initialize
|
10
|
+
super('Aggregate modifiers cannot be used in this query')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pursuit
|
4
|
+
# Raised when an attribute cannot be found.
|
5
|
+
#
|
6
|
+
class AttributeNotFound < QueryError
|
7
|
+
# @return [Symbol] The name of the attribute which could not be found.
|
8
|
+
#
|
9
|
+
attr_reader :attribute
|
10
|
+
|
11
|
+
# Creates a new error instance.
|
12
|
+
#
|
13
|
+
# @param attribute [Symbol] The name of the attribute which could not be found.
|
14
|
+
#
|
15
|
+
def initialize(attribute)
|
16
|
+
@attribute = attribute
|
17
|
+
super("'#{attribute}' is not a valid attribute")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/pursuit/constants.rb
CHANGED