arel-extensions 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -195
- data/arel-extensions.gemspec +1 -1
- data/lib/active_record/query_methods.rb +37 -0
- data/lib/arel/array_predications.rb +6 -6
- data/lib/arel/extensions.rb +2 -0
- data/lib/arel/visitors/postgresql_extensions.rb +2 -2
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea6bb2f32dc1602cd546c28188fe5ed2be2a0f09
|
4
|
+
data.tar.gz: e11ccebf5147a7d83f7e081c17bda2e387aa6b41
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd5bb4101f987f0143643d01437550e141b2867ff5447e9e15164cb0359e44445f15a188bcf72d12ac729602e9f5093dfcaf618c6646dbbc68ca11002e8e6274
|
7
|
+
data.tar.gz: 39827c24bc7ed46ee7d2578db388f30d38c00ef489acf98d49929401e5476c33f05aaff91363125dcf420917f643393b68e351675b6bfe6d8df2bd10f567c541
|
data/README.md
CHANGED
@@ -19,198 +19,4 @@ Or install it yourself as:
|
|
19
19
|
## Usage
|
20
20
|
|
21
21
|
Just `require 'arel-extensions'` and use Arel/ActiveRecord as you normally would!
|
22
|
-
arel-extensions extends ActiveRecord's query methods in both Arel and ActiveRecord.
|
23
|
-
|
24
|
-
* [Querying PostgreSQL datatypes](docs/querying.md)
|
25
|
-
|
26
|
-
## Arrays
|
27
|
-
|
28
|
-
* [@> - Array Contains operator](#---array-contains-operator)
|
29
|
-
* [<@ - Array Contained By operator](#---array-contined-by-operator)
|
30
|
-
* [&& - Array Overlap operator](#---array-overlap-operator)
|
31
|
-
|
32
|
-
### && - Array Overlap operator
|
33
|
-
|
34
|
-
PostgreSQL implements the `&&` operator, known as the overlap operator,
|
35
|
-
for arrays. The overlap operator returns `t` (true) when two arrays have
|
36
|
-
one or more elements in common.
|
37
|
-
|
38
|
-
```sql
|
39
|
-
ARRAY[1,2,3] && ARRAY[4,5,6]
|
40
|
-
-- f
|
41
|
-
|
42
|
-
ARRAY[1,2,3] && ARRAY[3,5,6]
|
43
|
-
-- t
|
44
|
-
```
|
45
|
-
|
46
|
-
Postgres\_ext extends the `ActiveRecord::Relation.where` method similar
|
47
|
-
to the Rails 4.0 not clause. The easiest way to make a overlap query
|
48
|
-
would be:
|
49
|
-
|
50
|
-
```ruby
|
51
|
-
User.where.overlap(:nick_names => ['Bob', 'Fred'])
|
52
|
-
```
|
53
|
-
|
54
|
-
Postgres\_ext defines `overlap`, an [Arel](https://github.com/rails/arel)
|
55
|
-
predicate for the `&&` operator. This is utilized by the `where.overlap`
|
56
|
-
call above.
|
57
|
-
|
58
|
-
```ruby
|
59
|
-
user_arel = User.arel_table
|
60
|
-
|
61
|
-
# Execute the query
|
62
|
-
User.where(user_arel[:tags].overlap(['one','two']))
|
63
|
-
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"tags\" && '{one,two}'
|
64
|
-
```
|
65
|
-
|
66
|
-
### @> - Array Contains operator
|
67
|
-
|
68
|
-
PostgreSQL has a contains (`@>`) operator for querying whether all the
|
69
|
-
elements of an array are within another.
|
70
|
-
|
71
|
-
```sql
|
72
|
-
ARRAY[1,2,3] @> ARRAY[3,4]
|
73
|
-
-- f
|
74
|
-
|
75
|
-
ARRAY[1,2,3] @> ARRAY[2,3]
|
76
|
-
-- t
|
77
|
-
```
|
78
|
-
|
79
|
-
Postgres\_ext extends the `ActiveRecord::Relation.where` method by
|
80
|
-
adding a `contains` method. To make a contains query, you can do:
|
81
|
-
|
82
|
-
```ruby
|
83
|
-
User.where.contains(:nick_names => ['Bob', 'Fred'])
|
84
|
-
```
|
85
|
-
|
86
|
-
Postgres\_ext overrides `contains`, an [Arel](https://github.com/rails/arel)
|
87
|
-
predicate, to use the `@>` operator for arrays. This is utilized by the
|
88
|
-
`where.contains` call above.
|
89
|
-
|
90
|
-
```ruby
|
91
|
-
user_arel = User.arel_table
|
92
|
-
|
93
|
-
# Execute the query
|
94
|
-
User.where(user_arel[:tags].contains(['one','two']))
|
95
|
-
# => SELECT "users".* FROM "users" WHERE "users"."tags" @> '{"one","two"}'
|
96
|
-
```
|
97
|
-
|
98
|
-
### ANY or ALL functions
|
99
|
-
|
100
|
-
When querying array columns, you have the ability to see if a predicate
|
101
|
-
apply's to either *any* element in the array, or *all* elements of the
|
102
|
-
array. The syntax for these predicates are slightly different then the
|
103
|
-
normal `where` syntax in PostgreSQL. To see if an array contains the
|
104
|
-
string `'test'` in any location, you would write the following in SQL
|
105
|
-
|
106
|
-
```sql
|
107
|
-
SELECT *
|
108
|
-
FROM users
|
109
|
-
WHERE 'test' = ANY(users.tags)
|
110
|
-
```
|
111
|
-
|
112
|
-
Notice that the column is on the right hand side of the predicate,
|
113
|
-
instead of the left, because we have to call the `ANY` function on that
|
114
|
-
column.
|
115
|
-
|
116
|
-
Postgres\_ext provides a `ActiveRecord::Relation.where.any()` method. The
|
117
|
-
easiest way to make a ANY query would be:
|
118
|
-
|
119
|
-
```ruby
|
120
|
-
User.where.any(:nick_names => 'Bob')
|
121
|
-
```
|
122
|
-
|
123
|
-
There is also an `ActiveRecord::Relation.where.all()` call as well. This
|
124
|
-
method utilizes the following code to create the query:
|
125
|
-
|
126
|
-
We can generate the above query using [Arel](https://github.com/rails/arel)
|
127
|
-
and generating the Node manually. We would use the following to
|
128
|
-
accompish this:
|
129
|
-
|
130
|
-
```ruby
|
131
|
-
user_arel = User.arel_table
|
132
|
-
|
133
|
-
# Execute the query
|
134
|
-
User.where(user_arel[:tags].any('test'))
|
135
|
-
#=> SELECT \"users\".* FROM \"users\" WHERE 'test' = ANY(\"users\".\"tags\")
|
136
|
-
```
|
137
|
-
|
138
|
-
The ALL version of this same predicate can be generated by swapping
|
139
|
-
`#any()` for `#all()`.
|
140
|
-
|
141
|
-
## INET/CIDR Queries
|
142
|
-
|
143
|
-
PostgreSQL defines the `<<`, or contained within operator for INET and
|
144
|
-
CIDR datatypes. The `<<` operator returns `t` (true) if a INET or CIDR
|
145
|
-
address is contained within the given subnet.
|
146
|
-
|
147
|
-
```sql
|
148
|
-
inet '192.168.1.6' << inet '10.0.0.0/24'
|
149
|
-
-- f
|
150
|
-
|
151
|
-
inet '192.168.1.6' << inet '192.168.1.0/24'
|
152
|
-
-- t
|
153
|
-
```
|
154
|
-
|
155
|
-
In addition to contained within, there is also:
|
156
|
-
|
157
|
-
* `<<=` - Contained within or equals
|
158
|
-
* `>>` - Contains
|
159
|
-
* `>>=` - Contains or equals
|
160
|
-
|
161
|
-
Postgres\_ext extends the `ActiveRecord::Relation.where` method similar
|
162
|
-
to the Rails 4.0 not clause. The easiest way to make a overlap query
|
163
|
-
would be:
|
164
|
-
|
165
|
-
```ruby
|
166
|
-
User.where.contained_within(:ip => '192.168.1.1/24')
|
167
|
-
User.where.contained_within_or_equals(:ip => '192.168.1.1/24')
|
168
|
-
User.where.contains(:ip => '192.168.1.14')
|
169
|
-
User.where.contains_or_equals(:ip => '192.168.1.14')
|
170
|
-
```
|
171
|
-
|
172
|
-
Postgres\_ext defines `contained_within`, an [Arel](https://github.com/rails/arel)
|
173
|
-
predicate for the `<<` operator. This is utilized by the
|
174
|
-
methods above.
|
175
|
-
|
176
|
-
```ruby
|
177
|
-
user_arel = User.arel_table
|
178
|
-
|
179
|
-
# Execute the query
|
180
|
-
User.where(user_arel[:ip_address].contained_within('127.0.0.1/24'))
|
181
|
-
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"ip_address\" << '127.0.0.1/24'
|
182
|
-
User.where(user_arel[:ip_address].contained_within_or_equals('127.0.0.1/24'))
|
183
|
-
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"ip_address\" <<= '127.0.0.1/24'
|
184
|
-
User.where(user_arel[:ip_address].contains('127.0.0.1'))
|
185
|
-
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"ip_address\" >> '127.0.0.1'
|
186
|
-
User.where(user_arel[:ip_address].contains_or_equals('127.0.0.1'))
|
187
|
-
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"ip_address\" >>= '127.0.0.1'
|
188
|
-
```
|
189
|
-
|
190
|
-
## Developing
|
191
|
-
|
192
|
-
To work on postgres\_ext locally, follow these steps:
|
193
|
-
|
194
|
-
1. Run `bundle install`, this will install (almost) all the development
|
195
|
-
dependencies
|
196
|
-
2. Run `gem install byebug` (not a declared dependency to not break CI)
|
197
|
-
3. Run `bundle exec rake db:setup`, this will set up the `.env` file necessary to run
|
198
|
-
the tests and set up the database
|
199
|
-
4. Run `bundle exec rake db:create`, this will create the test database
|
200
|
-
5. Run `bundle exec rake db:migrate`, this will set up the database tables required
|
201
|
-
by the test
|
202
|
-
6. Run `BUNDLE_GEMFILE='gemfiles/Gemfile.activerecord-4.0.x' bundle install --quiet` to create the Gemfile.lock for 4.0.
|
203
|
-
7. Run `BUNDLE_GEMFILE='gemfiles/Gemfile.activerecord-4.1.x' bundle install --quiet` to create the Gemfile.lock for 4.1.
|
204
|
-
8. Run `bundle exec rake test:all` to run tests against all supported versions of Active Record
|
205
|
-
|
206
|
-
## Authors
|
207
|
-
|
208
|
-
Dan McClain [twitter](http://twitter.com/_danmcclain) [github](http://github.com/danmcclain)
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
Change.arel_table[:diff].has_key?(:in_review)
|
215
|
-
Change.arel_table[:diff].has_keys?(:in_review, :cached_at)
|
216
|
-
Change.arel_table[:diff].has_any_key?(:in_review, :nokey)
|
22
|
+
arel-extensions extends ActiveRecord's query methods in both Arel and ActiveRecord.
|
data/arel-extensions.gemspec
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_record/relation'
|
3
|
+
require 'active_record/querying'
|
4
|
+
require 'active_record/relation/query_methods'
|
5
|
+
|
6
|
+
module ActiveRecord::QueryMethods
|
7
|
+
def distinct_on_values
|
8
|
+
@values["distinct_on_values"] || []
|
9
|
+
end
|
10
|
+
|
11
|
+
def distinct_on_values=(value)
|
12
|
+
@values["distinct_on_values"] = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def distinct_on(*fields)
|
16
|
+
spawn.distinct_on!(*fields)
|
17
|
+
end
|
18
|
+
alias uniq_on distinct_on
|
19
|
+
|
20
|
+
def distinct_on!(*fields)
|
21
|
+
fields.flatten!
|
22
|
+
self.distinct_on_values = fields.map { |x| x.is_a?(Arel::Attributes::Attribute) ? x : klass.arel_table[x] }
|
23
|
+
self
|
24
|
+
end
|
25
|
+
alias uniq_on! distinct_on!
|
26
|
+
|
27
|
+
def build_arel_with_distinct_on
|
28
|
+
arel = build_arel_without_distinct_on
|
29
|
+
arel.distinct_on(self.distinct_on_values) if !self.distinct_on_values.empty?
|
30
|
+
arel
|
31
|
+
end
|
32
|
+
alias_method :build_arel_without_distinct_on, :build_arel
|
33
|
+
alias_method :build_arel, :build_arel_with_distinct_on
|
34
|
+
end
|
35
|
+
|
36
|
+
ActiveRecord::Querying.delegate :distinct_on, to: :all
|
37
|
+
ActiveRecord::Querying.delegate :distinct_on!, to: :all
|
@@ -1,14 +1,14 @@
|
|
1
1
|
module Arel
|
2
2
|
module ArrayPredications
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
Arel::Nodes::Contains.new(self,
|
4
|
+
# Used by both JSON and ARRAY so it doesn't try to cast to array
|
5
|
+
def contains(value)
|
6
|
+
Arel::Nodes::Contains.new(self, value)
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
Arel::Nodes::ContainedBy.new(self,
|
9
|
+
# Used by both JSON and ARRAY so it doesn't try to cast to array
|
10
|
+
def contained_by(value)
|
11
|
+
Arel::Nodes::ContainedBy.new(self, value)
|
12
12
|
end
|
13
13
|
|
14
14
|
def overlaps(*values)
|
data/lib/arel/extensions.rb
CHANGED
@@ -18,6 +18,8 @@ require File.expand_path('../nodes/ts_match', __FILE__)
|
|
18
18
|
require File.expand_path('../ts_predications', __FILE__)
|
19
19
|
Arel::Attributes::Attribute.include(Arel::TSPredications)
|
20
20
|
|
21
|
+
require File.expand_path('../../active_record/query_methods', __FILE__)
|
22
|
+
|
21
23
|
if defined?(Arel::Visitors::PostgreSQL)
|
22
24
|
require File.expand_path('../visitors/postgresql_extensions', __FILE__)
|
23
25
|
end
|
@@ -41,7 +41,7 @@ module Arel
|
|
41
41
|
end
|
42
42
|
else
|
43
43
|
visit(o.relation, collector)
|
44
|
-
collector << "
|
44
|
+
collector << "\#>'{" << o.name.to_s
|
45
45
|
collector << (last_key ? "}'" : ",")
|
46
46
|
end
|
47
47
|
collector
|
@@ -94,4 +94,4 @@ module Arel
|
|
94
94
|
|
95
95
|
end
|
96
96
|
end
|
97
|
-
end
|
97
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arel-extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Bracy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-03-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: arel
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- LICENSE
|
63
63
|
- README.md
|
64
64
|
- arel-extensions.gemspec
|
65
|
+
- lib/active_record/query_methods.rb
|
65
66
|
- lib/arel/array_predications.rb
|
66
67
|
- lib/arel/attributes/cast.rb
|
67
68
|
- lib/arel/attributes/key.rb
|
@@ -98,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
99
|
version: '0'
|
99
100
|
requirements: []
|
100
101
|
rubyforge_project:
|
101
|
-
rubygems_version: 2.6.
|
102
|
+
rubygems_version: 2.6.8
|
102
103
|
signing_key:
|
103
104
|
specification_version: 4
|
104
105
|
summary: Adds support for missing SQL operators and functions to Arel
|