<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/">
	<channel>
		<title>Things I Wish ActiveRecord Had After Using Ecto | Infinum</title>
		<atom:link href="https://infinum.com/blog/things-i-wish-active-record-had-after-using-ecto/feed/" rel="self" type="application/rss+xml" />
		<link>https://infinum.com/blog/things-i-wish-active-record-had-after-using-ecto/</link>
		<description>Building digital products</description>
		<lastBuildDate>Fri, 03 Apr 2026 12:58:20 +0000</lastBuildDate>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>

					<item>
				<image>
					<url>8011https://infinum.com/uploads/2018/01/things-i-wish-active-record-had-after-using-ecto-0.webp</url>
				</image>
				<title>Things I Wish ActiveRecord Had After Using Ecto</title>
				<link>https://infinum.com/blog/things-i-wish-active-record-had-after-using-ecto/</link>
				<pubDate>Tue, 16 Jan 2018 10:10:00 +0000</pubDate>
				<dc:creator>Vladimir Rosancic</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/things-i-wish-active-record-had-after-using-ecto/</guid>
				<description>
					<![CDATA[<p>Moving from one programming language to another is not hard as long as you have good knowledge of the concepts they share. </p>
<p>The post <a href="https://infinum.com/blog/things-i-wish-active-record-had-after-using-ecto/">Things I Wish ActiveRecord Had After Using Ecto</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-222"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-92">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-95"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-93">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-94'
	>
	A few years ago, I wrote an article about <a href="https://infinum.com/blog/i-moved-from-django-to-rails-and-nothing-terrible-happened/">moving from Django to Rails</a>. As I said there, I don’t find it too hard moving from one programming language to another, as long as you have good knowledge on concepts they all share. Each language, of course, brings something on its own.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-98"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-96">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-97'
	>
	Last year, I decided to try something new. As a Ruby developer, Elixir proved to be a logical choice, and I have to admit, I am not disappointed. I fell in love with it at first sight, and I enjoy working with Elixir/Phoenix now.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-101"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-99"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-100">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2018/01/things-i-wish-active-record-had-after-using-ecto-1-1400x840.webp				media='(max-width: 699px)'
				type=image/webp								height="840"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2018/01/things-i-wish-active-record-had-after-using-ecto-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="846"
															width="1410"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-104"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-102">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-103'
	>
	One thing that I especially like is Ecto, a database wrapper, and a domain-specific language for writing queries in Elixir. Although it’s not entirely the same thing as Rails’ Active Record (Ecto is not ORM), they serve the same purpose.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-107"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-105">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-106'
	>
	In this article, I’ll write about few things I like about Ecto that aren’t available in Active Record. It’s not meant to be a “Phoenix is better than Rails” rant as both frameworks provide really great things and we can all learn from each of them.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-110"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-108">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-109'
	>
	Changesets</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-113"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-111">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-112'
	>
	When you want to insert or update the data in your database with Ecto, you should use changesets. As the official documentation says, they allow you to filter, cast and validate changes before you apply them to the data. When I first saw the concept of changesets, I thought of a form object pattern that I often use in Rails. Changesets, like form objects, allow you to have different ‘forms’ for various use cases. Think of a registration form vs. update profile form. Both operate on the same model (<code>User</code>), but they have different validations.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-115"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-elixir github-light" data-language="elixir" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">def</span><span class="token"> </span><span class="token" style="color: #6f42c1;">registration_changeset</span><span class="token">(</span><span class="token">struct</span><span class="token">,</span><span class="token"> params</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">do</span><span class="token">
</span></span><span class="line"><span class="token">  struct
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">|&gt;</span><span class="token"> </span><span class="token" style="color: #6f42c1;">cast</span><span class="token">(</span><span class="token">params</span><span class="token">,</span><span class="token"> </span><span class="token">[</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">email</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">password</span><span class="token">]</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">|&gt;</span><span class="token"> </span><span class="token" style="color: #6f42c1;">validate_required</span><span class="token">(</span><span class="token">[</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">email</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">password</span><span class="token">]</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">|&gt;</span><span class="token"> </span><span class="token" style="color: #6f42c1;">unique_constraint</span><span class="token">(</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">email</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">|&gt;</span><span class="token"> </span><span class="token" style="color: #6f42c1;">put_password_hash</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">def</span><span class="token"> </span><span class="token" style="color: #6f42c1;">update_profile_changeset</span><span class="token">(</span><span class="token">struct</span><span class="token">,</span><span class="token"> params</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">do</span><span class="token">
</span></span><span class="line"><span class="token">  struct
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">|&gt;</span><span class="token"> </span><span class="token" style="color: #6f42c1;">cast</span><span class="token">(</span><span class="token">params</span><span class="token">,</span><span class="token"> </span><span class="token">[</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">first_name</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">last_name</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">age</span><span class="token">]</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">|&gt;</span><span class="token"> </span><span class="token" style="color: #6f42c1;">validate_required</span><span class="token">(</span><span class="token">[</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">first_name</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">last_name</span><span class="token">]</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-118"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-116">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-117'
	>
	To accomplish this in Active Record, you have to use conditional validations (if/unless) which is ugly and <strong>hard to reuse</strong>, or you would have to use external gems like <a href="https://github.com/makandra/active_type">Active Type</a> or <a href="https://github.com/trailblazer/reform">Reform</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-121"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-119">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-120'
	>
	Ecto provides it out-of-the-box. The whole data manipulation philosophy in Ecto relies on the concept of small, <strong>reusable and modular</strong> changesets making it a powerful tool.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-124"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-122">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-123'
	>
	Validations use database constraints</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-127"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-125">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-126'
	>
	Ecto can transform database constraints, like unique indexes or foreign key checks, into errors. This allows for a consistent database while giving users proper feedback and friendly error messages.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-130"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-128">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-129'
	>
	Let’s say we have a unique index on <code>email</code> field in <code>users</code> table.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-132"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-elixir github-light" data-language="elixir" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">create </span><span class="token" style="color: #6f42c1;">unique_index</span><span class="token">(</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">users</span><span class="token">,</span><span class="token"> </span><span class="token">[</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">email</span><span class="token">]</span><span class="token">)</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-135"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-133">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-134'
	>
	If we try to insert a user with an email that already exists, an exception will be raised with a message like this:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-137"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-php github-light" data-language="php" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">**</span><span class="token"> </span><span class="token">(</span><span class="token" style="color: #005cc5;">Ecto</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #005cc5;">ConstraintError</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #005cc5;">constraint</span><span class="token"> </span><span class="token" style="color: #005cc5;">error</span><span class="token"> </span><span class="token" style="color: #005cc5;">when</span><span class="token"> </span><span class="token" style="color: #005cc5;">attempting</span><span class="token"> </span><span class="token" style="color: #005cc5;">to</span><span class="token"> 
</span></span><span class="line"><span class="token" style="color: #005cc5;">insert</span><span class="token"> </span><span class="token" style="color: #005cc5;">struct</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">*</span><span class="token"> </span><span class="token" style="color: #005cc5;">unique</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">users_email_index</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">If</span><span class="token"> </span><span class="token" style="color: #005cc5;">you</span><span class="token"> </span><span class="token" style="color: #005cc5;">would</span><span class="token"> </span><span class="token" style="color: #005cc5;">like</span><span class="token"> </span><span class="token" style="color: #005cc5;">to</span><span class="token"> </span><span class="token" style="color: #005cc5;">convert</span><span class="token"> </span><span class="token" style="color: #005cc5;">this</span><span class="token"> </span><span class="token" style="color: #005cc5;">constraint</span><span class="token"> </span><span class="token" style="color: #005cc5;">into</span><span class="token"> </span><span class="token" style="color: #005cc5;">an</span><span class="token"> </span><span class="token" style="color: #005cc5;">error</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">please</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">call</span><span class="token"> </span><span class="token" style="color: #005cc5;">unique_constraint</span><span class="token" style="color: #d73a49;">/</span><span class="token" style="color: #005cc5;">3</span><span class="token"> </span><span class="token" style="color: #005cc5;">in</span><span class="token"> </span><span class="token" style="color: #005cc5;">your</span><span class="token"> </span><span class="token" style="color: #005cc5;">changeset</span><span class="token"> </span><span class="token" style="color: #d73a49;">and</span><span class="token"> </span><span class="token" style="color: #005cc5;">define</span><span class="token"> </span><span class="token" style="color: #005cc5;">the</span><span class="token"> </span><span class="token" style="color: #005cc5;">proper</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">constraint</span><span class="token"> </span><span class="token" style="color: #005cc5;">name</span><span class="token" style="color: #d73a49;">.</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-140"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-138">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-139'
	>
	Let’s call the <code>unique_constraint/3</code> function in our changeset.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-142"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-elixir github-light" data-language="elixir" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">def</span><span class="token"> </span><span class="token" style="color: #6f42c1;">changeset</span><span class="token">(</span><span class="token">struct</span><span class="token">,</span><span class="token"> params</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">do</span><span class="token">
</span></span><span class="line"><span class="token">  struct
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">|&gt;</span><span class="token"> </span><span class="token" style="color: #6f42c1;">cast</span><span class="token">(</span><span class="token">params</span><span class="token">,</span><span class="token"> </span><span class="token">[</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">email</span><span class="token">]</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">|&gt;</span><span class="token"> </span><span class="token" style="color: #6f42c1;">unique_constraint</span><span class="token">(</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">email</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-145"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-143">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-144'
	>
	Now, if we try to do the same thing as above, Ecto will <strong>catch</strong> the exception and <strong>transform</strong> it into a readable changeset error:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-147"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-elixir github-light" data-language="elixir" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">changeset</span><span class="token">.</span><span class="token">errors
</span></span><span class="line"><span class="token">[</span><span class="token" style="color: #005cc5;">email</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token">{</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">has already been taken</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">,</span><span class="token"> </span><span class="token">[</span><span class="token">]</span><span class="token">}</span><span class="token">]</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-150"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-148">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-149'
	>
	On the other hand, Active Record does not catch errors raised by the database, but rather checks the database state right before performing a validation. This could lead to <a href="http://nathanmlong.com/2017/02/guaranteed-consistency-the-case-for-database-constraints/">unwanted situations</a> in case of high traffic and a lot of parallel requests.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-153"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-151">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-152'
	>
	Preloading</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-156"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-154">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-155'
	>
	We all know that N+1 queries are a bad thing. In most cases, you want to lower the number of database queries in a single request. Both Active Record and Ecto provide a way to specify a list of associations that need to be fetched along with the main query.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-159"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-157">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-158'
	>
	The difference is that Ecto will enforce preloading if you want to use the associated resource (it will raise errors in case you don’t), while Active Record will load that resource at the time you use it. As I tend to forget to preload associations and because I don’t want bad things in my apps, I like Ecto’s enforcement.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-161"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-elixir github-light" data-language="elixir" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">user </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #6f42c1;">MyApp</span><span class="token">.</span><span class="token" style="color: #6f42c1;">Repo</span><span class="token">.</span><span class="token" style="color: #6f42c1;">get</span><span class="token">(</span><span class="token" style="color: #6f42c1;">MyApp</span><span class="token">.</span><span class="token" style="color: #6f42c1;">User</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">1</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">user</span><span class="token">.</span><span class="token">company
</span></span><span class="line"><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">Ecto.Association.NotLoaded&lt;association :company is not loaded&gt;</span><span class="token" style="color: #6a737d;">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-164"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-162">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-163'
	>
	Batch inserts</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-167"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-165">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-166'
	>
	To reduce the number of SQL queries, you might need to import data in batches. A use case could be to process data from large <a href="https://infinum.com/blog/superfast-csv-imports-using-postgresqls-copy/">.csv</a> or <a href="https://infinum.com/blog/how-to-efficiently-process-large-excel-files-using-ruby/">.xls</a> tables. For that purpose, we use SQL’s INSERT statement with multiple rows.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-170"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-168">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-169'
	>
	In Rails, we could use a gem like <a href="https://github.com/zdennis/activerecord-import">Active Record Import</a> or similar, but there is no built-in solution. Although Active Record’s <code>create</code> method can accept an array of objects, it does not perform a batch insert, but rather inserts each record one by one.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-173"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-171">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-172'
	>
	Ecto provides a built-in function called <code>insert_all/3</code> that performs batch inserts and it works well.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-175"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-elixir github-light" data-language="elixir" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">MyApp</span><span class="token">.</span><span class="token" style="color: #6f42c1;">Repo</span><span class="token">.</span><span class="token" style="color: #6f42c1;">insert_all</span><span class="token">(</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #6f42c1;">User</span><span class="token">,</span><span class="token"> 
</span></span><span class="line"><span class="token">  </span><span class="token">[</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">[</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #005cc5;">first_name</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">John</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">,</span><span class="token"> 
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #005cc5;">last_name</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">Doe</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">,</span><span class="token"> 
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #005cc5;">email</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">john.doe@example.com</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">]</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">[</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #005cc5;">first_name</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">Jane</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">,</span><span class="token"> 
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #005cc5;">last_name</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">Doe</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">,</span><span class="token"> 
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #005cc5;">email</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">jane.doe@example.com</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">]</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token">]</span><span class="token">
</span></span><span class="line"><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-178"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-176">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-177'
	>
	Repo.one</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-181"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-179">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-180'
	>
	Sometimes you expect only one record to be returned by your query. If you get more than one, you know something is wrong. Ecto provides a function called <code>one</code> that will fetch a single result from the query. It raises an exception if more than one entry is returned.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-184"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-182">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-183'
	>
	Imagine we have a unique index on <code>nickname</code> field in <code>users</code> table.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-187"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-185">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-186'
	>
	Somewhere in our code, we have a query to find a user with the specified nickname:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-189"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-elixir github-light" data-language="elixir" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">query </span><span class="token" style="color: #d73a49;">=</span><span class="token"> from u </span><span class="token" style="color: #d73a49;">in</span><span class="token"> </span><span class="token" style="color: #6f42c1;">User</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">where</span><span class="token" style="color: #005cc5;">:</span><span class="token"> u</span><span class="token">.</span><span class="token">nickname </span><span class="token" style="color: #d73a49;">==</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">mickey</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #6f42c1;">Repo</span><span class="token">.</span><span class="token" style="color: #6f42c1;">one</span><span class="token">(</span><span class="token">query</span><span class="token">)</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-192"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-190">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-191'
	>
	As we know we have a unique index, we are expecting only one result.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-195"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-193">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-194'
	>
	After some time, our business logic changes, and we add another field to our unique index – <code>group_id</code>. Now we can have multiple users with the same nickname, but in different groups.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-198"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-196">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-197'
	>
	Let’s assume that we changed our index, but forgot to change the query in the code; when we query on a nickname that is the same for multiple users, Ecto will raise the following error:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-200"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-elixir github-light" data-language="elixir" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">*</span><span class="token" style="color: #d73a49;">*</span><span class="token"> </span><span class="token">(</span><span class="token" style="color: #6f42c1;">Ecto</span><span class="token">.</span><span class="token" style="color: #6f42c1;">MultipleResultsError</span><span class="token">)</span><span class="token"> expected at most one result but 
</span></span><span class="line"><span class="token">got </span><span class="token" style="color: #005cc5;">2</span><span class="token"> </span><span class="token" style="color: #d73a49;">in</span><span class="token"> query
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-203"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-201">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-202'
	>
	If <code>Repo.one</code> didn’t raise the error on multiple results, we probably wouldn’t easily notice that something is wrong. Our business logic would continue to work with the <strong>first</strong> user returned by the database, not necessarily the <strong>right</strong> one.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-206"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-204">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-205'
	>
	If we compare this with Active Record, methods like <code>find_by</code> would return the first record matching the specified conditions.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-209"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-207">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-208'
	>
	Ecto query language</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-212"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-210">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-211'
	>
	Last, but not least, I like the way queries are written in Ecto. They just feel natural and SQL-ish to me. Let me give you an example of a query written in Ecto:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-214"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-elixir github-light" data-language="elixir" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">from user </span><span class="token" style="color: #d73a49;">in</span><span class="token"> </span><span class="token" style="color: #6f42c1;">User</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">left_join</span><span class="token" style="color: #005cc5;">:</span><span class="token"> company </span><span class="token" style="color: #d73a49;">in</span><span class="token"> </span><span class="token" style="color: #6f42c1;">assoc</span><span class="token">(</span><span class="token">user</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">company</span><span class="token">)</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">where</span><span class="token" style="color: #005cc5;">:</span><span class="token"> user</span><span class="token">.</span><span class="token">age </span><span class="token" style="color: #d73a49;">&lt;</span><span class="token"> </span><span class="token" style="color: #005cc5;">25</span><span class="token"> </span><span class="token" style="color: #d73a49;">or</span><span class="token"> user</span><span class="token">.</span><span class="token">age </span><span class="token" style="color: #d73a49;">&gt;</span><span class="token"> </span><span class="token" style="color: #005cc5;">60</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">select</span><span class="token" style="color: #005cc5;">:</span><span class="token"> %</span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #005cc5;">first_name</span><span class="token" style="color: #005cc5;">:</span><span class="token"> user</span><span class="token">.</span><span class="token">first_name</span><span class="token">,</span><span class="token"> 
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #005cc5;">last_name</span><span class="token" style="color: #005cc5;">:</span><span class="token"> user</span><span class="token">.</span><span class="token">last_name</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #005cc5;">age</span><span class="token" style="color: #005cc5;">:</span><span class="token"> user</span><span class="token">.</span><span class="token">age</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #005cc5;">company</span><span class="token" style="color: #005cc5;">:</span><span class="token"> company</span><span class="token">.</span><span class="token">name
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-217"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-215">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-216'
	>
	Isn’t that beautiful?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-220"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-218">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-219'
	>
	While there are some things I didn’t cover in this article, it’s a brief overview of things I love about Ecto. Feel free to comment about things you love about each of these libraries.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/things-i-wish-active-record-had-after-using-ecto/">Things I Wish ActiveRecord Had After Using Ecto</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
		
	</channel>
</rss>