Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 95 lines (53 sloc) 3.659 kB
b9e83c9 @tenderlove adding a manifest, converting to Hoe, generating gemspec
tenderlove authored
1 # ARel
2
3 * http://github.com/rails/arel
4
5 ## DESCRIPTION
d3c7c37 added primitive update functionality
Nick Kallen authored
6
3eae3b0 renamed select operation to where
Nick Kallen authored
7 Arel is a Relational Algebra for Ruby. It 1) simplifies the generation complex of SQL queries and it 2) adapts to various RDBMS systems. It is intended to be a framework framework; that is, you can build your own ORM with it, focusing on innovative object and collection modeling as opposed to database compatibility and query generation.
d3c7c37 added primitive update functionality
Nick Kallen authored
8
b9e83c9 @tenderlove adding a manifest, converting to Hoe, generating gemspec
tenderlove authored
9 ## Status
3eae3b0 renamed select operation to where
Nick Kallen authored
10
aca9b5b @tenderlove removing irrelevant docs, updating relevant docs
tenderlove authored
11 For the moment, Arel uses ActiveRecord's connection adapters to connect to the various engines, connection pooling, perform quoting, and do type conversion.
3eae3b0 renamed select operation to where
Nick Kallen authored
12
b9e83c9 @tenderlove adding a manifest, converting to Hoe, generating gemspec
tenderlove authored
13 ## A Gentle Introduction
d3c7c37 added primitive update functionality
Nick Kallen authored
14
15 Generating a query with ARel is simple. For example, in order to produce
16
17 SELECT * FROM users
755a7ce @miloops REAME updated: remove whitespaces, fix invalid join in query output.
miloops authored
18
d3c7c37 added primitive update functionality
Nick Kallen authored
19 you construct a table relation and convert it to sql:
20
aca9b5b @tenderlove removing irrelevant docs, updating relevant docs
tenderlove authored
21 users = Arel::Table.new(:users)
22 users.project(Arel.sql('*'))
3eae3b0 renamed select operation to where
Nick Kallen authored
23 users.to_sql
755a7ce @miloops REAME updated: remove whitespaces, fix invalid join in query output.
miloops authored
24
b9e83c9 @tenderlove adding a manifest, converting to Hoe, generating gemspec
tenderlove authored
25 ### More Sophisticated Queries
3eae3b0 renamed select operation to where
Nick Kallen authored
26
27 Here is a whirlwind tour through the most common relational operators. These will probably cover 80% of all interaction with the database.
d3c7c37 added primitive update functionality
Nick Kallen authored
28
3eae3b0 renamed select operation to where
Nick Kallen authored
29 First is the 'restriction' operator, `where`:
d3c7c37 added primitive update functionality
Nick Kallen authored
30
3eae3b0 renamed select operation to where
Nick Kallen authored
31 users.where(users[:name].eq('amy'))
32 # => SELECT * FROM users WHERE users.name = 'amy'
33
34 What would, in SQL, be part of the `SELECT` clause is called in Arel a `projection`:
35
36 users.project(users[:id]) # => SELECT users.id FROM users
755a7ce @miloops REAME updated: remove whitespaces, fix invalid join in query output.
miloops authored
37
3eae3b0 renamed select operation to where
Nick Kallen authored
38 Joins resemble SQL strongly:
39
40 users.join(photos).on(users[:id].eq(photos[:user_id]))
41 # => SELECT * FROM users INNER JOIN photos ON users.id = photos.user_id
42
43 What are called `LIMIT` and `OFFSET` in SQL are called `take` and `skip` in Arel:
44
45 users.take(5) # => SELECT * FROM users LIMIT 5
46 users.skip(4) # => SELECT * FROM users OFFSET 4
755a7ce @miloops REAME updated: remove whitespaces, fix invalid join in query output.
miloops authored
47
3eae3b0 renamed select operation to where
Nick Kallen authored
48 `GROUP BY` is called `group`:
49
50 users.group(users[:name]) # => SELECT * FROM users GROUP BY name
51
cf1db3c @peashutop tiny correction to readme
peashutop authored
52 The best property of the Relational Algebra is its "composability", or closure under all operations. For example, to restrict AND project, just "chain" the method invocations:
3eae3b0 renamed select operation to where
Nick Kallen authored
53
54 users \
55 .where(users[:name].eq('amy')) \
56 .project(users[:id]) \
57 # => SELECT users.id FROM users WHERE users.name = 'amy'
58
59 All operators are chainable in this way, and they are chainable any number of times, in any order.
d3c7c37 added primitive update functionality
Nick Kallen authored
60
3eae3b0 renamed select operation to where
Nick Kallen authored
61 users.where(users[:name].eq('bob')).where(users[:age].lt(25))
755a7ce @miloops REAME updated: remove whitespaces, fix invalid join in query output.
miloops authored
62
3eae3b0 renamed select operation to where
Nick Kallen authored
63 Of course, many of the operators take multiple arguments, so the last example can be written more tersely:
64
65 users.where(users[:name].eq('bob'), users[:age].lt(25))
d3c7c37 added primitive update functionality
Nick Kallen authored
66
aca9b5b @tenderlove removing irrelevant docs, updating relevant docs
tenderlove authored
67 The `OR` operator works like this:
3eae3b0 renamed select operation to where
Nick Kallen authored
68
69 users.where(users[:name].eq('bob').or(users[:age].lt(25)))
755a7ce @miloops REAME updated: remove whitespaces, fix invalid join in query output.
miloops authored
70
aca9b5b @tenderlove removing irrelevant docs, updating relevant docs
tenderlove authored
71 The `AND` operator behaves similarly.
41f80e4 limits and offsets need to be externalized too. first draft
Nick Kallen authored
72
b9e83c9 @tenderlove adding a manifest, converting to Hoe, generating gemspec
tenderlove authored
73 ### The Crazy Features
d3c7c37 added primitive update functionality
Nick Kallen authored
74
3eae3b0 renamed select operation to where
Nick Kallen authored
75 The examples above are fairly simple and other libraries match or come close to matching the expressiveness of Arel (e.g., `Sequel` in Ruby).
d3c7c37 added primitive update functionality
Nick Kallen authored
76
b9e83c9 @tenderlove adding a manifest, converting to Hoe, generating gemspec
tenderlove authored
77 #### Complex Joins
d3c7c37 added primitive update functionality
Nick Kallen authored
78
3eae3b0 renamed select operation to where
Nick Kallen authored
79 Where Arel really shines in its ability to handle complex joins and aggregations. As a first example, let's consider an "adjacency list", a tree represented in a table. Suppose we have a table `comments`, representing a threaded discussion:
80
aca9b5b @tenderlove removing irrelevant docs, updating relevant docs
tenderlove authored
81 comments = Arel::Table.new(:comments)
755a7ce @miloops REAME updated: remove whitespaces, fix invalid join in query output.
miloops authored
82
3eae3b0 renamed select operation to where
Nick Kallen authored
83 And this table has the following attributes:
ecd072d renamed attribute to operand per josh's suggestion
Nick Kallen authored
84
aca9b5b @tenderlove removing irrelevant docs, updating relevant docs
tenderlove authored
85 comments.columns # => [comments[:id], comments[:body], comments[:parent_id]]
d3c7c37 added primitive update functionality
Nick Kallen authored
86
3eae3b0 renamed select operation to where
Nick Kallen authored
87 The `parent_id` column is a foreign key from the `comments` table to itself. Now, joining a table to itself requires aliasing in SQL. In fact, you may alias in Arel as well:
d3c7c37 added primitive update functionality
Nick Kallen authored
88
3eae3b0 renamed select operation to where
Nick Kallen authored
89 replies = comments.alias
90 comments_with_replies = \
91 comments.join(replies).on(replies[:parent_id].eq(comments[:id]))
92 # => SELECT * FROM comments INNER JOIN comments AS comments_2 WHERE comments_2.parent_id = comments.id
755a7ce @miloops REAME updated: remove whitespaces, fix invalid join in query output.
miloops authored
93
3eae3b0 renamed select operation to where
Nick Kallen authored
94 This will return the first comment's reply's body.
Something went wrong with that request. Please try again.