arel-extensions 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4847138fb20c8ca58e5bf419b595e1cf9e4dc809
4
+ data.tar.gz: 54565109b15574583361a153a2558bdb5deac376
5
+ SHA512:
6
+ metadata.gz: d934dc0afa953e09db3837747ebc919ae473901f6da32033a76635261eda113c75504a7ac98c861b48983993c2e0dace2f439f31d18542b62e01ce30b1d66d74
7
+ data.tar.gz: f568ff754c5f16fca13c73925353ffe9aae53fcd1cdfa8da74dafebabef5110c0308135375241c8c82e7bb2f420229da4ec41bdc3d9b99e055215d387a988ae6
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Jon Bracy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,216 @@
1
+ # Arel Extensions
2
+
3
+ Adds support for missing SQL operators and functions to Arel for ActiveRecord.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'arel-extensions', require: 'arel/extensions'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install arel-extensions
18
+
19
+ ## Usage
20
+
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)
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |gem|
2
+ gem.name = 'arel-extensions'
3
+ gem.version = '1.0.0'
4
+
5
+ gem.authors = ["Jon Bracy"]
6
+ gem.email = ["jonbracy@gmail.com"]
7
+ gem.summary = %q{Adds support for missing SQL operators and functions to Arel}
8
+ gem.homepage = 'https://github.com/malomalo/arel-extensions'
9
+ gem.licenses = ['MIT']
10
+
11
+ gem.files = `git ls-files`.split("\n")
12
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
13
+ gem.require_paths = ["lib"]
14
+
15
+ gem.add_dependency 'arel', '>= 7.0.0'
16
+
17
+ gem.add_development_dependency 'rake'
18
+ gem.add_development_dependency 'minitest'
19
+ end
@@ -0,0 +1,20 @@
1
+ module Arel
2
+ module ArrayPredications
3
+
4
+ def contains(*values)
5
+ values = values[0] if values.size == 1 && values[0].is_a?(Array)
6
+ Arel::Nodes::Contains.new(self, values)
7
+ end
8
+
9
+ def contained_by(*values)
10
+ values = values[0] if values.size == 1 && values[0].is_a?(Array)
11
+ Arel::Nodes::ContainedBy.new(self, values)
12
+ end
13
+
14
+ def overlaps(*values)
15
+ values = values[0] if values.size == 1 && values[0].is_a?(Array)
16
+ Arel::Nodes::Overlaps.new(self, values)
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ module Arel
2
+ module Attributes
3
+ class Key < Attribute
4
+ def able_to_type_cast?
5
+ false
6
+ end
7
+
8
+ def table_name
9
+ nil
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ require File.expand_path('../array_predications', __FILE__)
2
+ require File.expand_path('../nodes/overlaps', __FILE__)
3
+ require File.expand_path('../nodes/contains', __FILE__)
4
+ Arel::Attributes::Attribute.include(Arel::ArrayPredications)
5
+
6
+
7
+ require File.expand_path('../attributes/key', __FILE__)
8
+ require File.expand_path('../nodes/has_any_key', __FILE__)
9
+ require File.expand_path('../nodes/has_key', __FILE__)
10
+ require File.expand_path('../nodes/has_keys', __FILE__)
11
+ require File.expand_path('../json_predications', __FILE__)
12
+ Arel::Attributes::Attribute.include(Arel::JSONPredications)
13
+
14
+ if defined?(Arel::Visitors::PostgreSQL)
15
+ require File.expand_path('../visitors/postgresql_extensions', __FILE__)
16
+ end
@@ -0,0 +1,23 @@
1
+ module Arel
2
+ module JSONPredications
3
+
4
+ def key(key)
5
+ Arel::Attributes::Key.new(self, key)
6
+ end
7
+ alias :[] :key
8
+ alias :index :key
9
+
10
+ def has_key(key)
11
+ Arel::Nodes::HasKey.new(self, key)
12
+ end
13
+
14
+ def has_keys(*keys)
15
+ Arel::Nodes::HasKeys.new(self, keys)
16
+ end
17
+
18
+ def has_any_key(*keys)
19
+ Arel::Nodes::HasAnyKeys.new(self, keys)
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,6 @@
1
+ module Arel
2
+ module Nodes
3
+ class Contains < Binary
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ module Arel
2
+ module Nodes
3
+ class HasAnyKeys < Binary
4
+ # ?|
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Arel
2
+ module Nodes
3
+ class HasKey < Binary
4
+ # ?
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Arel
2
+ module Nodes
3
+ class HasKeys < Binary
4
+ # ?&
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ module Arel
2
+ module Nodes
3
+ class Overlaps < Binary
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,45 @@
1
+ module Arel
2
+ module Visitors
3
+ class PostgreSQL
4
+ private
5
+
6
+ def visit_Arel_Nodes_Contains o, collector
7
+ visit o.left, collector
8
+ collector << ' @> '
9
+ collector << quote(o.left.type_cast_for_database(o.right))
10
+ end
11
+
12
+ def visit_Arel_Nodes_ContainedBy o, collector
13
+ visit o.left, collector
14
+ collector << ' <@ '
15
+ collector << quote(o.left.type_cast_for_database(o.right))
16
+ end
17
+
18
+ def visit_Arel_Nodes_Overlaps o, collector
19
+ visit o.left, collector
20
+ collector << ' && '
21
+ collector << quote(o.left.type_cast_for_database(o.right))
22
+ end
23
+
24
+ def visit_Arel_Attributes_Key(o, collector, last_key = true)
25
+ if o.relation.is_a?(Arel::Attributes::Key)
26
+ visit_Arel_Attributes_Key(o.relation, collector, false)
27
+ if last_key
28
+ collector << o.name.to_s
29
+ collector << "}'"
30
+ else
31
+ collector << o.name.to_s
32
+ collector << "."
33
+ end
34
+ else
35
+ visit(o.relation, collector)
36
+ collector << "\#>>'{" << o.name.to_s
37
+ if !last_key
38
+ collector << "."
39
+ end
40
+ end
41
+ end
42
+
43
+ end
44
+ end
45
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: arel-extensions
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jon Bracy
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: arel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 7.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 7.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
56
+ email:
57
+ - jonbracy@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - LICENSE
63
+ - README.md
64
+ - arel-extensions.gemspec
65
+ - lib/arel/array_predications.rb
66
+ - lib/arel/attributes/key.rb
67
+ - lib/arel/extensions.rb
68
+ - lib/arel/json_predications.rb
69
+ - lib/arel/nodes/contains.rb
70
+ - lib/arel/nodes/has_any_key.rb
71
+ - lib/arel/nodes/has_key.rb
72
+ - lib/arel/nodes/has_keys.rb
73
+ - lib/arel/nodes/overlaps.rb
74
+ - lib/arel/visitors/postgresql_extensions.rb
75
+ homepage: https://github.com/malomalo/arel-extensions
76
+ licenses:
77
+ - MIT
78
+ metadata: {}
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 2.5.1
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: Adds support for missing SQL operators and functions to Arel
99
+ test_files: []