postgres_ext 0.1.0 → 0.2.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.
- data/.travis.yml +4 -0
- data/CHANGELOG.md +22 -0
- data/README.md +12 -240
- data/docs/indexes.md +19 -0
- data/docs/migrations.md +76 -0
- data/docs/querying.md +138 -0
- data/docs/type_casting.md +51 -0
- data/lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb +10 -4
- data/lib/postgres_ext/active_record/relation/predicate_builder.rb +71 -0
- data/lib/postgres_ext/active_record/relation/query_methods.rb +84 -0
- data/lib/postgres_ext/active_record/relation.rb +2 -0
- data/lib/postgres_ext/active_record.rb +1 -0
- data/lib/postgres_ext/arel/nodes/contained_within.rb +12 -0
- data/lib/postgres_ext/arel/predications.rb +12 -0
- data/lib/postgres_ext/arel/visitors/to_sql.rb +15 -0
- data/lib/postgres_ext/arel/visitors/visitor.rb +14 -8
- data/lib/postgres_ext/arel/visitors.rb +1 -0
- data/lib/postgres_ext/version.rb +1 -1
- data/postgres_ext.gemspec +2 -2
- data/spec/arel/inet_spec.rb +25 -2
- data/spec/columns/array_spec.rb +39 -0
- data/spec/dummy/db/migrate/20120501163758_create_people.rb +3 -5
- data/spec/dummy/db/schema.rb +11 -7
- data/spec/migrations/array_spec.rb +23 -7
- data/spec/migrations/citext_spec.rb +27 -0
- data/spec/queries/array_queries_spec.rb +57 -0
- data/spec/queries/contains_querie_spec.rb +36 -0
- data/spec/queries/sanity_spec.rb +23 -0
- data/spec/schema_dumper/citext_spec.rb +17 -0
- metadata +26 -8
data/.travis.yml
CHANGED
@@ -8,7 +8,11 @@ rvm:
|
|
8
8
|
before_script:
|
9
9
|
- psql -c 'create database postgres_ext_test;' -U postgres
|
10
10
|
- cp spec/dummy/config/database.yml.example spec/dummy/config/database.yml
|
11
|
+
- RAILS_ENV=test rake db:migrate
|
11
12
|
|
12
13
|
notifications:
|
13
14
|
email:
|
14
15
|
- git@danmcclain.net
|
16
|
+
campfire:
|
17
|
+
rooms:
|
18
|
+
- secure: "yVESPleawl+fzvnzXw/W7rULyCjMEq3gPc3cEqcqM2SBBtEIDNXto2zoTAoR\nC5yqhijr+UtmVMsI7CxVK3XvfkmCJZN9P4DP0uas8XYx5DsSabCdPN0h3pka\nbaDCMCInU5QF4WswL2iuyLsOJeKDRwxh09adsHi1HpMgf0nTKPA="
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
## 0.2.0
|
2
|
+
|
3
|
+
* Introduces extensions to `ActiveRecord::Relation.where` to simplify
|
4
|
+
Array and INET/CIDR queries - Dan McClain (@danmcclain)
|
5
|
+
* Fixes `where(:array => [1,2])` to use equailty instead of IN clauses
|
6
|
+
- Dan McClain (@danmcclain)
|
7
|
+
* Adds Arel predicates for more network comparisons - Patrick Muldoon
|
8
|
+
(@doon)
|
9
|
+
* Adds support for citext in migrations/schema.rb - Jonathan Younger
|
10
|
+
(@daikini)
|
11
|
+
* Fixes text character encoding for text columns - Andy Monat (@amonat)
|
12
|
+
* Cleans up alias_method_chains for better interoperability - Raido
|
13
|
+
Paaslepp (@legendetm)
|
14
|
+
* Doc updates - Dan McClain, Caleb Woods (@danmcclain @calebwoods)
|
15
|
+
|
16
|
+
## 0.1.0
|
17
|
+
|
18
|
+
* Performs PostgreSQL version check before attempting to dumpe
|
19
|
+
extensions - Dan McClain (@danmcclain)
|
20
|
+
* Fixes issues with schema dumper when indexes have no index_opclass -
|
21
|
+
Mario Visic (@mariovisic)
|
22
|
+
|
1
23
|
## 0.0.10
|
2
24
|
|
3
25
|
* Fixes parsing of number arrays when they are set from a string array - Alexey Noskov (@alno)
|
data/README.md
CHANGED
@@ -5,10 +5,13 @@ Adds support for missing PostgreSQL data types to ActiveRecord.
|
|
5
5
|
[](http://travis-ci.org/dockyard/postgres_ext)
|
6
6
|
[](https://codeclimate.com/github/dockyard/postgres_ext)
|
7
7
|
|
8
|
-
##
|
8
|
+
## Looking for help? ##
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
If it is a bug [please open an issue on
|
11
|
+
Github](https://github.com/dockyard/party_foul/issues). If you need help using
|
12
|
+
the gem please ask the question on
|
13
|
+
[Stack Overflow](http://stackoverflow.com). Be sure to tag the
|
14
|
+
question with `DockYard` so we can find it.
|
12
15
|
|
13
16
|
## Installation
|
14
17
|
|
@@ -29,11 +32,12 @@ Or install it yourself as:
|
|
29
32
|
Just `require 'postgres_ext'` and use ActiveRecord as you normally would! postgres\_ext extends
|
30
33
|
ActiveRecord's data type handling.
|
31
34
|
|
32
|
-
* [Migration/Schema.rb support](
|
33
|
-
* [Type Casting support](
|
34
|
-
* [Querying PostgreSQL datatypes](
|
35
|
+
* [Migration/Schema.rb support](docs/migrations.md)
|
36
|
+
* [Type Casting support](docs/type_casting.md)
|
37
|
+
* [Querying PostgreSQL datatypes](docs/querying.md)
|
38
|
+
* [Indexes](docs/indexes.md)
|
35
39
|
|
36
|
-
|
40
|
+
## Usage Notes
|
37
41
|
Avoid the use of in place operators (ie `Array#<<`). These changes are
|
38
42
|
*not* tracked by Rails ([this issue](https://github.com/rails/rails/issues/6954))
|
39
43
|
explains why). In place modifications also modify the default object.
|
@@ -64,7 +68,7 @@ The supported way of modifying `a.names`:
|
|
64
68
|
|
65
69
|
```ruby
|
66
70
|
a = Item.new
|
67
|
-
a.names += 'foo'
|
71
|
+
a.names += ['foo']
|
68
72
|
|
69
73
|
b = Item.new
|
70
74
|
puts b.names
|
@@ -74,240 +78,8 @@ puts b.names
|
|
74
78
|
As a result, in place operators are discouraged and will not be
|
75
79
|
supported in postgres\_ext at this time.
|
76
80
|
|
77
|
-
## Migration/Schema.rb support
|
78
81
|
|
79
|
-
### INET
|
80
82
|
|
81
|
-
```ruby
|
82
|
-
create_table :testing do |t|
|
83
|
-
t.inet :inet_column
|
84
|
-
# or
|
85
|
-
t.inet :inet_column_1, :inet_column_2
|
86
|
-
# or
|
87
|
-
t.column :inet_column, :inet
|
88
|
-
end
|
89
|
-
```
|
90
|
-
|
91
|
-
### CIDR
|
92
|
-
|
93
|
-
```ruby
|
94
|
-
create_table :testing do |t|
|
95
|
-
t.cidr :cidr_column
|
96
|
-
# or
|
97
|
-
t.cidr :cidr_column_1, :cidr_column_2
|
98
|
-
# or
|
99
|
-
t.column :cidr_column, :cidr
|
100
|
-
end
|
101
|
-
```
|
102
|
-
|
103
|
-
### MACADDR
|
104
|
-
|
105
|
-
```ruby
|
106
|
-
create_table :testing do |t|
|
107
|
-
t.macaddr :macaddr_column
|
108
|
-
# or
|
109
|
-
t.macaddr :macaddr_column_1, :macaddr_column_2
|
110
|
-
# or
|
111
|
-
t.column :macaddr_column, :macaddr
|
112
|
-
end
|
113
|
-
```
|
114
|
-
|
115
|
-
### UUID
|
116
|
-
|
117
|
-
```ruby
|
118
|
-
create_table :testing do |t|
|
119
|
-
t.uuid :uuid_column
|
120
|
-
# or
|
121
|
-
t.uuid :uuid_column_1, :uuid_column_2
|
122
|
-
# or
|
123
|
-
t.column :uuid_column, :uuid
|
124
|
-
end
|
125
|
-
```
|
126
|
-
|
127
|
-
### Arrays
|
128
|
-
Arrays are created from any ActiveRecord supported datatype (including
|
129
|
-
ones added by postgre\_ext), and respect length constraints
|
130
|
-
|
131
|
-
```ruby
|
132
|
-
create_table :testing do |t|
|
133
|
-
t.integer :int_array, :array => true
|
134
|
-
# integer[]
|
135
|
-
t.integer :int_array, :array => true, :limit => 2
|
136
|
-
# smallint[]
|
137
|
-
t.string :macaddr_column_1, :array => true, :limit => 30
|
138
|
-
# char varying(30)[]
|
139
|
-
end
|
140
|
-
```
|
141
|
-
|
142
|
-
## Type Casting support
|
143
|
-
|
144
|
-
### INET and CIDR
|
145
|
-
INET and CIDR values are converted to
|
146
|
-
[IPAddr](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/ipaddr/rdoc/IPAddr.html)
|
147
|
-
objects when retrieved from the database, or set as a string.
|
148
|
-
|
149
|
-
```ruby
|
150
|
-
create_table :inet_examples do |t|
|
151
|
-
t.inet :ip_address
|
152
|
-
end
|
153
|
-
|
154
|
-
class InetExample < ActiveRecord::Base
|
155
|
-
end
|
156
|
-
|
157
|
-
inetExample = InetExample.new
|
158
|
-
inetExample.ip_address = '127.0.0.0/24'
|
159
|
-
inetExample.ip_address
|
160
|
-
# => #<IPAddr: IPv4:127.0.0.0/255.255.255.0>
|
161
|
-
inetExample.save
|
162
|
-
|
163
|
-
inet_2 = InetExample.first
|
164
|
-
inet_2.ip_address
|
165
|
-
# => #<IPAddr: IPv4:127.0.0.0/255.255.255.0>
|
166
|
-
```
|
167
|
-
|
168
|
-
### Arrays
|
169
|
-
Array values can be set with Array objects. Any array stored in the
|
170
|
-
database will be converted to a properly casted array of values on the
|
171
|
-
way out.
|
172
|
-
|
173
|
-
```ruby
|
174
|
-
create_table :people do |t|
|
175
|
-
t.integer :favorite_numbers, :array => true
|
176
|
-
end
|
177
|
-
|
178
|
-
class Person < ActiveRecord::Base
|
179
|
-
end
|
180
|
-
|
181
|
-
person = Person.new
|
182
|
-
person.favorite_numbers = [1,2,3]
|
183
|
-
person.favorite_numbers
|
184
|
-
# => [1,2,3]
|
185
|
-
person.save
|
186
|
-
|
187
|
-
person_2 = Person.first
|
188
|
-
person_2.favorite_numbers
|
189
|
-
# => [1,2,3]
|
190
|
-
person_2.favorite_numbers.first.class
|
191
|
-
# => Fixnum
|
192
|
-
```
|
193
|
-
|
194
|
-
## Querying PostgreSQL datatypes
|
195
|
-
|
196
|
-
* [Arrays](#arrays-2)
|
197
|
-
* [INET/CIDR](#inetcidr)
|
198
|
-
|
199
|
-
### Arrays
|
200
|
-
|
201
|
-
* [&& - Array Overlap operator](#---array-overlap-operator)
|
202
|
-
* [ANY or ALL functions](#any-or-all-functions)
|
203
|
-
|
204
|
-
#### && - Array Overlap operator
|
205
|
-
|
206
|
-
PostgreSQL implements the `&&` operator, known as the overlap operator,
|
207
|
-
for arrays. The overlap operator returns `t` (true) when two arrays have
|
208
|
-
one or more elements in common.
|
209
|
-
|
210
|
-
```sql
|
211
|
-
ARRAY[1,2,3] && ARRAY[4,5,6]
|
212
|
-
-- f
|
213
|
-
|
214
|
-
ARRAY[1,2,3] && ARRAY[3,5,6]
|
215
|
-
-- t
|
216
|
-
```
|
217
|
-
|
218
|
-
Postgres\_ext defines `array_overlap`, an [Arel](https://github.com/rails/arel)
|
219
|
-
predicate for the `&&` operator.
|
220
|
-
|
221
|
-
```ruby
|
222
|
-
user_arel = User.arel_table
|
223
|
-
|
224
|
-
# Execute the query
|
225
|
-
User.where(user_arel[:tags].array_overlap(['one','two']))
|
226
|
-
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"tags\" && '{one,two}'
|
227
|
-
```
|
228
|
-
|
229
|
-
#### ANY or ALL functions
|
230
|
-
|
231
|
-
When querying array columns, you have the ability to see if a predicate
|
232
|
-
apply's to either *any* element in the array, or *all* elements of the
|
233
|
-
array. The syntax for these predicates are slightly different then the
|
234
|
-
normal `where` syntax in PostgreSQL. To see if an array contains the
|
235
|
-
string `'test'` in any location, you would write the following in SQL
|
236
|
-
|
237
|
-
```sql
|
238
|
-
SELECT *
|
239
|
-
FROM users
|
240
|
-
WHERE 'test' = ANY(users.tags)
|
241
|
-
```
|
242
|
-
|
243
|
-
Notice that the column is on the right hand side of the predicate,
|
244
|
-
instead of the left, because we have to call the `ANY` function on that
|
245
|
-
column.
|
246
|
-
|
247
|
-
We can generate the above query using [Arel](https://github.com/rails/arel)
|
248
|
-
and generating the Node manually. We would use the following to
|
249
|
-
accompish this:
|
250
|
-
|
251
|
-
```ruby
|
252
|
-
user_arel = User.arel_table
|
253
|
-
|
254
|
-
any_tags_function = Arel::Nodes::NamedFunction.new('ANY', [user_arel[:tags]])
|
255
|
-
predicate = Arel::Nodes::Equality.new('test', any_tags_function)
|
256
|
-
|
257
|
-
# Execute the query
|
258
|
-
User.where(predicate)
|
259
|
-
#=> SELECT \"users\".* FROM \"users\" WHERE 'test' = ANY(\"users\".\"tags\")
|
260
|
-
```
|
261
|
-
|
262
|
-
The ALL version of this same predicate can be generated by swap `'ANY'`
|
263
|
-
for `'ALL'` in the named function.
|
264
|
-
|
265
|
-
### INET/CIDR
|
266
|
-
|
267
|
-
#### `<<` -- Contained within operator
|
268
|
-
|
269
|
-
PostgreSQL defines the `<<`, or contained within operator for INET and
|
270
|
-
CIDR datatypes. The `<<` operator returns `t` (true) if a INET or CIDR
|
271
|
-
address is contained within the given subnet.
|
272
|
-
|
273
|
-
```sql
|
274
|
-
inet '192.168.1.6' << inet '10.0.0.0/24'
|
275
|
-
-- f
|
276
|
-
|
277
|
-
inet '192.168.1.6' << inet '192.168.1.0/24'
|
278
|
-
-- t
|
279
|
-
```
|
280
|
-
|
281
|
-
Postgres\_ext defines `contained_within`, an [Arel](https://github.com/rails/arel)
|
282
|
-
predicate for the `<<` operator.
|
283
|
-
|
284
|
-
```ruby
|
285
|
-
user_arel = User.arel_table
|
286
|
-
|
287
|
-
# Execute the query
|
288
|
-
User.where(user_arel[:ip_address].contained_witin('127.0.0.1/24'))
|
289
|
-
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"ip_address\" << '127.0.0.1/24'
|
290
|
-
```
|
291
|
-
|
292
|
-
## Indexes
|
293
|
-
|
294
|
-
### Index types
|
295
|
-
|
296
|
-
Postgres\_ext allows you to specify index type and index operator
|
297
|
-
class at index creation.
|
298
|
-
|
299
|
-
```ruby
|
300
|
-
add_index :table_name, :column, :index_type => :gin
|
301
|
-
add_index :table_name, :column, :index_type => :gin, :index_opclass => :gin_trgm_ops
|
302
|
-
```
|
303
|
-
|
304
|
-
### Where clauses
|
305
|
-
|
306
|
-
Postgres\_ext allows you to specify a where clause at index creation.
|
307
|
-
|
308
|
-
```ruby
|
309
|
-
add_index :table_name, :column, :where => 'column < 50'
|
310
|
-
```
|
311
83
|
|
312
84
|
## Authors
|
313
85
|
|
data/docs/indexes.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# Indexes
|
2
|
+
|
3
|
+
## Index types
|
4
|
+
|
5
|
+
Postgres\_ext allows you to specify index type and index operator
|
6
|
+
class at index creation.
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
add_index :table_name, :column, :index_type => :gin
|
10
|
+
add_index :table_name, :column, :index_type => :gin, :index_opclass => :gin_trgm_ops
|
11
|
+
```
|
12
|
+
|
13
|
+
## Where clauses
|
14
|
+
|
15
|
+
Postgres\_ext allows you to specify a where clause at index creation.
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
add_index :table_name, :column, :where => 'column < 50'
|
19
|
+
```
|
data/docs/migrations.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Migration/Schema.rb support
|
2
|
+
|
3
|
+
## INET
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
create_table :testing do |t|
|
7
|
+
t.inet :inet_column
|
8
|
+
# or
|
9
|
+
t.inet :inet_column_1, :inet_column_2
|
10
|
+
# or
|
11
|
+
t.column :inet_column, :inet
|
12
|
+
end
|
13
|
+
```
|
14
|
+
|
15
|
+
## CIDR
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
create_table :testing do |t|
|
19
|
+
t.cidr :cidr_column
|
20
|
+
# or
|
21
|
+
t.cidr :cidr_column_1, :cidr_column_2
|
22
|
+
# or
|
23
|
+
t.column :cidr_column, :cidr
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
## MACADDR
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
create_table :testing do |t|
|
31
|
+
t.macaddr :macaddr_column
|
32
|
+
# or
|
33
|
+
t.macaddr :macaddr_column_1, :macaddr_column_2
|
34
|
+
# or
|
35
|
+
t.column :macaddr_column, :macaddr
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
## UUID
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
create_table :testing do |t|
|
43
|
+
t.uuid :uuid_column
|
44
|
+
# or
|
45
|
+
t.uuid :uuid_column_1, :uuid_column_2
|
46
|
+
# or
|
47
|
+
t.column :uuid_column, :uuid
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
## CITEXT
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
create_table :testing do |t|
|
55
|
+
t.citext :citext_column
|
56
|
+
# or
|
57
|
+
t.citext :citext_column_1, :citext_column_2
|
58
|
+
# or
|
59
|
+
t.column :citext_column, :citext
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
## Arrays
|
64
|
+
Arrays are created from any ActiveRecord supported datatype (including
|
65
|
+
ones added by postgres\_ext), and respect length constraints
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
create_table :testing do |t|
|
69
|
+
t.integer :int_array, :array => true
|
70
|
+
# integer[]
|
71
|
+
t.integer :int_array, :array => true, :limit => 2
|
72
|
+
# smallint[]
|
73
|
+
t.string :macaddr_column_1, :array => true, :limit => 30
|
74
|
+
# char varying(30)[]
|
75
|
+
end
|
76
|
+
```
|
data/docs/querying.md
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
# Querying PostgreSQL datatypes
|
2
|
+
|
3
|
+
* [Arrays](#arrays)
|
4
|
+
* [INET/CIDR](#inetcidr-queries)
|
5
|
+
|
6
|
+
## Arrays
|
7
|
+
|
8
|
+
* [&& - Array Overlap operator](#---array-overlap-operator)
|
9
|
+
* [ANY or ALL functions](#any-or-all-functions)
|
10
|
+
|
11
|
+
### && - Array Overlap operator
|
12
|
+
|
13
|
+
PostgreSQL implements the `&&` operator, known as the overlap operator,
|
14
|
+
for arrays. The overlap operator returns `t` (true) when two arrays have
|
15
|
+
one or more elements in common.
|
16
|
+
|
17
|
+
```sql
|
18
|
+
ARRAY[1,2,3] && ARRAY[4,5,6]
|
19
|
+
-- f
|
20
|
+
|
21
|
+
ARRAY[1,2,3] && ARRAY[3,5,6]
|
22
|
+
-- t
|
23
|
+
```
|
24
|
+
|
25
|
+
Postgres\_ext extends the `ActiveRecord::Relation.where` method similar
|
26
|
+
to the Rails 4.0 not clause. The easiest way to make a overlap query
|
27
|
+
would be:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
User.where.overlap(:nick_names => ['Bob', 'Fred'])
|
31
|
+
```
|
32
|
+
|
33
|
+
Postgres\_ext defines `array_overlap`, an [Arel](https://github.com/rails/arel)
|
34
|
+
predicate for the `&&` operator. This is utilized by the `where.overlap`
|
35
|
+
call above.
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
user_arel = User.arel_table
|
39
|
+
|
40
|
+
# Execute the query
|
41
|
+
User.where(user_arel[:tags].array_overlap(['one','two']))
|
42
|
+
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"tags\" && '{one,two}'
|
43
|
+
```
|
44
|
+
|
45
|
+
### ANY or ALL functions
|
46
|
+
|
47
|
+
When querying array columns, you have the ability to see if a predicate
|
48
|
+
apply's to either *any* element in the array, or *all* elements of the
|
49
|
+
array. The syntax for these predicates are slightly different then the
|
50
|
+
normal `where` syntax in PostgreSQL. To see if an array contains the
|
51
|
+
string `'test'` in any location, you would write the following in SQL
|
52
|
+
|
53
|
+
```sql
|
54
|
+
SELECT *
|
55
|
+
FROM users
|
56
|
+
WHERE 'test' = ANY(users.tags)
|
57
|
+
```
|
58
|
+
|
59
|
+
Notice that the column is on the right hand side of the predicate,
|
60
|
+
instead of the left, because we have to call the `ANY` function on that
|
61
|
+
column.
|
62
|
+
|
63
|
+
Postgres\_ext provides a `ActiveRecord::Relation.where.any()` method. The
|
64
|
+
easiest way to make a ANY query would be:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
User.where.any(:nick_names => 'Bob')
|
68
|
+
```
|
69
|
+
|
70
|
+
There is also an `ActiveRecord::Relation.where.all()` call as well. This
|
71
|
+
method utilizes the following code to create the query:
|
72
|
+
|
73
|
+
We can generate the above query using [Arel](https://github.com/rails/arel)
|
74
|
+
and generating the Node manually. We would use the following to
|
75
|
+
accompish this:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
user_arel = User.arel_table
|
79
|
+
|
80
|
+
any_tags_function = Arel::Nodes::NamedFunction.new('ANY', [user_arel[:tags]])
|
81
|
+
predicate = Arel::Nodes::Equality.new('test', any_tags_function)
|
82
|
+
|
83
|
+
# Execute the query
|
84
|
+
User.where(predicate)
|
85
|
+
#=> SELECT \"users\".* FROM \"users\" WHERE 'test' = ANY(\"users\".\"tags\")
|
86
|
+
```
|
87
|
+
|
88
|
+
The ALL version of this same predicate can be generated by swap `'ANY'`
|
89
|
+
for `'ALL'` in the named function.
|
90
|
+
|
91
|
+
## INET/CIDR Queries
|
92
|
+
|
93
|
+
PostgreSQL defines the `<<`, or contained within operator for INET and
|
94
|
+
CIDR datatypes. The `<<` operator returns `t` (true) if a INET or CIDR
|
95
|
+
address is contained within the given subnet.
|
96
|
+
|
97
|
+
```sql
|
98
|
+
inet '192.168.1.6' << inet '10.0.0.0/24'
|
99
|
+
-- f
|
100
|
+
|
101
|
+
inet '192.168.1.6' << inet '192.168.1.0/24'
|
102
|
+
-- t
|
103
|
+
```
|
104
|
+
|
105
|
+
In addition to contained within, there is also:
|
106
|
+
|
107
|
+
* `<<=` - Contained within or equals
|
108
|
+
* `>>` - Contains
|
109
|
+
* `>>=` - Contains or equals
|
110
|
+
|
111
|
+
Postgres\_ext extends the `ActiveRecord::Relation.where` method similar
|
112
|
+
to the Rails 4.0 not clause. The easiest way to make a overlap query
|
113
|
+
would be:
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
User.where.contained_within(:ip => '192.168.1.1/24')
|
117
|
+
User.where.contained_within_or_equals(:ip => '192.168.1.1/24')
|
118
|
+
User.where.contains(:ip => '192.168.1.14')
|
119
|
+
User.where.contains_or_equals(:ip => '192.168.1.14')
|
120
|
+
```
|
121
|
+
|
122
|
+
Postgres\_ext defines `contained_within`, an [Arel](https://github.com/rails/arel)
|
123
|
+
predicate for the `<<` operator. This is utilized by the
|
124
|
+
methods above.
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
user_arel = User.arel_table
|
128
|
+
|
129
|
+
# Execute the query
|
130
|
+
User.where(user_arel[:ip_address].contained_within('127.0.0.1/24'))
|
131
|
+
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"ip_address\" << '127.0.0.1/24'
|
132
|
+
User.where(user_arel[:ip_address].contained_within_or_equals('127.0.0.1/24'))
|
133
|
+
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"ip_address\" <<= '127.0.0.1/24'
|
134
|
+
User.where(user_arel[:ip_address].contains('127.0.0.1'))
|
135
|
+
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"ip_address\" >> '127.0.0.1'
|
136
|
+
User.where(user_arel[:ip_address].contains_or_equals('127.0.0.1'))
|
137
|
+
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"ip_address\" >>= '127.0.0.1'
|
138
|
+
```
|