scoped_search 4.1.13 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fbd1e857e3b248d6d585ac7c41679b536949dc945f4c7e067b2b16e86ce325b2
4
- data.tar.gz: b4c1dc92102ff1d56b1f23406b16cf0523c6bdc17ab336ee92300993de5fd7f9
3
+ metadata.gz: 958718e625d5bbb80f93ea868abebac96d29a54e712c6c0275f9e6a1e44e07d3
4
+ data.tar.gz: 90f57db3c2009746a0beb9d843bee7a46d55d1b0ef02d796c12490d7b3e7f1b8
5
5
  SHA512:
6
- metadata.gz: 1fe965444b5640251c4ca34c5fc1fca34857f2c8cc96a8f759096165391490ca7deb7f5b3f9d8ed8c9219a5ddfa82716660e2739adb5d7dfdb2d61ca95a968a7
7
- data.tar.gz: f9ce7c87b95ceec5f3f5d1cc46f6401ef121870bf58a8cffe1b07cb7de597b8bcd3bcd1069e98ef52007df2209b26998f3f1c05a9719eefe17351d1f6da1eebf
6
+ metadata.gz: 2cc38b0ce04452df7b7205465621c0624d1173c9e9a95eb849f50eaa99fdcad9545a7411aec5fae2a3c787f348a3f440244c54e8623a3ed2589d47735110ef8b
7
+ data.tar.gz: 60ebb019e199a50505e0e934a1e2fd405a03c903350554c8f13ca62f85c5acc472b073a6bf1ebcdb1f44b15c54ec593dc31b9bf474782ff739803a0d94f43e81
@@ -146,8 +146,22 @@ module ScopedSearch
146
146
  # but the field is of datetime type. Change the comparison to return
147
147
  # more logical results.
148
148
  if field.datetime?
149
- span = 1.minute if(value =~ /\A\s*\d+\s+\bminutes?\b\s+\bago\b\s*\z/i)
150
- span ||= (timestamp.day_fraction == 0) ? 1.day : 1.hour
149
+ if value =~ time_unit_regex("minutes?|hours?")
150
+ span = 1.minute
151
+ elsif value =~ time_unit_regex("days?|weeks?|months?|years?") || value =~ /\b(today|tomorrow|yesterday)\b/i
152
+ span = 1.day
153
+ else
154
+ tokens = DateTime._parse(value)
155
+ # find the smallest unit of time given in input and determine span for further adjustment of the search query
156
+ span = {
157
+ sec: 1.second,
158
+ min: 1.minute,
159
+ hour: 1.hour,
160
+ mday: 1.day,
161
+ mon: 1.month
162
+ }.find { |key, _| tokens[key] }&.last || 1.year
163
+ end
164
+
151
165
  if [:eq, :ne].include?(operator)
152
166
  # Instead of looking for an exact (non-)match, look for dates that
153
167
  # fall inside/outside the range of timestamps of that day.
@@ -155,13 +169,13 @@ module ScopedSearch
155
169
  field_sql = field.to_sql(operator, &block)
156
170
  return ["#{negate}(#{field_sql} >= ? AND #{field_sql} < ?)", timestamp, timestamp + span]
157
171
 
158
- elsif operator == :gt
172
+ elsif span >= 1.day && operator == :gt
159
173
  # Make sure timestamps on the given date are not included in the results
160
174
  # by moving the date to the next day.
161
175
  timestamp += span
162
176
  operator = :gte
163
177
 
164
- elsif operator == :lte
178
+ elsif span >= 1.day && operator == :lte
165
179
  # Make sure the timestamps of the given date are included by moving the
166
180
  # date to the next date.
167
181
  timestamp += span
@@ -320,6 +334,12 @@ module ScopedSearch
320
334
  definition.reflection_by_name(reflection.klass, as).options[:polymorphic]
321
335
  end
322
336
 
337
+ private
338
+
339
+ def time_unit_regex(time_unit)
340
+ /\A\s*\d+\s+\b(?:#{time_unit})\b\s+\b(ago|from\s+now)\b\s*\z/i
341
+ end
342
+
323
343
  # This module gets included into the Field class to add SQL generation.
324
344
  module Field
325
345
 
@@ -1,3 +1,3 @@
1
1
  module ScopedSearch
2
- VERSION = "4.1.13"
2
+ VERSION = "4.2.0"
3
3
  end
data/lib/scoped_search.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'logger' # a workaround for https://github.com/rails/rails/issues/54263
1
2
  require 'active_record'
2
3
 
3
4
  # ScopedSearch is the base module for the scoped_search plugin. This file
@@ -34,6 +34,13 @@ Gem::Specification.new do |gem|
34
34
  gem.add_development_dependency('rspec', '~> 3.0')
35
35
  gem.add_development_dependency('rake')
36
36
 
37
+ # Rails require these, but don't explicitly depend on them
38
+ gem.add_development_dependency('base64')
39
+ gem.add_development_dependency('benchmark')
40
+ gem.add_development_dependency('bigdecimal')
41
+ gem.add_development_dependency('logger')
42
+ gem.add_development_dependency('mutex_m')
43
+
37
44
  gem.rdoc_options << '--title' << gem.name << '--main' << 'README.rdoc' << '--line-numbers' << '--inline-source'
38
45
  gem.extra_rdoc_files = ['README.rdoc', 'CHANGELOG.rdoc', 'CONTRIBUTING.rdoc', 'LICENSE']
39
46
  end
@@ -155,4 +155,65 @@ describe ScopedSearch::QueryBuilder do
155
155
  lambda { ScopedSearch::QueryBuilder.build_query(@definition, 'test_field = test_val') }.should raise_error(ScopedSearch::QueryNotSupported, /failed with error: test/)
156
156
  end
157
157
  end
158
+
159
+ context 'datetime_test' do
160
+ before(:each) do
161
+ @field = double('field')
162
+ @query_builder = ScopedSearch::QueryBuilder.new(@definition, nil, nil)
163
+
164
+ @field.stub(:datetime?).and_return(true)
165
+ @field.stub(:date?).and_return(false)
166
+ @field.stub(:to_sql).and_return('started_at')
167
+
168
+ [:virtual?, :set?, :temporal?, :relation, :offset].each { |key| @field.stub(key).and_return(false) }
169
+ end
170
+
171
+ it "should return correct SQL literal for equality operator" do
172
+ @definition.stub(:parse_temporal).and_return(DateTime.new(2023, 10, 10))
173
+ result = @query_builder.datetime_test(@field, :eq, '2023-10-10') { |type, value| }
174
+ result.should eq(["(started_at >= ? AND started_at < ?)", DateTime.new(2023, 10, 10), DateTime.new(2023, 10, 11)])
175
+ end
176
+
177
+ it "should return correct SQL literal for inequality operator" do
178
+ @definition.stub(:parse_temporal).and_return(DateTime.new(2023, 10, 10))
179
+ result = @query_builder.datetime_test(@field, :ne, '2023-10-10') { |type, value| }
180
+ result.should eq(["NOT (started_at >= ? AND started_at < ?)", DateTime.new(2023, 10, 10), DateTime.new(2023, 10, 11)])
181
+ end
182
+
183
+ it "should return correct SQL literal for greater operator" do
184
+ @definition.stub(:parse_temporal).and_return(DateTime.new(2023, 10, 9))
185
+ result = @query_builder.datetime_test(@field, :gt, '2023-10-9') { |type, value| }
186
+ result.should eq(["started_at >= ?", DateTime.new(2023, 10, 10)])
187
+ end
188
+
189
+ it "should return correct SQL literal for less than or equal operator" do
190
+ @definition.stub(:parse_temporal).and_return(DateTime.new(2023, 10, 10))
191
+ result = @query_builder.datetime_test(@field, :lte, '2023-10-10') { |type, value| }
192
+ result.should eq(["started_at < ?", DateTime.new(2023, 10, 11)])
193
+ end
194
+
195
+ it "should return empty array for invalid date" do
196
+ @definition.stub(:parse_temporal).and_return(nil)
197
+ result = @query_builder.datetime_test(@field, :eq, 'invalid-date') { |type, value| }
198
+ result.should eq([])
199
+ end
200
+
201
+ it "should count with 1 month deviation if only year and month is provided" do
202
+ @definition.stub(:parse_temporal).and_return(DateTime.new(2024, 1, 1))
203
+ result = @query_builder.datetime_test(@field, :gt, 'January 2024') { |type, value| }
204
+ result.should eq(["started_at >= ?", DateTime.new(2024, 2, 1)])
205
+ end
206
+
207
+ it "should not count with deviation if minute is the smallest unit provided" do
208
+ @definition.stub(:parse_temporal).and_return(DateTime.new(2023, 10, 10, 13, 0, 0))
209
+ result = @query_builder.datetime_test(@field, :gt, '2023-10-10 13:00') { |type, value| }
210
+ result.should eq(["started_at > ?", DateTime.new(2023, 10, 10, 13, 0, 0)])
211
+ end
212
+
213
+ it "should not count with deviation if second is the smallest unit provided" do
214
+ @definition.stub(:parse_temporal).and_return(DateTime.new(2023, 10, 10, 13, 0, 0, 1))
215
+ result = @query_builder.datetime_test(@field, :gt, '2023-10-10 13:00:01') { |type, value| }
216
+ result.should eq(["started_at > ?", DateTime.new(2023, 10, 10, 13, 0, 0, 1)])
217
+ end
218
+ end
158
219
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scoped_search
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.13
4
+ version: 4.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amos Benari
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-12-03 00:00:00.000000000 Z
13
+ date: 2025-02-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -54,6 +54,76 @@ dependencies:
54
54
  - - ">="
55
55
  - !ruby/object:Gem::Version
56
56
  version: '0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: base64
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ - !ruby/object:Gem::Dependency
72
+ name: benchmark
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ - !ruby/object:Gem::Dependency
86
+ name: bigdecimal
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ type: :development
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ - !ruby/object:Gem::Dependency
100
+ name: logger
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ type: :development
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ - !ruby/object:Gem::Dependency
114
+ name: mutex_m
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ type: :development
121
+ prerelease: false
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
57
127
  description: |2
58
128
  Scoped search makes it easy to search your ActiveRecord-based models.
59
129