arel-helpers 1.1.0 → 1.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.
- checksums.yaml +4 -4
- data/History.txt +5 -1
- data/README.md +154 -0
- data/arel-helpers.gemspec +5 -1
- data/lib/arel-helpers/join_association.rb +27 -2
- data/lib/arel-helpers/version.rb +1 -1
- metadata +19 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7fcf6cccc8b45ef008f68a1da1ef9e8b468d474
|
4
|
+
data.tar.gz: dc76542898067426f8715ccb4b91b2b1d48f1787
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c95d188bfb80db50e13f8c98d7847bca7abc6c0b95502c22efd0eef043f1a5ec0b71b5c71410cfeaeabfb9533ae9ee02099d5fc55644f886fe95599ecd1631a
|
7
|
+
data.tar.gz: b74df2e5fd0224f8945219944888eea41be7e78532f4e277ae1e17eb3fc5ba792a35e0957e08b1b0dc87cd8a376d4b769c99fb0981c12475ca54efca404e084d
|
data/History.txt
CHANGED
data/README.md
CHANGED
@@ -0,0 +1,154 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
## arel-helpers [](http://travis-ci.org/camertron/arel-helpers)
|
4
|
+
|
5
|
+
Useful tools to help construct database queries with ActiveRecord and Arel.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
`gem install arel-helpers`
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
require 'arel-helpers'
|
15
|
+
```
|
16
|
+
|
17
|
+
### ArelTable Helper
|
18
|
+
|
19
|
+
Usually you'd reference database columns in Arel via the `#arel_table` method on your ActiveRecord models. For example:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
class Post < ActiveRecord::Base
|
23
|
+
...
|
24
|
+
end
|
25
|
+
|
26
|
+
Post.where(Post.arel_table[:id].eq(1))
|
27
|
+
```
|
28
|
+
|
29
|
+
Typing ".arel_table" over and over again can get pretty old and make constructing queries unnecessarily verbose. Try using the `ArelTable` helper to clean things up a bit:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
class Post < ActiveRecord::Base
|
33
|
+
include ArelHelpers::ArelTable
|
34
|
+
...
|
35
|
+
end
|
36
|
+
|
37
|
+
Post.where(Post[:id].eq(1))
|
38
|
+
```
|
39
|
+
|
40
|
+
### JoinAssociation Helper
|
41
|
+
|
42
|
+
Using pure Arel is probably one of the only ways to do an outer join with ActiveRecord. For example, let's say we have these two models:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
class Post < ActiveRecord::Base
|
46
|
+
has_many :comments
|
47
|
+
end
|
48
|
+
|
49
|
+
class Comment < ActiveRecord::Base
|
50
|
+
belongs_to :post
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
A join between posts and comments might look like this:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
Post.joins(:comments)
|
58
|
+
```
|
59
|
+
|
60
|
+
ActiveRecord introspects the association between posts and comments and automatically chooses the right columns to use in the join conditions.
|
61
|
+
|
62
|
+
Things start to get messy however if you wanted to do an outer join instead of the default inner join. Your query might look like this:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
Post
|
66
|
+
.joins(
|
67
|
+
Post.arel_table.join(Comments.arel_table, Arel::OuterJoin)
|
68
|
+
.on(Post[:id].eq(Coments[:post_id]))
|
69
|
+
.join_sources
|
70
|
+
)
|
71
|
+
```
|
72
|
+
|
73
|
+
Such verbose. Much code. Very bloat. Wow. We've lost all the awesome association introspection that ActiveRecord would otherwise have given us. Enter `ArelHelpers::JoinAssociation`:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
include ArelHelpers::JoinAssociation
|
77
|
+
Post.joins(join_association(Post, :comments, Arel::OuterJoin))
|
78
|
+
```
|
79
|
+
|
80
|
+
Easy peasy.
|
81
|
+
|
82
|
+
`JoinAssociation` also allows you to customize the join conditions via a block:
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
Post.joins(
|
86
|
+
join_association(Post, :comments, Arel::OuterJoin) do |assoc_name, join_conditions|
|
87
|
+
join_conditions.and(Post[:author_id].eq(4))
|
88
|
+
end
|
89
|
+
)
|
90
|
+
```
|
91
|
+
|
92
|
+
### Query Builders
|
93
|
+
|
94
|
+
ArelHelpers also contains a very simple class that's designed to provide a light framework for constructing queries using the builder pattern. For example, let's write a class that encapsulates generating queries for blog posts:
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
class PostQueryBuilder < ArelHelpers::QueryBuilder
|
98
|
+
def initialize(query = nil)
|
99
|
+
# whatever you want your initial query to be
|
100
|
+
super(query || post.unscoped)
|
101
|
+
end
|
102
|
+
|
103
|
+
def with_title_matching(title)
|
104
|
+
reflect(
|
105
|
+
query.where(post[:title].matches("%#{title}%"))
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
109
|
+
def with_comments_by(usernames)
|
110
|
+
reflect(
|
111
|
+
query
|
112
|
+
.joins(:comments => :author)
|
113
|
+
.where(Author[:username].in(usernames))
|
114
|
+
)
|
115
|
+
end
|
116
|
+
|
117
|
+
def since_yesterday
|
118
|
+
reflect(
|
119
|
+
query.where(post[:created_at].gteq(Date.yesterday))
|
120
|
+
)
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
def author
|
126
|
+
Author
|
127
|
+
end
|
128
|
+
|
129
|
+
def post
|
130
|
+
Post
|
131
|
+
end
|
132
|
+
end
|
133
|
+
```
|
134
|
+
|
135
|
+
The `#reflect` method creates a new instance of `PostQueryBuilder`, copies the query into it and returns the new query builder instance. This allows you to chain your method calls:
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
PostQueryBuilder.new
|
139
|
+
.with_comments_by(['camertron', 'catwithtail'])
|
140
|
+
.with_title_matching("arel rocks")
|
141
|
+
.since_yesterday
|
142
|
+
```
|
143
|
+
|
144
|
+
## Requirements
|
145
|
+
|
146
|
+
No external requirements. Depends on SQLite for testing purposes.
|
147
|
+
|
148
|
+
## Running Tests
|
149
|
+
|
150
|
+
`bundle exec rspec`
|
151
|
+
|
152
|
+
## Authors
|
153
|
+
|
154
|
+
* Cameron C. Dutro: http://github.com/camertron
|
data/arel-helpers.gemspec
CHANGED
@@ -13,7 +13,11 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.platform = Gem::Platform::RUBY
|
14
14
|
s.has_rdoc = true
|
15
15
|
|
16
|
-
|
16
|
+
if ENV["AR"]
|
17
|
+
s.add_dependency 'activerecord', ENV["AR"]
|
18
|
+
else
|
19
|
+
s.add_dependency 'activerecord', '>= 3.1.0', '<= 4.1.0'
|
20
|
+
end
|
17
21
|
|
18
22
|
s.require_path = 'lib'
|
19
23
|
s.files = Dir["{lib,spec}/**/*", "Gemfile", "History.txt", "README.md", "Rakefile", "arel-helpers.gemspec"]
|
@@ -6,9 +6,19 @@ module ArelHelpers
|
|
6
6
|
# activerecord uses JoinDependency to automagically generate inner join statements for
|
7
7
|
# any type of association (belongs_to, has_many, and has_and_belongs_to_many).
|
8
8
|
# For example, for HABTM associations, two join statements are required.
|
9
|
-
# This method encapsulates that functionality and
|
9
|
+
# This method encapsulates that functionality and yields an intermediate object for chaining.
|
10
10
|
# It also allows you to use an outer join instead of the default inner via the join_type arg.
|
11
|
-
def join_association(table, association, join_type = Arel::InnerJoin)
|
11
|
+
def join_association(table, association, join_type = Arel::InnerJoin, &block)
|
12
|
+
if ActiveRecord::VERSION::STRING >= '4.1.0'
|
13
|
+
join_association_4_1(table, association, join_type, &block)
|
14
|
+
else
|
15
|
+
join_association_3_1(table, association, join_type, &block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def join_association_3_1(table, association, join_type)
|
12
22
|
associations = association.is_a?(Array) ? association : [association]
|
13
23
|
join_dependency = ActiveRecord::Associations::JoinDependency.new(table, associations, [])
|
14
24
|
manager = Arel::SelectManager.new(table)
|
@@ -29,5 +39,20 @@ module ArelHelpers
|
|
29
39
|
end
|
30
40
|
end
|
31
41
|
|
42
|
+
def join_association_4_1(table, association, join_type)
|
43
|
+
associations = association.is_a?(Array) ? association : [association]
|
44
|
+
join_dependency = ActiveRecord::Associations::JoinDependency.new(table, associations, [])
|
45
|
+
|
46
|
+
join_dependency.join_constraints([]).map do |constraint|
|
47
|
+
right = if block_given?
|
48
|
+
yield constraint.left.name.to_sym, constraint.right
|
49
|
+
else
|
50
|
+
constraint.right
|
51
|
+
end
|
52
|
+
|
53
|
+
join_type.new(constraint.left, right)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
32
57
|
end
|
33
58
|
end
|
data/lib/arel-helpers/version.rb
CHANGED
metadata
CHANGED
@@ -1,29 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arel-helpers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cameron Dutro
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 3.1.0
|
20
|
+
- - <=
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 4.1.0
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
|
-
- -
|
27
|
+
- - '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.1.0
|
30
|
+
- - <=
|
25
31
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
32
|
+
version: 4.1.0
|
27
33
|
description: Useful tools to help construct database queries with ActiveRecord and
|
28
34
|
Arel.
|
29
35
|
email:
|
@@ -32,20 +38,20 @@ executables: []
|
|
32
38
|
extensions: []
|
33
39
|
extra_rdoc_files: []
|
34
40
|
files:
|
35
|
-
- Gemfile
|
36
|
-
- History.txt
|
37
|
-
- README.md
|
38
|
-
- Rakefile
|
39
|
-
- arel-helpers.gemspec
|
40
|
-
- lib/arel-helpers.rb
|
41
41
|
- lib/arel-helpers/arel_table.rb
|
42
42
|
- lib/arel-helpers/join_association.rb
|
43
43
|
- lib/arel-helpers/query_builder.rb
|
44
44
|
- lib/arel-helpers/version.rb
|
45
|
+
- lib/arel-helpers.rb
|
45
46
|
- spec/arel_table_spec.rb
|
46
47
|
- spec/join_association_spec.rb
|
47
48
|
- spec/query_builder_spec.rb
|
48
49
|
- spec/spec_helper.rb
|
50
|
+
- Gemfile
|
51
|
+
- History.txt
|
52
|
+
- README.md
|
53
|
+
- Rakefile
|
54
|
+
- arel-helpers.gemspec
|
49
55
|
homepage: http://github.com/camertron
|
50
56
|
licenses: []
|
51
57
|
metadata: {}
|
@@ -65,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
65
71
|
version: '0'
|
66
72
|
requirements: []
|
67
73
|
rubyforge_project:
|
68
|
-
rubygems_version: 2.
|
74
|
+
rubygems_version: 2.0.3
|
69
75
|
signing_key:
|
70
76
|
specification_version: 4
|
71
77
|
summary: Useful tools to help construct database queries with ActiveRecord and Arel.
|