3. Arel
Alg`bre relationnelle ou ActiveRelation
e
Trˆn Jean-Fran¸ois
a c AREL
4. Qu’est-ce qu’Arel ?
Biblioth`que ´crite par Nick Kallen.
e e
Trˆn Jean-Fran¸ois
a c AREL
5. Qu’est-ce qu’Arel ?
Biblioth`que ´crite par Nick Kallen.
e e
Nick Kallen : auteur de has finder, int´gr´ dans Rails sous le
e e
nom de Name Scoped (sera dispo dans Rails 2.1)
Trˆn Jean-Fran¸ois
a c AREL
6. Qu’est-ce qu’Arel ?
Biblioth`que ´crite par Nick Kallen.
e e
Nick Kallen : auteur de has finder, int´gr´ dans Rails sous le
e e
nom de Name Scoped (sera dispo dans Rails 2.1)
Arel se veut le ”Rack des ORM”.
Trˆn Jean-Fran¸ois
a c AREL
7. Alg`bre relationnelle
e
Alg`bre relationnelle : th´orie ` la base des Bases de donn´es
e e a e
relationnelles.
pour les d´tails, demandez ` Codd de vous expliquer, pour
e a
moi mes cours de BD sont loins !
En gros, on a des relations, on peut y op´rer des op´rations
e e
comme la S´lection, la Projection, le Produit Cart´sien, le
e e
Rename, l’Union, la Diff´rence, la Division, les Jointures...
e
Trˆn Jean-Fran¸ois
a c AREL
8. Installation
Sur GitHub : http://github.com/nkallen/arel/tree/master
git clone git://github.com/nkallen/arel.git
Trˆn Jean-Fran¸ois
a c AREL
9. ORM Builder
Un ORM Builder, c’est-`-dire qu’on peut construire son
a
propre ORM en se basant sur Arel.
Trˆn Jean-Fran¸ois
a c AREL
10. ORM Builder
Un ORM Builder, c’est-`-dire qu’on peut construire son
a
propre ORM en se basant sur Arel.
Celui va g´n´rer le SQL en traversant une sorte d’AST.
e e
Trˆn Jean-Fran¸ois
a c AREL
11. ORM Builder
Un ORM Builder, c’est-`-dire qu’on peut construire son
a
propre ORM en se basant sur Arel.
Celui va g´n´rer le SQL en traversant une sorte d’AST.
e e
Plus puissant qu’un QueryBuilder car Arel travaille sur des
relations et ne fait pas de concat´nation de chaˆ
e ınes
(seulement en dernier lieu).
Trˆn Jean-Fran¸ois
a c AREL
12. ORM Builder
Un ORM Builder, c’est-`-dire qu’on peut construire son
a
propre ORM en se basant sur Arel.
Celui va g´n´rer le SQL en traversant une sorte d’AST.
e e
Plus puissant qu’un QueryBuilder car Arel travaille sur des
relations et ne fait pas de concat´nation de chaˆ
e ınes
(seulement en dernier lieu).
Arel : se veut un middleware pour ORM.
Trˆn Jean-Fran¸ois
a c AREL
13. ORM Builder
Pas de gestion du mapping table/classe Ruby.
Trˆn Jean-Fran¸ois
a c AREL
14. ORM Builder
Pas de gestion du mapping table/classe Ruby.
Pas de gestion des associations au sens d’ActiveRecord.
Trˆn Jean-Fran¸ois
a c AREL
15. ORM Builder
Pas de gestion du mapping table/classe Ruby.
Pas de gestion des associations au sens d’ActiveRecord.
peut-ˆtre utilis´ pour refactoriser le code interne
e e
d’ActiveRecord (ou de DataMapper ou...).
Trˆn Jean-Fran¸ois
a c AREL
16. ORM Builder
Pas de gestion du mapping table/classe Ruby.
Pas de gestion des associations au sens d’ActiveRecord.
peut-ˆtre utilis´ pour refactoriser le code interne
e e
d’ActiveRecord (ou de DataMapper ou...).
On d´finit son API publique au dessus d’Arel comme on le
e
souhaite (Ambition ?).
Trˆn Jean-Fran¸ois
a c AREL
17. Closure under composition
C’est quoi la ”closure under composition” ?
J’en sais rien, et vous ?
closure : ”In mathematics, a set is said to be closed under
some operation if the operation on members of the set
produces a member of the set.” (Wikipedia ”closure
(mathematics”)”)
Trˆn Jean-Fran¸ois
a c AREL
18. SQL g´n´r´
e ee
#to_sql
Les exemples suivants sont faits en passant #to_sql Ici avec
ActiveRecord et l’adaptateur SQLite pour le quoting SQL.
Trˆn Jean-Fran¸ois
a c AREL
19. D´finition des tables des exemples
e
create_table :users, :force => true do |t|
t.string :name
end
create_table :articles do |t|
t.string :title
t.integer :comments_count
t.references :user
end
Trˆn Jean-Fran¸ois
a c AREL
20. CRUD
Insertion
Delete
Update
Trˆn Jean-Fran¸ois
a c AREL
21. CRUD avec ActiveRelation::Table
users = ActiveRelation::Table.new(:users)
users.select(...)
users.insert(users[:name] => ’Iron Man’)
users.update(...)
users.delete(...)
Trˆn Jean-Fran¸ois
a c AREL
22. CRUD : Delete
ActiveRelation::Deletion.new(articles.select(articles[:id].
DELETE
FROM articles
WHERE articles.quot;idquot; = 1
Update
Trˆn Jean-Fran¸ois
a c AREL
23. CRUD : Insertion
ActiveRelation::Insertion.new(
articles, articles[:title] => ’chti’).to_sql
INSERT
INTO articles
(articles.quot;titlequot;)
VALUES (’coucou’)
Trˆn Jean-Fran¸ois
a c AREL
24. Attributs
ActiveRelation::Attribute.new(articles, :id)
mˆme chose que :
e
articles[:id]
Trˆn Jean-Fran¸ois
a c AREL
25. Pr´dicats
e
Avec les Attributs, on peut composer des pr´dicats (´galit´,
e e e
inclusion, op´rateurs binaires)
e
Trˆn Jean-Fran¸ois
a c AREL
26. Pr´dicats : Equality
e
articles[:id].eq(’foo’).class
# => ActiveRelation::Equality
Trˆn Jean-Fran¸ois
a c AREL
27. Pr´dicats : Equality
e
ActiveRelation::Equality.new(
articles[:user_id],
users[:id]
)
# SQL => quot;articles.quot;user_idquot; = users.quot;idquot;quot;
identique ` :
a
articles[:user_id].eq(users[:id])
# SQL => quot;articles.quot;user_idquot; = users.quot;idquot;quot;
Trˆn Jean-Fran¸ois
a c AREL
28. Pr´dicats : Equality (suite)
e
articles[:id].eq(’foo’)
# SQL => quot;articles.quot;idquot; = 0quot;
articles[:title].eq(’foo’)
# SQL => quot;articles.quot;titlequot; = ’foo’quot;
articles[:title].eq(nil)
# SQL => quot;articles.quot;titlequot; IS NULLquot;
articles[:title].eq(true)
# SQL => quot;articles.quot;titlequot; = ’t’quot;
Trˆn Jean-Fran¸ois
a c AREL
32. Inclusion
articles[:id].in(1..4)
# SQL => quot;articles.quot;idquot; BETWEEN 1 AND 4quot;
articles[:id].in([1, 3, 5])
# SQL => quot;articles.quot;idquot; IN (1, 3, 5)quot;
Trˆn Jean-Fran¸ois
a c AREL
33. Inclusion (suite)
users
# SQL => quot;SELECT users.quot;idquot;, users.quot;namequot; FROM usersquot;
articles[:id].in(users)
# SQL => quot;articles.quot;idquot; IN (SELECT
users.quot;idquot;, users.quot;namequot; FROM users)quot;
articles[:user_id].in(
users.select(users[:id].in(1..5))
)
# => quot;articles.quot;user_idquot; IN
(SELECT users.quot;idquot;, users.quot;namequot;
FROM users WHERE users.quot;idquot; BETWEEN 1 AND 5)quot;
Trˆn Jean-Fran¸ois
a c AREL
34. Select
users.select(users[:id].in(1..5))
Trˆn Jean-Fran¸ois
a c AREL
35. Sub Select
articles.select(
articles[:user_id].in(
users.select(users[:id].in(1..5)).project(users[:id])
)
).to_sql
SELECT articles.quot;idquot;, articles.quot;titlequot;,
articles.quot;comments_countquot;,
articles.quot;user_idquot;
FROM articles
WHERE articles.quot;user_idquot; IN
(SELECT users.quot;idquot;
FROM users
WHERE users.quot;idquot; BETWEEN 1 AND 5)
Trˆn Jean-Fran¸ois
a c AREL
36. Exemple plus compliqu´
e
articles.select(
articles[:user_id].in(
users.select( users[:id].in(1..5) ).project(users[:id])
).project(articles[:id].maximum).to_sql
SELECT MAX(articles.quot;idquot;)
FROM articles
WHERE articles.quot;user_idquot; IN (
SELECT users.quot;idquot;
FROM users
WHERE users.quot;idquot; BETWEEN 1 AND 5)
Trˆn Jean-Fran¸ois
a c AREL
37. Order
articles.select.order(articles[:title]).to_sql
SELECT articles.quot;idquot;, articles.quot;titlequot;,
articles.quot;comments_countquot;, articles.quot;user_idquot;
FROM articles
WHERE
ORDER BY articles.quot;titlequot;
Trˆn Jean-Fran¸ois
a c AREL
38. Jointures
articles.join(users).on(articles[:user_id].eq(users[:id]))
SELECT articles.quot;idquot;, articles.quot;titlequot;,
articles.quot;comments_countquot;, articles.quot;user_idquot;,
users.quot;idquot;, users.quot;namequot;
FROM articles
INNER JOIN users ON articles.quot;user_idquot; = users.quot;idquot;
Trˆn Jean-Fran¸ois
a c AREL
39. Jointures
articles.
project(articles[:user_id]).
join(users).
on(articles[:user_id].eq(users[:id]))
SELECT articles.quot;user_idquot;, users.quot;idquot;, users.quot;namequot;
FROM articles
INNER JOIN users ON articles.quot;user_idquot; = users.quot;idquot;quot;
Trˆn Jean-Fran¸ois
a c AREL
40. Outer Join
articles.outer_join(users).
on(articles[:user_id].eq(users[:id]))
=>
SELECT articles.quot;idquot;, articles.quot;titlequot;,
articles.quot;comments_countquot;,
articles.quot;user_idquot;,
users.quot;idquot;, users.quot;namequot;
FROM articles
LEFT OUTER JOIN users ON articles.quot;user_idquot; = users.quot;idquot;
Trˆn Jean-Fran¸ois
a c AREL
41. Outer Join pour Has many, Belongs to
def user_has_many_articles(user_relation)
user_relation.
outer_join(@articles).
on(user_relation[:id].eq(@articles[:user_id]))
end
@user = ActiveRelation::Table(:users)
user_has_many_photos(@user).select ...
def article_belongs_to_camera(article_relation)
article_relation.
outer_join(@cameras).
on(photo_relation[foreign_key].equals(@cameras[primary_
)
end
Trˆn Jean-Fran¸ois
a c AREL
42. Renommage
ActiveRelation::Rename.new(
articles, articles[:id] => :koala
)
SELECT articles.quot;idquot; AS ’koala’, articles.quot;titlequot;,
articles.quot;comments_countquot;, articles.quot;user_idquot;
FROM articles
identique ` :
a
articles.rename(articles[:id], :koala)
Trˆn Jean-Fran¸ois
a c AREL
43. Agr´gation
e
articles.
aggregate(articles[:user_id], articles[:id].count).
group(articles[:user_id]).
rename(articles[:id].count, :cnt).
as(’articles_count’)
SELECT articles.quot;user_idquot;, COUNT(articles.quot;idquot;) AS quot;c
FROM articles
GROUP BY articles.quot;user_idquot;
Trˆn Jean-Fran¸ois
a c AREL
44. Expressions avec LIKE, expressions temporelles (?)
Prepared statements
pour ActiveRecord DataMapper API
Trˆn Jean-Fran¸ois
a c AREL