arel_extensions 1.3.6 → 1.3.7

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: '0076504922a3f08d3770d9bedca4b24f0b2d19b080abcfd925f3ab928a1d7802'
4
- data.tar.gz: '080a98b49a9a43f1ad319933c77befd0a8947b0d3f3fc503058cfc81b863d815'
3
+ metadata.gz: 6d8d074334ab5ecab7fc6b0d4d9a24180b83d4d3c9a0e7c9237d9ec567146272
4
+ data.tar.gz: 0cf4c51ebd196eb2671506f0aef243c9cd6332bb5f55eac89c77024c105390ff
5
5
  SHA512:
6
- metadata.gz: d658b44c16c1af76c9c6e55c084186a663683269c974757e70333755b8986b2226e7561261776ce0fb41acf063469628f215627ea80991e977968d47851af831
7
- data.tar.gz: c9f0b4f123fac561f1aedcf93bc162d8bfa0f31740b539efe599f7f12725b995279b541dd7d501d3d8bdec636880ceade3eb1346f6c5fed90d67ea7124d6e9fd
6
+ metadata.gz: 89ae8015b86e8ead47050f5af4dba33f851d02eeafa9a8123752fb24911ae46124391fdc7e3e5f09da41f0efc092ee4b7f084b6f01572e07ab5376d507c2741c
7
+ data.tar.gz: 988bef22406e320405f71dec5ca8e666de0acc8f87bc3b67f755951788ddca7fb92b65d2e313144413c3cde2adb4363e0e87aea418dfd691889a650e2fd57166
@@ -13,19 +13,21 @@ jobs:
13
13
  fail-fast: false
14
14
  matrix:
15
15
  versions: [
16
- {ruby: 3.1, rails: 7, arelx: 2},
17
- {ruby: 3.1, rails: 6_1, arelx: 2},
18
- {ruby: 3.0, rails: 7, arelx: 2},
19
- {ruby: 3.0, rails: 6_1, arelx: 2},
20
- {ruby: 2.7, rails: 7, arelx: 2},
21
- {ruby: 2.7, rails: 6_1, arelx: 2},
22
- {ruby: 2.7, rails: 6, arelx: 2},
23
- {ruby: 2.7, rails: 5_2, arelx: 1},
24
- {ruby: 2.7, rails: 4_2, arelx: 1},
25
- {ruby: 2.5, rails: 6_1, arelx: 2},
26
- {ruby: 2.5, rails: 6, arelx: 2},
27
- {ruby: 2.5, rails: 5_2, arelx: 1},
28
- {ruby: 2.5, rails: 4_2, arelx: 1},
16
+ {ruby: '3.2', rails: 7, arelx: 2},
17
+ {ruby: '3.2', rails: 6_1, arelx: 2},
18
+ {ruby: '3.1', rails: 7, arelx: 2},
19
+ {ruby: '3.1', rails: 6_1, arelx: 2},
20
+ {ruby: '3.0', rails: 7, arelx: 2},
21
+ {ruby: '3.0', rails: 6_1, arelx: 2},
22
+ {ruby: '2.7', rails: 7, arelx: 2},
23
+ {ruby: '2.7', rails: 6_1, arelx: 2},
24
+ {ruby: '2.7', rails: 6, arelx: 2},
25
+ {ruby: '2.7', rails: 5_2, arelx: 1},
26
+ {ruby: '2.7', rails: 4_2, arelx: 1},
27
+ {ruby: '2.5', rails: 6_1, arelx: 2},
28
+ {ruby: '2.5', rails: 6, arelx: 2},
29
+ {ruby: '2.5', rails: 5_2, arelx: 1},
30
+ {ruby: '2.5', rails: 4_2, arelx: 1},
29
31
  {ruby: jruby-9.2, rails: 6_1, arelx: 2},
30
32
  {ruby: jruby-9.2, rails: 6, arelx: 2},
31
33
  {ruby: jruby-9.2, rails: 5_2, arelx: 1},
@@ -44,6 +46,7 @@ jobs:
44
46
  sudo apt-get update -q
45
47
  sudo apt-get install -y freetds-dev
46
48
  - name: Update system-wide gems
49
+ if: ${{ !contains(fromJson('["2.5", "jruby-9.2"]'), matrix.versions.ruby) }}
47
50
  run: gem update --system --no-document
48
51
  - name: Setup Gemfile for arelx 2.x
49
52
  if: ${{ matrix.versions.arelx == 2 }}
@@ -65,19 +68,21 @@ jobs:
65
68
  fail-fast: false
66
69
  matrix:
67
70
  versions: [
68
- {ruby: 3.1, rails: 7, arelx: 2},
69
- {ruby: 3.1, rails: 6_1, arelx: 2},
70
- {ruby: 3.0, rails: 7, arelx: 2},
71
- {ruby: 3.0, rails: 6_1, arelx: 2},
72
- {ruby: 2.7, rails: 7, arelx: 2},
73
- {ruby: 2.7, rails: 6_1, arelx: 2},
74
- {ruby: 2.7, rails: 6, arelx: 2},
75
- {ruby: 2.7, rails: 5_2, arelx: 1},
76
- {ruby: 2.7, rails: 4_2, arelx: 1},
77
- {ruby: 2.5, rails: 6_1, arelx: 2},
78
- {ruby: 2.5, rails: 6, arelx: 2},
79
- {ruby: 2.5, rails: 5_2, arelx: 1},
80
- {ruby: 2.5, rails: 4_2, arelx: 1},
71
+ {ruby: '3.2', rails: 7, arelx: 2},
72
+ {ruby: '3.2', rails: 6_1, arelx: 2},
73
+ {ruby: '3.1', rails: 7, arelx: 2},
74
+ {ruby: '3.1', rails: 6_1, arelx: 2},
75
+ {ruby: '3.0', rails: 7, arelx: 2},
76
+ {ruby: '3.0', rails: 6_1, arelx: 2},
77
+ {ruby: '2.7', rails: 7, arelx: 2},
78
+ {ruby: '2.7', rails: 6_1, arelx: 2},
79
+ {ruby: '2.7', rails: 6, arelx: 2},
80
+ {ruby: '2.7', rails: 5_2, arelx: 1},
81
+ {ruby: '2.7', rails: 4_2, arelx: 1},
82
+ {ruby: '2.5', rails: 6_1, arelx: 2},
83
+ {ruby: '2.5', rails: 6, arelx: 2},
84
+ {ruby: '2.5', rails: 5_2, arelx: 1},
85
+ {ruby: '2.5', rails: 4_2, arelx: 1},
81
86
  {ruby: jruby-9.2, rails: 6_1, arelx: 2},
82
87
  {ruby: jruby-9.2, rails: 6, arelx: 2},
83
88
  {ruby: jruby-9.2, rails: 5_2, arelx: 1},
@@ -97,6 +102,7 @@ jobs:
97
102
  sudo apt-get update -q
98
103
  sudo apt-get install -y freetds-dev
99
104
  - name: Update system-wide gems
105
+ if: ${{ !contains(fromJson('["2.5", "jruby-9.2"]'), matrix.versions.ruby) }}
100
106
  run: gem update --system --no-document
101
107
  - name: Setup Gemfile
102
108
  if: ${{ matrix.versions.arelx == 2 }}
@@ -118,19 +124,21 @@ jobs:
118
124
  fail-fast: false
119
125
  matrix:
120
126
  versions: [
121
- {ruby: 3.1, rails: 7, arelx: 2},
122
- {ruby: 3.1, rails: 6_1, arelx: 2},
123
- {ruby: 3.0, rails: 7, arelx: 2},
124
- {ruby: 3.0, rails: 6_1, arelx: 2},
125
- {ruby: 2.7, rails: 7, arelx: 2},
126
- {ruby: 2.7, rails: 6_1, arelx: 2},
127
- {ruby: 2.7, rails: 6, arelx: 2},
128
- {ruby: 2.7, rails: 5_2, arelx: 1},
129
- {ruby: 2.7, rails: 4_2, arelx: 1},
130
- {ruby: 2.5, rails: 6_1, arelx: 2},
131
- {ruby: 2.5, rails: 6, arelx: 2},
132
- {ruby: 2.5, rails: 5_2, arelx: 1},
133
- {ruby: 2.5, rails: 4_2, arelx: 1},
127
+ {ruby: '3.2', rails: 7, arelx: 2},
128
+ {ruby: '3.2', rails: 6_1, arelx: 2},
129
+ {ruby: '3.1', rails: 7, arelx: 2},
130
+ {ruby: '3.1', rails: 6_1, arelx: 2},
131
+ {ruby: '3.0', rails: 7, arelx: 2},
132
+ {ruby: '3.0', rails: 6_1, arelx: 2},
133
+ {ruby: '2.7', rails: 7, arelx: 2},
134
+ {ruby: '2.7', rails: 6_1, arelx: 2},
135
+ {ruby: '2.7', rails: 6, arelx: 2},
136
+ {ruby: '2.7', rails: 5_2, arelx: 1},
137
+ {ruby: '2.7', rails: 4_2, arelx: 1},
138
+ {ruby: '2.5', rails: 6_1, arelx: 2},
139
+ {ruby: '2.5', rails: 6, arelx: 2},
140
+ {ruby: '2.5', rails: 5_2, arelx: 1},
141
+ {ruby: '2.5', rails: 4_2, arelx: 1},
134
142
  {ruby: jruby-9.2, rails: 6_1, arelx: 2},
135
143
  {ruby: jruby-9.2, rails: 6, arelx: 2},
136
144
  {ruby: jruby-9.2, rails: 5_2, arelx: 1},
@@ -172,6 +180,7 @@ jobs:
172
180
  sudo apt-get update -q
173
181
  sudo apt-get install -y freetds-dev
174
182
  - name: Update system-wide gems
183
+ if: ${{ !contains(fromJson('["2.5", "jruby-9.2"]'), matrix.versions.ruby) }}
175
184
  run: gem update --system --no-document
176
185
  - name: Setup Gemfile
177
186
  if: ${{ matrix.versions.arelx == 2 }}
@@ -196,19 +205,21 @@ jobs:
196
205
  fail-fast: false
197
206
  matrix:
198
207
  versions: [
199
- {ruby: 3.1, rails: 7, arelx: 2},
200
- {ruby: 3.1, rails: 6_1, arelx: 2},
201
- {ruby: 3.0, rails: 7, arelx: 2},
202
- {ruby: 3.0, rails: 6_1, arelx: 2},
203
- {ruby: 2.7, rails: 7, arelx: 2},
204
- {ruby: 2.7, rails: 6_1, arelx: 2},
205
- {ruby: 2.7, rails: 6, arelx: 2},
206
- {ruby: 2.7, rails: 5_2, arelx: 1},
207
- {ruby: 2.7, rails: 4_2, arelx: 1},
208
- {ruby: 2.5, rails: 6_1, arelx: 2},
209
- {ruby: 2.5, rails: 6, arelx: 2},
210
- {ruby: 2.5, rails: 5_2, arelx: 1},
211
- {ruby: 2.5, rails: 4_2, arelx: 1},
208
+ {ruby: '3.2', rails: 7, arelx: 2},
209
+ {ruby: '3.2', rails: 6_1, arelx: 2},
210
+ {ruby: '3.1', rails: 7, arelx: 2},
211
+ {ruby: '3.1', rails: 6_1, arelx: 2},
212
+ {ruby: '3.0', rails: 7, arelx: 2},
213
+ {ruby: '3.0', rails: 6_1, arelx: 2},
214
+ {ruby: '2.7', rails: 7, arelx: 2},
215
+ {ruby: '2.7', rails: 6_1, arelx: 2},
216
+ {ruby: '2.7', rails: 6, arelx: 2},
217
+ {ruby: '2.7', rails: 5_2, arelx: 1},
218
+ {ruby: '2.7', rails: 4_2, arelx: 1},
219
+ {ruby: '2.5', rails: 6_1, arelx: 2},
220
+ {ruby: '2.5', rails: 6, arelx: 2},
221
+ {ruby: '2.5', rails: 5_2, arelx: 1},
222
+ {ruby: '2.5', rails: 4_2, arelx: 1},
212
223
  {ruby: jruby-9.2, rails: 6_1, arelx: 2},
213
224
  {ruby: jruby-9.2, rails: 6, arelx: 2},
214
225
  {ruby: jruby-9.2, rails: 5_2, arelx: 1},
@@ -242,6 +253,7 @@ jobs:
242
253
  sudo apt-get update -q
243
254
  sudo apt-get install -y freetds-dev
244
255
  - name: Update system-wide gems
256
+ if: ${{ !contains(fromJson('["2.5", "jruby-9.2"]'), matrix.versions.ruby) }}
245
257
  run: gem update --system --no-document
246
258
  - name: Setup Gemfile
247
259
  if: ${{ matrix.versions.arelx == 2 }}
@@ -269,19 +281,21 @@ jobs:
269
281
  fail-fast: false
270
282
  matrix:
271
283
  versions: [
272
- # {ruby: 3.1, rails: 7, arelx: 2},
273
- {ruby: 3.1, rails: 6_1, arelx: 2},
274
- # {ruby: 3.0, rails: 7, arelx: 2},
275
- {ruby: 3.0, rails: 6_1, arelx: 2},
276
- # {ruby: 2.7, rails: 7, arelx: 2},
277
- {ruby: 2.7, rails: 6_1, arelx: 2},
278
- {ruby: 2.7, rails: 6, arelx: 2},
279
- {ruby: 2.7, rails: 5_2, arelx: 1},
280
- {ruby: 2.7, rails: 4_2, arelx: 1},
281
- {ruby: 2.5, rails: 6_1, arelx: 2},
282
- {ruby: 2.5, rails: 6, arelx: 2},
283
- {ruby: 2.5, rails: 5_2, arelx: 1},
284
- {ruby: 2.5, rails: 4_2, arelx: 1},
284
+ # {ruby: '3.2', rails: 7, arelx: 2},
285
+ {ruby: '3.2', rails: 6_1, arelx: 2},
286
+ # {ruby: '3.1', rails: 7, arelx: 2},
287
+ {ruby: '3.1', rails: 6_1, arelx: 2},
288
+ # {ruby: '3.0', rails: 7, arelx: 2},
289
+ {ruby: '3.0', rails: 6_1, arelx: 2},
290
+ # {ruby: '2.7', rails: 7, arelx: 2},
291
+ {ruby: '2.7', rails: 6_1, arelx: 2},
292
+ {ruby: '2.7', rails: 6, arelx: 2},
293
+ {ruby: '2.7', rails: 5_2, arelx: 1},
294
+ {ruby: '2.7', rails: 4_2, arelx: 1},
295
+ {ruby: '2.5', rails: 6_1, arelx: 2},
296
+ {ruby: '2.5', rails: 6, arelx: 2},
297
+ {ruby: '2.5', rails: 5_2, arelx: 1},
298
+ {ruby: '2.5', rails: 4_2, arelx: 1},
285
299
  # {ruby: jruby-9.2, rails: 6_1, arelx: 2},
286
300
  # {ruby: jruby-9.2, rails: 6, arelx: 2},
287
301
  {ruby: jruby-9.2, rails: 5_2, arelx: 1},
@@ -308,6 +322,7 @@ jobs:
308
322
  install: sqlengine, sqlclient, sqlpackage, localdb
309
323
  sa-password: Password12!
310
324
  - name: Update system-wide gems
325
+ if: ${{ !contains(fromJson('["2.5", "jruby-9.2"]'), matrix.versions.ruby) }}
311
326
  run: gem update --system --no-document
312
327
  - name: Setup Gemfile
313
328
  if: ${{ matrix.versions.arelx == 2 }}
data/NEWS.md CHANGED
@@ -1,13 +1,30 @@
1
- # Release
1
+ # News
2
2
 
3
- ## Bug Fixes
3
+ ## Current Release
4
+
5
+ ### New Features
6
+
7
+ - `o.format_date` as an alternative to `o.format`
8
+ The actual behavior of `format` is inconsistent across DB vendors: in mysql we
9
+ can format dates and numbers with it, and in the other ones we only format
10
+ dates.
11
+
12
+ We're planning on normalizing this behavior. We want `format` to "cleverly"
13
+ format dates or numbers, and `format_date` / `format_number` to strictly
14
+ format dates / numbers.
15
+
16
+ The introduction of `format_date` is the first step in this direction.
17
+
18
+ ## Release v2.1.6/v1.3.6
19
+
20
+ ### Bug Fixes
4
21
 
5
22
  - This used to fail.
6
23
  ```
7
24
  Arel.when(a).then(b).format('%Y-%m-%d')
8
25
  ```
9
26
 
10
- ## New Features
27
+ ### New Features
11
28
 
12
29
  - `o.present`, a synonym for `o.not_blank`
13
30
  - `o.coalesce_blank(a, b, c)`
data/README.md CHANGED
@@ -36,7 +36,8 @@ It will add common SQL features in your DB to align ti with current routines. Te
36
36
 
37
37
  ## Examples
38
38
 
39
- t is an Arel::Table for table my_table
39
+ In the following examples
40
+ `t` is an `Arel::Table` for table `my_table` (i.e., `t = Arel::Table.new('my_table')`).
40
41
 
41
42
  ## Comparators
42
43
 
@@ -50,7 +51,7 @@ t is an Arel::Table for table my_table
50
51
  # => my_table.nb > 42
51
52
  ```
52
53
 
53
- Other operators : <, >=, <=, =~
54
+ Other operators: <, >=, <=, =~
54
55
 
55
56
 
56
57
  ## Maths
@@ -73,7 +74,7 @@ With Arel Extensions:
73
74
  # => SUM(my_table.nb) + 42
74
75
  ```
75
76
 
76
- Other functions : ABS, RAND, ROUND, FLOOR, CEIL, FORMAT
77
+ Other functions: ABS, RAND, ROUND, FLOOR, CEIL, FORMAT
77
78
 
78
79
  For Example:
79
80
  ```ruby
@@ -94,14 +95,29 @@ t[:price].format_number("%07.2f €","fr_FR")
94
95
  # => TRIM(TRIM(TRIM(COALESCE(my_table.name, '')), '\t'), '\n') = ''
95
96
 
96
97
  (t[:name] =~ /\A[a-d_]+/).to_sql
97
- # => my_table.name REGEXP '\^[a-d_]+'
98
+ # => my_table.name REGEXP '^[a-d_]+'
98
99
  ```
99
100
 
100
- Other functions : SOUNDEX, LENGTH, REPLACE, LOCATE, SUBSTRING, TRIM
101
+ The `replace` function supports string and regex patterns.
102
+ For instance
103
+
104
+ ```ruby
105
+ t[:email].replace('@', ' at ').replace('.', ' dot ').to_sql
106
+ # => REPLACE(REPLACE(`my_table`.`email`, '@', ' at '), '.', ' dot ')
107
+ ```
108
+
109
+ Captures are supported when using regex patterns. The replace string may then reference the capture groups using `\1`, `\2`, etc. For instance
110
+
111
+ ```ruby
112
+ t[:email].replace(/^(.*)@(.*)$/, 'user: \1, host: \2').to_sql
113
+ # => REGEXP_REPLACE(`my_table`.`email`, '(?-mix:^(.*)@(.*)$)', 'user: \\1, host: \\2')
114
+ ```
115
+
116
+ Other functions: SOUNDEX, LENGTH, REPLACE, LOCATE, SUBSTRING, TRIM
101
117
 
102
118
  ### String Array operations
103
119
 
104
- ```t[:list]``` is a classical varchar containing a comma separated list ("1,2,3,4")
120
+ `t[:list]` is a classical varchar containing a comma separated list (`"1,2,3,4"`).
105
121
 
106
122
  ```ruby
107
123
  (t[:list] & 3).to_sql
@@ -228,15 +244,15 @@ t[:id].cast('char').to_sql
228
244
  ## Stored Procedures and User-defined functions
229
245
 
230
246
  To optimize queries, some classical functions are defined in databases missing any alternative native functions.
231
- Examples :
232
- - FIND_IN_SET
247
+ Examples:
248
+ - `FIND_IN_SET`
233
249
 
234
250
  ## BULK INSERT / UPSERT
235
251
 
236
252
  Arel Extensions improves InsertManager by adding bulk_insert method, which allows to insert multiple rows in one insert.
237
253
 
238
254
 
239
- ```
255
+ ```ruby
240
256
  @cols = ['id', 'name', 'comments', 'created_at']
241
257
  @data = [
242
258
  [23, 'name1', "sdfdsfdsfsdf", '2016-01-01'],
@@ -437,6 +453,15 @@ User.connection.execute(insert_manager.to_sql)
437
453
  <td class="ok">✔</td>
438
454
  <td class="ok">✔</td>
439
455
  </tr>
456
+ <tr>
457
+ <td class="tg-yw4l">REPLACE<br>column.replace(/re/,"X")</td>
458
+ <td class="ok">✔</td>
459
+ <td class="ok">✔</td>
460
+ <td class="ok">✔</td>
461
+ <td class="ok">✔</td>
462
+ <td class="ok">✔</td>
463
+ <td class="ok">✔</td>
464
+ </tr>
440
465
  <tr>
441
466
  <td class="tg-yw4l">SOUNDEX<br>column.soundex</td>
442
467
  <td class="ok">✔</td>
@@ -9,7 +9,7 @@ group :development, :test do
9
9
  gem 'activerecord', '~> 6.1.0'
10
10
 
11
11
  gem 'sqlite3', '~> 1.4', platforms: [:mri]
12
- gem 'mysql2', '0.5.2', platforms: [:mri]
12
+ gem 'mysql2', '~>0.5', platforms: [:mri]
13
13
  gem 'pg', '~> 1.1', platforms: [:mri]
14
14
 
15
15
  gem 'tiny_tds', platforms: %i[mri mingw x64_mingw mswin]
@@ -9,7 +9,7 @@ group :development, :test do
9
9
  gem 'activerecord', '~> 7.0.1'
10
10
 
11
11
  gem 'sqlite3', '~> 1.4', platforms: [:mri]
12
- gem 'mysql2', '0.5.2', platforms: [:mri]
12
+ gem 'mysql2', '~>0.5', platforms: [:mri]
13
13
  gem 'pg', '~> 1.1', platforms: [:mri]
14
14
 
15
15
  gem 'tiny_tds', platforms: %i[mri mingw x64_mingw mswin]
@@ -1,4 +1,5 @@
1
1
  require 'arel_extensions/nodes/format'
2
+ require 'arel_extensions/nodes/formatted_date'
2
3
  require 'arel_extensions/nodes/duration'
3
4
  require 'arel_extensions/nodes/wday'
4
5
 
@@ -43,5 +44,9 @@ module ArelExtensions
43
44
  def format(tpl, time_zone = nil)
44
45
  ArelExtensions::Nodes::Format.new [self, tpl, time_zone]
45
46
  end
47
+
48
+ def format_date(tpl, time_zone = nil)
49
+ ArelExtensions::Nodes::FormattedDate.new [self, tpl, time_zone]
50
+ end
46
51
  end
47
52
  end
@@ -0,0 +1,42 @@
1
+ require 'strscan'
2
+
3
+ module ArelExtensions
4
+ module Nodes
5
+ class FormattedDate < Function
6
+ RETURN_TYPE = :string
7
+
8
+ attr_accessor :col_type, :iso_format, :time_zone
9
+
10
+ def initialize expr
11
+ col = expr[0]
12
+ @iso_format = convert_format(expr[1])
13
+ @time_zone = expr[2]
14
+ @col_type = type_of_attribute(col)
15
+ super [col, convert_to_string_node(@iso_format)]
16
+ end
17
+
18
+ private
19
+
20
+ # Address portability issues with some of the formats.
21
+ def convert_format(fmt)
22
+ s = StringScanner.new fmt
23
+ res = StringIO.new
24
+ while !s.eos?
25
+ res <<
26
+ case
27
+ when s.scan(/%D/) then '%m/%d/%y'
28
+ when s.scan(/%F/) then '%Y-%m-%d'
29
+ when s.scan(/%R/) then '%H:%M'
30
+ when s.scan(/%r/) then '%I:%M:%S %p'
31
+ when s.scan(/%T/) then '%H:%M:%S'
32
+ when s.scan(/%v/) then '%e-%b-%Y'
33
+
34
+ when s.scan(/[^%]+/) then s.matched
35
+ when s.scan(/./) then s.matched
36
+ end
37
+ end
38
+ res.string
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,3 +1,3 @@
1
1
  module ArelExtensions
2
- VERSION = '1.3.6'.freeze
2
+ VERSION = '1.3.7'.freeze
3
3
  end
@@ -355,6 +355,10 @@ module ArelExtensions
355
355
  end
356
356
 
357
357
  def visit_ArelExtensions_Nodes_Format o, collector
358
+ visit_ArelExtensions_Nodes_FormattedDate o, collector
359
+ end
360
+
361
+ def visit_ArelExtensions_Nodes_FormattedDate o, collector
358
362
  f = ArelExtensions::Visitors::strftime_to_format(o.iso_format, LOADED_VISITOR::DATE_FORMAT_DIRECTIVES)
359
363
  if fmt = LOADED_VISITOR::DATE_CONVERT_FORMATS[f]
360
364
  collector << "CONVERT(VARCHAR(#{f.length})"
@@ -258,33 +258,16 @@ module ArelExtensions
258
258
  # In this case, `o.col_type` is `nil` but we have a legitimate type in
259
259
  # the expression to be formatted. The following is a best effort to
260
260
  # infer the proper type.
261
+ first = o.expressions[0]
261
262
  type =
262
- o.col_type.nil? && !o.expressions[0].return_type.nil? \
263
- ? o.expressions[0].return_type \
263
+ o.col_type.nil? \
264
+ && (first.respond_to?(:return_type) && !first&.return_type.nil?) \
265
+ ? first&.return_type \
264
266
  : o.col_type
265
267
 
266
268
  case type
267
269
  when :date, :datetime, :time
268
- fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
269
- collector << 'DATE_FORMAT('
270
- collector << 'CONVERT_TZ(' if o.time_zone
271
- collector = visit o.left, collector
272
- case o.time_zone
273
- when Hash
274
- src_tz, dst_tz = o.time_zone.first
275
- collector << COMMA
276
- collector = visit Arel.quoted(src_tz), collector
277
- collector << COMMA
278
- collector = visit Arel.quoted(dst_tz), collector
279
- collector << ')'
280
- when String
281
- collector << COMMA << "'UTC'" << COMMA
282
- collector = visit Arel.quoted(o.time_zone), collector
283
- collector << ')'
284
- end
285
- collector << COMMA
286
- collector = visit Arel.quoted(fmt), collector
287
- collector << ')'
270
+ visit_ArelExtensions_Nodes_FormattedDate o, collector
288
271
  when :integer, :float, :decimal
289
272
  collector << 'FORMAT('
290
273
  collector = visit o.left, collector
@@ -299,6 +282,29 @@ module ArelExtensions
299
282
  collector
300
283
  end
301
284
 
285
+ def visit_ArelExtensions_Nodes_FormattedDate o, collector
286
+ fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
287
+ collector << 'DATE_FORMAT('
288
+ collector << 'CONVERT_TZ(' if o.time_zone
289
+ collector = visit o.left, collector
290
+ case o.time_zone
291
+ when Hash
292
+ src_tz, dst_tz = o.time_zone.first
293
+ collector << COMMA
294
+ collector = visit Arel.quoted(src_tz), collector
295
+ collector << COMMA
296
+ collector = visit Arel.quoted(dst_tz), collector
297
+ collector << ')'
298
+ when String
299
+ collector << COMMA << "'UTC'" << COMMA
300
+ collector = visit Arel.quoted(o.time_zone), collector
301
+ collector << ')'
302
+ end
303
+ collector << COMMA
304
+ collector = visit Arel.quoted(fmt), collector
305
+ collector << ')'
306
+ end
307
+
302
308
  def visit_ArelExtensions_Nodes_DateDiff o, collector
303
309
  case o.right_node_type
304
310
  when :ruby_date, :ruby_time, :date, :datetime, :time
@@ -451,6 +451,10 @@ module ArelExtensions
451
451
  end
452
452
 
453
453
  def visit_ArelExtensions_Nodes_Format o, collector
454
+ visit_ArelExtensions_Nodes_FormattedDate o, collector
455
+ end
456
+
457
+ def visit_ArelExtensions_Nodes_FormattedDate o, collector
454
458
  fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
455
459
  collector << 'TO_CHAR('
456
460
  collector << 'CAST(' if o.time_zone
@@ -174,6 +174,10 @@ module ArelExtensions
174
174
  end
175
175
 
176
176
  def visit_ArelExtensions_Nodes_Format o, collector
177
+ visit_ArelExtensions_Nodes_FormattedDate o, collector
178
+ end
179
+
180
+ def visit_ArelExtensions_Nodes_FormattedDate o, collector
177
181
  fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
178
182
  collector << 'TO_CHAR('
179
183
  collector << '(' if o.time_zone
@@ -289,6 +289,26 @@ module ArelExtensions
289
289
  collector
290
290
  end
291
291
 
292
+ def visit_ArelExtensions_Nodes_FormattedDate o, collector
293
+ case o.col_type
294
+ when :date, :datetime, :time
295
+ collector << 'STRFTIME('
296
+ collector = visit o.right, collector
297
+ collector << COMMA
298
+ collector = visit o.left, collector
299
+ collector << ')'
300
+ when :integer, :float, :decimal
301
+ collector << 'FORMAT('
302
+ collector = visit o.left, collector
303
+ collector << COMMA
304
+ collector = visit o.right, collector
305
+ collector << ')'
306
+ else
307
+ collector = visit o.left, collector
308
+ end
309
+ collector
310
+ end
311
+
292
312
  # comparators
293
313
 
294
314
  def visit_ArelExtensions_Nodes_Cast o, collector
@@ -437,123 +437,134 @@ module ArelExtensions
437
437
  end
438
438
 
439
439
  def test_format
440
- assert_equal '2016-05-23', t(@lucas, @created_at.format('%Y-%m-%d'))
441
- assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S'))
442
- assert_equal '12:42%', t(@lucas, @updated_at.format('%R%%'))
443
-
444
- # The following tests will ensure proper conversion of timestamps to
445
- # requested timezones.
446
- #
447
- # The names of the timezones is highly dependant on the underlying
448
- # operating system, and this is why we need to handle each database
449
- # separately: the images we're using to test these databases are
450
- # different. So don't rely on the provided examples. Your setup is your
451
- # reference.
452
- #
453
- # One could always have portable code if s/he uses standard
454
- # abbreviations, like:
455
- #
456
- # 1. CET => Central European Time
457
- # 2. CEST => Central European Summer Time
458
- #
459
- # Which implies that the caller should handle daylight saving detection.
460
- # In fact, CET will handle daylight saving in MySQL but not Postgres.
461
- #
462
- # It looks like the posix convention is supported by mysql and
463
- # postgresql, e.g.:
464
- #
465
- # posix/Europe/Paris
466
- # posix/America/Nipigon
467
- #
468
- # so it looks like a more reliably portable way of specifying it.
469
- time_zones = {
470
- 'mssql' => {
471
- 'utc' => 'UTC',
472
- 'sao_paulo' => 'Argentina Standard Time',
473
- 'tahiti' => 'Hawaiian Standard Time',
474
- 'paris' => 'Central European Standard Time'
475
- },
476
- 'posix' => {
477
- 'utc' => 'UTC',
478
- 'sao_paulo' => 'America/Sao_Paulo',
479
- 'tahiti' => 'Pacific/Tahiti',
480
- 'paris' => 'Europe/Paris'
481
- }
482
- }
483
-
484
- skip "Unsupported timezone conversion for DB=#{ENV['DB']}" if !%w[mssql mysql oracle postgresql].include?(ENV['DB'])
485
- # TODO: Standarize timezone conversion across all databases.
486
- # This test case will be refactored and should work the same across all vendors.
487
- if ENV['DB'] == 'mssql' && /Microsoft SQL Server (\d+)/.match(ActiveRecord::Base.connection.select_value('SELECT @@version'))[1].to_i < 2016
488
- skip "SQL Server < 2016 is not currently supported"
489
- end
490
-
491
- tz = ENV['DB'] == 'mssql' ? time_zones['mssql'] : time_zones['posix']
492
-
493
- assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', tz['utc']))
494
- assert_equal '2014/03/03 09:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['sao_paulo']}))
495
- assert_equal '2014/03/03 02:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['tahiti']}))
440
+ %i[format format_date].each do |method|
441
+ assert_equal '2016-05-23', t(@lucas, @created_at.send(method, '%Y-%m-%d'))
442
+ assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S'))
443
+ assert_equal '12:42%', t(@lucas, @updated_at.send(method, '%R%%'))
444
+
445
+ # The following tests will ensure proper conversion of timestamps to
446
+ # requested timezones.
447
+ #
448
+ # The names of the timezones is highly dependant on the underlying
449
+ # operating system, and this is why we need to handle each database
450
+ # separately: the images we're using to test these databases are
451
+ # different. So don't rely on the provided examples. Your setup is your
452
+ # reference.
453
+ #
454
+ # One could always have portable code if s/he uses standard
455
+ # abbreviations, like:
456
+ #
457
+ # 1. CET => Central European Time
458
+ # 2. CEST => Central European Summer Time
459
+ #
460
+ # Which implies that the caller should handle daylight saving detection.
461
+ # In fact, CET will handle daylight saving in MySQL but not Postgres.
462
+ #
463
+ # It looks like the posix convention is supported by mysql and
464
+ # postgresql, e.g.:
465
+ #
466
+ # posix/Europe/Paris
467
+ # posix/America/Nipigon
468
+ #
469
+ # so it looks like a more reliably portable way of specifying it.
470
+ time_zones = {
471
+ 'mssql' => {
472
+ 'utc' => 'UTC',
473
+ 'sao_paulo' => 'Argentina Standard Time',
474
+ 'tahiti' => 'Hawaiian Standard Time',
475
+ 'paris' => 'Central European Standard Time'
476
+ },
477
+ 'posix' => {
478
+ 'utc' => 'UTC',
479
+ 'sao_paulo' => 'America/Sao_Paulo',
480
+ 'tahiti' => 'Pacific/Tahiti',
481
+ 'paris' => 'Europe/Paris'
482
+ }
483
+ }
484
+
485
+ skip "Unsupported timezone conversion for DB=#{ENV['DB']}" if !%w[mssql mysql oracle postgresql].include?(ENV['DB'])
486
+ # TODO: Standarize timezone conversion across all databases.
487
+ # This test case will be refactored and should work the same across all vendors.
488
+ if ENV['DB'] == 'mssql' && /Microsoft SQL Server (\d+)/.match(ActiveRecord::Base.connection.select_value('SELECT @@version'))[1].to_i < 2016
489
+ skip "SQL Server < 2016 is not currently supported"
490
+ end
496
491
 
497
- # Skipping conversion from UTC to the desired timezones fails in SQL
498
- # Server and Postgres. This is mainly due to the fact that timezone
499
- # information is not preserved in the column itself.
500
- #
501
- # MySQL is happy to consider that times by default are in UTC.
502
- assert_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
503
- refute_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', tz['paris'])) if !['mysql'].include?(ENV['DB'])
504
-
505
- # Winter/Summer time
506
- assert_equal '2014/08/03 14:42:00', t(@lucas, (@updated_at + 5.months).format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
507
- if ENV['DB'] == 'mssql'
508
- assert_equal '2022/02/01 11:42:00', t(@lucas, Arel.quoted('2022-02-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
509
- assert_equal '2022/08/01 12:42:00', t(@lucas, Arel.quoted('2022-08-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
510
- else
511
- assert_equal '2022/02/01 11:42:00', t(@lucas, Arel.quoted('2022-02-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', tz['paris']))
512
- assert_equal '2022/08/01 12:42:00', t(@lucas, Arel.quoted('2022-08-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', tz['paris']))
492
+ tz = ENV['DB'] == 'mssql' ? time_zones['mssql'] : time_zones['posix']
493
+
494
+ assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', tz['utc']))
495
+ assert_equal '2014/03/03 09:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['sao_paulo']}))
496
+ assert_equal '2014/03/03 02:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['tahiti']}))
497
+
498
+ # Skipping conversion from UTC to the desired timezones fails in SQL
499
+ # Server and Postgres. This is mainly due to the fact that timezone
500
+ # information is not preserved in the column itself.
501
+ #
502
+ # MySQL is happy to consider that times by default are in UTC.
503
+ assert_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
504
+ refute_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', tz['paris'])) if !['mysql'].include?(ENV['DB'])
505
+
506
+ # Winter/Summer time
507
+ assert_equal '2014/08/03 14:42:00', t(@lucas, (@updated_at + 5.months).send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
508
+ if ENV['DB'] == 'mssql'
509
+ assert_equal '2022/02/01 11:42:00', t(@lucas, Arel.quoted('2022-02-01 10:42:00').cast(:datetime).send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
510
+ assert_equal '2022/08/01 12:42:00', t(@lucas, Arel.quoted('2022-08-01 10:42:00').cast(:datetime).send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
511
+ else
512
+ assert_equal '2022/02/01 11:42:00', t(@lucas, Arel.quoted('2022-02-01 10:42:00').cast(:datetime).send(method, '%Y/%m/%d %H:%M:%S', tz['paris']))
513
+ assert_equal '2022/08/01 12:42:00', t(@lucas, Arel.quoted('2022-08-01 10:42:00').cast(:datetime).send(method, '%Y/%m/%d %H:%M:%S', tz['paris']))
514
+ end
513
515
  end
514
516
  end
515
517
 
516
518
  def test_format_iso_week
517
- skip "Unsupported ISO week number for DB=#{ENV['DB']}" if ['sqlite'].include?(ENV['DB'])
518
- assert_equal '10', t(@lucas, @updated_at.format('%V'))
519
- {
520
- '2024-01-01 10:42:00' => '01', # Monday
521
- '2030-01-01 10:42:00' => '01', # Tuesday
522
- '2025-01-01 10:42:00' => '01', # Wednesday
523
- '2026-01-01 10:42:00' => '01', # Thursday
524
- '2027-01-01 10:42:00' => '53', # Friday
525
- '2028-01-01 10:42:00' => '52', # Saturday
526
- '2034-01-01 10:42:00' => '52', # Sunday
527
- }.each do |date, exp|
528
- assert_equal exp, t(@lucas, Arel.quoted(date).cast(:datetime).format('%V'))
519
+ %i[format format_date].each do |method|
520
+ skip "Unsupported ISO week number for DB=#{ENV['DB']}" if ['sqlite'].include?(ENV['DB'])
521
+ assert_equal '10', t(@lucas, @updated_at.send(method, '%V'))
522
+ {
523
+ '2024-01-01 10:42:00' => '01', # Monday
524
+ '2030-01-01 10:42:00' => '01', # Tuesday
525
+ '2025-01-01 10:42:00' => '01', # Wednesday
526
+ '2026-01-01 10:42:00' => '01', # Thursday
527
+ '2027-01-01 10:42:00' => '53', # Friday
528
+ '2028-01-01 10:42:00' => '52', # Saturday
529
+ '2034-01-01 10:42:00' => '52', # Sunday
530
+ }.each do |date, exp|
531
+ assert_equal exp, t(@lucas, Arel.quoted(date).cast(:datetime).send(method, '%V'))
532
+ end
529
533
  end
530
534
  end
531
535
 
532
536
  def test_format_iso_year_of_week
533
537
  skip "Unsupported ISO year of week for DB=#{ENV['DB']}" if %w[mssql sqlite].include?(ENV['DB'])
534
- assert_equal '2014', t(@lucas, @updated_at.format('%G'))
535
-
536
- {
537
- '2024-01-01 10:42:00' => '2024', # Monday
538
- '2030-01-01 10:42:00' => '2030', # Tuesday
539
- '2025-01-01 10:42:00' => '2025', # Wednesday
540
- '2026-01-01 10:42:00' => '2026', # Thursday
541
- '2027-01-01 10:42:00' => '2026', # Friday
542
- '2028-01-01 10:42:00' => '2027', # Saturday
543
- '2034-01-01 10:42:00' => '2033', # Sunday
544
- }.each do |date, exp|
545
- assert_equal exp, t(@lucas, Arel.quoted(date).cast(:datetime).format('%G'))
538
+ %i[format format_date].each do |method|
539
+ assert_equal '2014', t(@lucas, @updated_at.send(method, '%G'))
540
+
541
+ {
542
+ '2024-01-01 10:42:00' => '2024', # Monday
543
+ '2030-01-01 10:42:00' => '2030', # Tuesday
544
+ '2025-01-01 10:42:00' => '2025', # Wednesday
545
+ '2026-01-01 10:42:00' => '2026', # Thursday
546
+ '2027-01-01 10:42:00' => '2026', # Friday
547
+ '2028-01-01 10:42:00' => '2027', # Saturday
548
+ '2034-01-01 10:42:00' => '2033', # Sunday
549
+ }.each do |date, exp|
550
+ assert_equal exp, t(@lucas, Arel.quoted(date).cast(:datetime).send(method, '%G'))
551
+ end
546
552
  end
547
553
  end
548
554
 
549
555
  def test_format_date_with_names
550
556
  skip "#{ENV['DB']} does not support a variety of word-based formatting for month and day names" if %w[mssql sqlite].include?(ENV['DB'])
551
- assert_equal 'Mon, 03 Mar 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
552
- assert_equal 'Monday, 03 March 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
557
+ %i[format format_date].each do |method|
558
+ assert_equal 'Mon, 03 Mar 14', t(@lucas, @updated_at.send(method, '%a, %d %b %y'))
559
+ assert_equal 'Monday, 03 March 14', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
560
+ end
553
561
 
554
562
  skip "#{ENV['DB']} does not support ALLCAPS month and day names" if ['mysql'].include?(ENV['DB'])
555
- assert_equal 'Mon, 03 MAR 14', t(@lucas, @updated_at.format('%a, %d %^b %y'))
556
- assert_equal 'Monday, 03 MARCH 14', t(@lucas, @updated_at.format('%A, %d %^B %y'))
563
+ %i[format format_date].each do |method|
564
+
565
+ assert_equal 'Mon, 03 MAR 14', t(@lucas, @updated_at.send(method, '%a, %d %^b %y'))
566
+ assert_equal 'Monday, 03 MARCH 14', t(@lucas, @updated_at.send(method, '%A, %d %^B %y'))
567
+ end
557
568
  end
558
569
 
559
570
  def switch_to_lang(lang)
@@ -580,28 +591,30 @@ module ArelExtensions
580
591
  #
581
592
  # Tests should assert one single thing in principle, but until we
582
593
  # refactor this whole thing, we'll have to do tricks of this sort.
583
- begin
584
- switch_to_lang(:en)
585
- case ENV['DB']
586
- when 'mysql', 'postgresql'
587
- assert_equal 'Mon, 03 Mar 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
588
- assert_equal 'Monday, 03 March 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
589
- when 'mssql'
590
- assert_equal 'Monday, 03 March 2014', t(@lucas, @updated_at.format('%A, %d %B %y'))
591
- end
592
- switch_to_lang(:fr)
593
- case ENV['DB']
594
- when 'mysql'
595
- assert_equal 'lun, 03 mar 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
596
- assert_equal 'lundi, 03 mars 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
597
- when 'postgresql'
598
- assert_equal 'Lun., 03 Mars 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
599
- assert_equal 'Lundi, 03 Mars 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
600
- when 'mssql'
601
- assert_equal 'lundi, 03 mars 2014', t(@lucas, @updated_at.format('%A, %d %B %y'))
594
+ %i[format format_date].each do |method|
595
+ begin
596
+ switch_to_lang(:en)
597
+ case ENV['DB']
598
+ when 'mysql', 'postgresql'
599
+ assert_equal 'Mon, 03 Mar 14', t(@lucas, @updated_at.send(method, '%a, %d %b %y'))
600
+ assert_equal 'Monday, 03 March 14', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
601
+ when 'mssql'
602
+ assert_equal 'Monday, 03 March 2014', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
603
+ end
604
+ switch_to_lang(:fr)
605
+ case ENV['DB']
606
+ when 'mysql'
607
+ assert_equal 'lun, 03 mar 14', t(@lucas, @updated_at.send(method, '%a, %d %b %y'))
608
+ assert_equal 'lundi, 03 mars 14', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
609
+ when 'postgresql'
610
+ assert_equal 'Lun., 03 Mars 14', t(@lucas, @updated_at.send(method, '%a, %d %b %y'))
611
+ assert_equal 'Lundi, 03 Mars 14', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
612
+ when 'mssql'
613
+ assert_equal 'lundi, 03 mars 2014', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
614
+ end
615
+ ensure
616
+ switch_to_lang(:en)
602
617
  end
603
- ensure
604
- switch_to_lang(:en)
605
618
  end
606
619
  end
607
620
 
@@ -632,6 +645,7 @@ module ArelExtensions
632
645
  assert_equal 'Myung', t(@myung, @comments.coalesce_blank('', ' ', ' ').coalesce_blank('Myung'))
633
646
  assert_equal 'Myung', t(@myung, @comments.coalesce_blank('', ' ', ' ', 'Myung'))
634
647
  assert_equal '2016-05-23', t(@myung, @created_at.coalesce_blank(Date.new(2022, 1, 1)).format('%Y-%m-%d'))
648
+ assert_equal '2016-05-23', t(@myung, @created_at.coalesce_blank(Date.new(2022, 1, 1)).format_date('%Y-%m-%d'))
635
649
  assert_equal 'Laure', t(@laure, @comments.coalesce_blank('Laure'))
636
650
  assert_equal 100, t(@test, @age.coalesce_blank(100))
637
651
  assert_equal 20, t(@test, @age.coalesce_blank(20))
@@ -734,8 +748,10 @@ module ArelExtensions
734
748
  t(@lucas, (@updated_at + Arel.duration('mn', (@updated_at.hour * 60 + @updated_at.minute))))
735
749
 
736
750
  assert_includes ['2024-03-03'], t(@lucas, (@updated_at + durPos).format('%Y-%m-%d'))
751
+ assert_includes ['2024-03-03'], t(@lucas, (@updated_at + durPos).format_date('%Y-%m-%d'))
737
752
  # puts (@updated_at - durPos).to_sql
738
753
  assert_includes ['2004-03-03'], t(@lucas, (@updated_at - durPos).format('%Y-%m-%d'))
754
+ assert_includes ['2004-03-03'], t(@lucas, (@updated_at - durPos).format_date('%Y-%m-%d'))
739
755
 
740
756
 
741
757
  # we test with the ruby object or the string because some adapters don't return an object Date
@@ -775,9 +791,11 @@ module ArelExtensions
775
791
  assert_equal 0, t(@myung, @comments.if_present.count)
776
792
  assert_equal 20.16, t(@myung, @score.if_present)
777
793
  assert_equal '2016-05-23', t(@myung, @created_at.if_present.format('%Y-%m-%d'))
794
+ assert_equal '2016-05-23', t(@myung, @created_at.if_present.format_date('%Y-%m-%d'))
778
795
  assert_nil t(@laure, @comments.if_present)
779
796
 
780
797
  assert_nil t(@nilly, @duration.if_present.format('%Y-%m-%d'))
798
+ assert_nil t(@nilly, @duration.if_present.format_date('%Y-%m-%d'))
781
799
 
782
800
  # NOTE: here we're testing the capacity to format a nil value,
783
801
  # however, @comments is a text field, and not a date/datetime field,
@@ -785,8 +803,10 @@ module ArelExtensions
785
803
  # we need to cast it first.
786
804
  if @env_db == 'postgresql'
787
805
  assert_nil t(@laure, @comments.cast(:date).if_present.format('%Y-%m-%d'))
806
+ assert_nil t(@laure, @comments.cast(:date).if_present.format_date('%Y-%m-%d'))
788
807
  else
789
808
  assert_nil t(@laure, @comments.if_present.format('%Y-%m-%d'))
809
+ assert_nil t(@laure, @comments.if_present.format_date('%Y-%m-%d'))
790
810
  end
791
811
  end
792
812
 
data/version_v1.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module ArelExtensions
2
- VERSION = '1.3.6'.freeze
2
+ VERSION = '1.3.7'.freeze
3
3
  end
data/version_v2.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module ArelExtensions
2
- VERSION = '2.1.6'.freeze
2
+ VERSION = '2.1.7'.freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arel_extensions
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.6
4
+ version: 1.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yann Azoury
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-11-22 00:00:00.000000000 Z
13
+ date: 2023-01-27 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: arel
@@ -123,6 +123,7 @@ files:
123
123
  - lib/arel_extensions/nodes/find_in_set.rb
124
124
  - lib/arel_extensions/nodes/floor.rb
125
125
  - lib/arel_extensions/nodes/format.rb
126
+ - lib/arel_extensions/nodes/formatted_date.rb
126
127
  - lib/arel_extensions/nodes/formatted_number.rb
127
128
  - lib/arel_extensions/nodes/function.rb
128
129
  - lib/arel_extensions/nodes/is_null.rb
@@ -207,7 +208,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
207
208
  - !ruby/object:Gem::Version
208
209
  version: '0'
209
210
  requirements: []
210
- rubygems_version: 3.2.3
211
+ rubygems_version: 3.3.5
211
212
  signing_key:
212
213
  specification_version: 4
213
214
  summary: Extending Arel