cheatsheets/arel.html

316 lines
10 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang='en' class='no-js '>
<head>
<meta charset='utf-8'>
<meta content='width=device-width, initial-scale=1.0' name='viewport'>
<link href='./assets/favicon.png' rel='shortcut icon'>
<meta content='/arel.html' name='app:pageurl'>
<title>Arel cheatsheet</title>
<meta content='Arel cheatsheet' property='og:title'>
<meta content='Arel cheatsheet' property='twitter:title'>
<meta content='article' property='og:type'>
<meta content='https://assets.devhints.io/previews/arel.jpg?t=20200622151222' property='og:image'>
<meta content='https://assets.devhints.io/previews/arel.jpg?t=20200622151222' property='twitter:image'>
<meta content='900' property='og:image:width'>
<meta content='471' property='og:image:height'>
<meta content="The one-page guide to Arel: usage, examples, links, snippets, and more." name="description">
<meta content="The one-page guide to Arel: usage, examples, links, snippets, and more." property="og:description">
<meta content="The one-page guide to Arel: usage, examples, links, snippets, and more." property="twitter:description">
<link rel="canonical" href="https://devhints.io/arel">
<meta name="og:url" content="https://devhints.io/arel">
<meta content='Devhints.io cheatsheets' property='og:site_name'>
<meta content='Rails' property='article:section'>
<script async src='https://www.googletagmanager.com/gtag/js?id=UA-106902774-1'></script>
<script>
window.dataLayer=window.dataLayer||[];
function gtag(){dataLayer.push(arguments)};
gtag('js',new Date());
gtag('config','UA-106902774-1');
</script>
<meta property='page:depth' content='1'>
<script>(function(H){H.className=H.className.replace(/\bno-js\b/,'js')})(document.documentElement)</script>
<script>(function(H){H.className=H.className.replace(/\bNoJs\b/,'WithJs')})(document.documentElement)</script>
<script>(function(d,s){if(window.Promise&&[].includes&&Object.assign&&window.Map)return;var js,sc=d.getElementsByTagName(s)[0];js=d.createElement(s);js.src='https://cdn.polyfill.io/v2/polyfill.min.js';sc.parentNode.insertBefore(js, sc);}(document,'script'))</script>
<!--[if lt IE 9]><script src='https://cdnjs.cloudflare.com/ajax/libs/nwmatcher/1.2.5/nwmatcher.min.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/json2/20140204/json2.js'></script><script src='https://cdn.rawgit.com/gisu/selectivizr/1.0.3/selectivizr.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.js'></script><![endif]-->
<style>html{opacity:0}</style>
<link rel="stylesheet" href="./assets/2015/style.css?t=20200622151222">
<link href="./assets/style.css?t=20200622151222" rel="stylesheet" />
<link href="./assets/print.css?t=20200622151222" rel="stylesheet" media="print" />
</head>
<body>
<div class='all'>
<div class='site-header'>
<div class='container'>
This is <a href="."><em>Devhints.io cheatsheets</em></a> &mdash; a collection of cheatsheets I've written.
</div>
</div>
<script type='application/ld+json'>
{
"@context": "http://schema.org",
"@type": "NewsArticle",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://google.com/article"
},
"headline": "Arel cheatsheet",
"image": [ "https://assets.devhints.io/previews/arel.jpg?t=20200622151222" ],
"description": "The one-page guide to Arel: usage, examples, links, snippets, and more."
}
</script>
<script type='application/ld+json'>
{
"@context": "http://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [{
"@type": "ListItem",
"position": 1,
"item": {
"@id": "https://devhints.io/#rails",
"name": "Rails"
}
},{
"@type": "ListItem",
"position": 2,
"item": {
"@id": "https://devhints.io/arel",
"name": "Arel"
}
}]
}
</script>
<div class='post-list -single -cheatsheet'>
<div class='post-item'>
<div class='post-headline -cheatsheet'>
<p class='prelude'><span></span></p>
<h1><span>Arel</span></h1>
<ul class="social-list ">
<li class="facebook link hint--bottom" data-hint="Share on Facebook"><a href="https://www.facebook.com/sharer/sharer.php?u=https://devhints.io/arel.html" target="share"><span class="text"></span></a></li>
<li class="twitter link hint--bottom" data-hint="Share on Twitter"><a href="https://twitter.com/intent/tweet?text=The%20ultimate%20cheatsheet%20for%20Arel.%20https://devhints.io/arel.html" target="share"><span class="text"></span></a></li>
</ul>
</div>
<div class='post-content -cheatsheet'>
<h3 id="tables">Tables</h3>
<pre><code class="language-rb">users = Arel::Table.new(:users)
users = User.arel_table # ActiveRecord model
</code></pre>
<h3 id="fields">Fields</h3>
<pre><code class="language-rb">users[:name]
users[:id]
</code></pre>
<h3 id="where-restriction"><code>where</code> (restriction)</h3>
<pre><code class="language-rb">users.where(users[:name].eq('amy'))
# SELECT * FROM users WHERE users.name = 'amy'
</code></pre>
<h3 id="select-projection"><code>select</code> (projection)</h3>
<pre><code class="language-rb">users.project(users[:id])
# SELECT users.id FROM users
</code></pre>
<h3 id="join"><code>join</code></h3>
<h4 id="basic-join">basic join</h4>
<p>In ActiveRecord (without Arel), if <code>:photos</code> is the name of the association, use <code>joins</code></p>
<pre><code class="language-rb">users.joins(:photos)
</code></pre>
<p>In Arel, if <code>photos</code> is defined as the Arel table,</p>
<pre><code class="language-rb">photos = Photo.arel_table
users.join(photos)
users.join(photos, Arel::Nodes::OuterJoin).on(users[:id].eq(photos[:user_id]))
</code></pre>
<h4 id="join-with-conditions">join with conditions</h4>
<pre><code class="language-rb">users.joins(:photos).merge(Photo.where(published: true))
</code></pre>
<p>If the simpler version doesnt help and you want to add more SQL statements to it:</p>
<pre><code class="language-rb">users.join(
users.join(photos, Arel::Nodes::OuterJoin)
.on(photos[:user_id].eq(users[:id]).and(photos[:published].eq(true)))
)
</code></pre>
<h4 id="advanced-join">advanced join</h4>
<p>multiple <code>joins</code> with the same table but different meanings and/or conditions</p>
<pre><code class="language-rb">creators = User.arel_table.alias('creators')
updaters = User.arel_table.alias('updaters')
photos = Photo.arel_table
photos_with_credits = photos
.join(photos.join(creators, Arel::Nodes::OuterJoin).on(photos[:created_by_id].eq(creators[:id])))
.join(photos.join(updaters, Arel::Nodes::OuterJoin).on(photos[:assigned_id].eq(updaters[:id])))
.project(photos[:name], photos[:created_at], creators[:name].as('creator'), updaters[:name].as('editor'))
photos_with_credits.to_sql
# =&gt; "SELECT `photos`.`name`, `photos`.`created_at`, `creators`.`name` AS creator, `updaters`.`name` AS editor FROM `photos` INNER JOIN (SELECT FROM `photos` LEFT OUTER JOIN `users` `creators` ON `photos`.`created_by_id` = `creators`.`id`) INNER JOIN (SELECT FROM `photos` LEFT OUTER JOIN `users` `updaters` ON `photos`.`updated_by_id` = `updaters`.`id`)"
# after the request is done, you can use the attributes you named
# it's as if every Photo record you got has "creator" and "editor" fields, containing creator name and editor name
photos_with_credits.map{|x|
"#{photo.name} - copyright #{photo.created_at.year} #{photo.creator}, edited by #{photo.editor}"
}.join('; ')
</code></pre>
<h3 id="limit--offset"><code>limit</code> / <code>offset</code></h3>
<pre><code class="language-rb">users.take(5) # =&gt; SELECT * FROM users LIMIT 5
users.skip(4) # =&gt; SELECT * FROM users OFFSET 4
</code></pre>
<h3 id="aggregates">Aggregates</h3>
<pre><code class="language-rb">users.project(users[:age].sum) # .average .minimum .maximum
users.project(users[:id].count)
users.project(users[:id].count.as('user_count'))
</code></pre>
<h3 id="order"><code>order</code></h3>
<pre><code class="language-rb">users.order(users[:name])
users.order(users[:name], users[:age].desc)
users.reorder(users[:age])
</code></pre>
<h3 id="with-activerecord">With ActiveRecord</h3>
<pre><code class="language-rb">User.arel_table
User.where(id: 1).arel
</code></pre>
<h3 id="clean-code-with-arel">Clean code with arel</h3>
<p>Most of the clever stuff should be in scopes, e.g. the code above could become:</p>
<pre><code class="language-rb">photos_with_credits = Photo.with_creator.with_editor
</code></pre>
<p>You can store requests in variables then add SQL segments:</p>
<pre><code class="language-rb">all_time = photos_with_credits.count
this_month = photos_with_credits.where(photos[:created_at].gteq(Date.today.beginning_of_month))
recent_photos = photos_with_credits.where(photos[:created_at].gteq(Date.today.beginning_of_month)).limit(5)
</code></pre>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="http://github.com/rails/arel">http://github.com/rails/arel</a></li>
</ul>
</div>
<ul class="social-list ">
<li class="facebook link hint--bottom" data-hint="Share on Facebook"><a href="https://www.facebook.com/sharer/sharer.php?u=https://devhints.io/arel.html" target="share"><span class="text"></span></a></li>
<li class="twitter link hint--bottom" data-hint="Share on Twitter"><a href="https://twitter.com/intent/tweet?text=The%20ultimate%20cheatsheet%20for%20Arel.%20https://devhints.io/arel.html" target="share"><span class="text"></span></a></li>
</ul>
</div>
</div>
<div class="about-the-site">
<div class="container">
<p class='blurb'>
<strong><a href=".">Devhints.io cheatsheets</a></strong> is a collection of cheatsheets I've written over the years.
Suggestions and corrections? <a href='https://github.com/rstacruz/cheatsheets/issues/907'>Send them in</a>.
<i class='fleuron'></i>
I'm <a href="http://ricostacruz.com">Rico Sta. Cruz</a>.
Check out my <a href="http://ricostacruz.com/til">Today I learned blog</a> for more.
</p>
<p class='back'>
<a class='big-button -back -slim' href='.#toc'></a>
</p>
<p>
</p>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.5/highlight.min.js"></script>
<script src="https://cdn.rawgit.com/rstacruz/unorphan/v1.0.1/index.js"></script>
<script>hljs.initHighlightingOnLoad()</script>
<script>unorphan('h1, h2, h3, p, li, .unorphan')</script>
</body>
</html>