<?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>Improve Code Quality with RuboCop | Infinum</title>
		<atom:link href="https://infinum.com/blog/code-quality-rubocop/feed/" rel="self" type="application/rss+xml" />
		<link>https://infinum.com/blog/code-quality-rubocop/</link>
		<description>Building digital products</description>
		<lastBuildDate>Fri, 10 Apr 2026 14:51:20 +0000</lastBuildDate>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>

					<item>
				<image>
					<url>8013https://infinum.com/uploads/2020/12/code-quality-rubocop-0.webp</url>
				</image>
				<title>Improve Code Quality with RuboCop</title>
				<link>https://infinum.com/blog/code-quality-rubocop/</link>
				<pubDate>Fri, 11 Dec 2020 11:20:00 +0000</pubDate>
				<dc:creator>Marko Ćilimković</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/code-quality-rubocop/</guid>
				<description>
					<![CDATA[<p>Cleaner pull requests, automated knowledge sharing, and easy engagement with open-source software? Sign me up!</p>
<p>The post <a href="https://infinum.com/blog/code-quality-rubocop/">Improve Code Quality with RuboCop</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-340"
	 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'
	>
	Modern code reviews are considered a key component in the development lifecycle of any IT organization.</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'
	>
	Yearly case studies performed by various researchers report that it’s one of the main methods for improving code quality, sharing knowledge across the team, increased collaboration as well as greater adherence to coding standards.</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-paragraph" data-id="es-99">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-100'
	>
	Unlike Fagan’s<a href="https://ieeexplore.ieee.org/document/5388086"> code inspection design</a> introduced in 1976, most of us employ a more lenient process, which is:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-104"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-102">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-103'
	>
	<li>informal</li><li>asynchronous</li><li>tool-based</li><li>focused on reviewing code changes</li></ul></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'
	>
	Results from multiple analysis have shown that the latent defect discovery rate is about 30% in case of informal reviews, proving them to be very effective. They are also a great source of knowledge, because the process usually entails multiple developers collectively looking at a problem and the possible solution.</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-paragraph" data-id="es-108">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-109'
	>
	However, code reviews can become quite cumbersome for newcomers, especially if you find yourself in a company that has some tribal knowledge, which is usually the case.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-113"
	 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-111"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-112">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2020/12/code-quality-rubocop-1-1400x1049.webp				media='(max-width: 699px)'
				type=image/webp								height="1049"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2020/12/code-quality-rubocop-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="1799"
															width="2400"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-116"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-114">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-115'
	>
	Tribal knowledge is any unwritten form of how a process should work, or in our specific case, how to produce code. And there can be quite <strong>a lot</strong> of it, spanning from syntax preferences to unwritten rules and established conventions, which in turn results in code reviews containing dozens of comments that could have been avoided.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-119"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-117">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-118'
	>
	That kind of noise takes a lot of focus from the business logic and design. It further elongates the code review process as each back and forth takes additional time due to the asynchronous nature of the process.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-122"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-120">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-121'
	>
	A solution to this problem are <strong>linters</strong> and if you chose Ruby as your programming language, chances are high that you already used <a href="https://rubocop.org/">RuboCop</a>.</p></div>	</div>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-128"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-126">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-127'
	>
	Linters are tools used during development that warn the programmer about formatting and adhering to a set of rules.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-131"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-129">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-130'
	>
	The warnings are usually related to syntax, but the Ruby community went a step further and introduced a couple of behavioral ones like <a href="https://github.com/rubocop-hq/rubocop-rails">rubocop-rails</a> that can even spot unwanted behaviour for you.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-134"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-132">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-133'
	>
	If you think about it, why wouldn’t you want automatic warnings when you introduce a bug…before the code is shipped. It sounds amazing!</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-paragraph" data-id="es-135">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-136'
	>
	A very cool behavioural cop is the <em>Rails/UniqueValidationWithoutIndex</em>, which detects model uniqueness validations and checks if the uniqueness constraints are also set on the database level. In the following example you can see how the warning looks like if you forget to add the unique index during database migrations.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-140"
	 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-138"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-139">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2020/12/code-quality-rubocop-2-1400x262.webp				media='(max-width: 699px)'
				type=image/webp								height="262"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2020/12/code-quality-rubocop-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="268"
															width="1434"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-143"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-141">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-142'
	>
	This concept opens up a lot of ideas and opportunities for a company to create a code convention template that is shared throughout all projects. This increases technical cohesion on a team level and ensures that everyone is roughly on the same page when it comes to conventions and best practices.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-146"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-144">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-145'
	>
	Let’s look at a specific code example in Rails that declares the attribute confirmed_at on a User and it defaults to the current time. The <a href="https://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute">Attributes API</a> provides just what we need:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-148"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">class</span><span class="token"> </span><span class="token" style="color: #6f42c1;">User</span><span class="token">
</span></span><span class="line"><span class="token">  attribute </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">confirmed_at</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">datetime</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">default</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">Time</span><span class="token">.</span><span class="token" style="color: #6f42c1;">zone</span><span class="token">.</span><span class="token" style="color: #6f42c1;">now</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-150"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">pry</span><span class="token" style="color: #d73a49;">&gt;</span><span class="token"> </span><span class="token" style="color: #005cc5;">User</span><span class="token">.</span><span class="token" style="color: #d73a49;">new</span><span class="token">
</span></span><span class="line"><span class="token">=&gt;</span><span class="token"> </span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">&lt;User id: nil, confirmed_at: Tue, 27 Oct 2020 11:39:22 UTC +00:00</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-153"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-151">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-152'
	>
	At first glance, this looks totally fine, but if you don’t write thorough tests, the bug can be hard to catch, even during code reviews. Look at what happens for every new user:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-155"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">pry</span><span class="token" style="color: #d73a49;">&gt;</span><span class="token"> </span><span class="token" style="color: #005cc5;">User</span><span class="token">.</span><span class="token" style="color: #d73a49;">new</span><span class="token">
</span></span><span class="line"><span class="token">=&gt;</span><span class="token"> </span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">&lt;User id: nil, confirmed_at: Tue, 27 Oct 2020 11:39:22 UTC +00:00</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">pry</span><span class="token" style="color: #d73a49;">&gt;</span><span class="token"> </span><span class="token" style="color: #005cc5;">User</span><span class="token">.</span><span class="token" style="color: #d73a49;">new</span><span class="token">
</span></span><span class="line"><span class="token">=&gt;</span><span class="token"> </span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">&lt;User id: nil, confirmed_at: Tue, 27 Oct 2020 11:39:22 UTC +00:00</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">pry</span><span class="token" style="color: #d73a49;">&gt;</span><span class="token"> </span><span class="token" style="color: #005cc5;">User</span><span class="token">.</span><span class="token" style="color: #d73a49;">new</span><span class="token">
</span></span><span class="line"><span class="token">=&gt;</span><span class="token"> </span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">&lt;User id: nil, confirmed_at: Tue, 27 Oct 2020 11:39:22 UTC +00:00</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-158"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-156">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-157'
	>
	<em>Time.zone.now</em> is being passed as a value to the default option, and since attribute is a class method, the value of <em>Time.zone.now</em> is set at the moment when the application is booted. This means that all <strong>values</strong> will be the <strong>same</strong> regardless of the return value of <em>Time.zone.now</em> at the time of code execution.<br>The solution is defining <em>confirmed_at</em> dynamically:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-160"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">class</span><span class="token"> </span><span class="token" style="color: #6f42c1;">User</span><span class="token">
</span></span><span class="line"><span class="token">  attribute </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">confirmed_at</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">datetime</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">default</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">-&gt;</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">Time</span><span class="token">.</span><span class="token" style="color: #6f42c1;">zone</span><span class="token">.</span><span class="token" style="color: #6f42c1;">now</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-163"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-161">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-162'
	>
	This is a perfect example of tribal knowledge. You either learn to avoid it by breaking production, writing very thorough unit tests or by having someone more experienced mention it during the code review.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-166"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-164">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-165'
	>
	Now imagine someone’s watching over your code as you type it, without the awkward presence of course, and giving you real time feedback to avoid such pitfalls. This is exactly what RuboCop’s cops provide us with. In order to be able to build such a layer of protection, you first need to understand how the source code gets converted into data structures.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-169"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-167">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-168'
	>
	Abstract syntax tree</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-172"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-170">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-171'
	>
	AST is a <strong>tree representation</strong> of the written <strong>source code</strong>. Each node of the tree denotes a piece of the source code, which can be any literal, object, constant or any other construct used in the programming language.</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-paragraph" data-id="es-173">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-174'
	>
	Let’s take a look at some simple examples of Ruby constructs and how their AST looks like.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-178"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-176">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-177'
	>
	For this, the <a href="https://github.com/whitequark/parser">parser</a> gem is used. After installing it, you can jump into your terminal and start playing around:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-180"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-shellscript github-light" data-language="shellscript" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">ruby-parse</span><span class="token"> </span><span class="token" style="color: #005cc5;">-</span><span class="token" style="color: #005cc5;">e</span><span class="token"> </span><span class="token">&amp;</span><span class="token">#8217;1&amp;#8217;
</span></span><span class="line"><span class="token">(</span><span class="token" style="color: #6f42c1;">int</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">
</span></span><span class="line"><span class="token" style="color: #6f42c1;">ruby-parse</span><span class="token"> </span><span class="token" style="color: #005cc5;">-</span><span class="token" style="color: #005cc5;">e</span><span class="token"> </span><span class="token">&amp;</span><span class="token">#8217;”1”&amp;#8217;
</span></span><span class="line"><span class="token">(</span><span class="token" style="color: #6f42c1;">str</span><span class="token"> </span><span class="token" style="color: #032f62;">“1”)
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #6f42c1;">ruby-parse</span><span class="token"> </span><span class="token" style="color: #005cc5;">-</span><span class="token" style="color: #005cc5;">e</span><span class="token"> </span><span class="token">&amp;</span><span class="token">#8217;:key&amp;#8217;
</span></span><span class="line"><span class="token">(</span><span class="token" style="color: #6f42c1;">sym</span><span class="token"> </span><span class="token" style="color: #032f62;">:key</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #6f42c1;">ruby-parse</span><span class="token"> </span><span class="token" style="color: #005cc5;">-</span><span class="token" style="color: #005cc5;">e</span><span class="token"> </span><span class="token">&amp;</span><span class="token">#8217;[]&amp;#8217;
</span></span><span class="line"><span class="token">(</span><span class="token" style="color: #6f42c1;">array</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #6f42c1;">ruby-parse</span><span class="token"> </span><span class="token" style="color: #005cc5;">-</span><span class="token" style="color: #005cc5;">e</span><span class="token"> </span><span class="token">&amp;</span><span class="token">#8217;{}&amp;#8217;
</span></span><span class="line"><span class="token">(</span><span class="token" style="color: #005cc5;">hash</span><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-183"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-181">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-182'
	>
	The basic constructs are pretty straightforward. We get a readable description of the code, which tells us that 1 is an <strong>integer</strong> with value 1, while “1” is a <strong>string</strong> with value “1”. We can see that this continues to be the case in more complex expressions:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-185"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-shellscript github-light" data-language="shellscript" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">ruby-parse</span><span class="token"> </span><span class="token" style="color: #005cc5;">-</span><span class="token" style="color: #005cc5;">e</span><span class="token"> </span><span class="token">&amp;</span><span class="token">#8217;[1, 2, 3]&amp;#8217;
</span></span><span class="line"><span class="token">(</span><span class="token" style="color: #6f42c1;">array</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token">(</span><span class="token" style="color: #6f42c1;">int</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">  </span><span class="token">(</span><span class="token" style="color: #6f42c1;">int</span><span class="token"> </span><span class="token" style="color: #005cc5;">2</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token">(</span><span class="token" style="color: #6f42c1;">int</span><span class="token"> </span><span class="token" style="color: #005cc5;">3</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #6f42c1;">ruby-parse</span><span class="token"> </span><span class="token" style="color: #005cc5;">-</span><span class="token" style="color: #005cc5;">e</span><span class="token"> </span><span class="token">&amp;</span><span class="token">#8217;{username: “john”, password: “doe”}&amp;#8217;
</span></span><span class="line"><span class="token">(</span><span class="token" style="color: #005cc5;">hash</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token">(</span><span class="token" style="color: #6f42c1;">pair</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">(</span><span class="token" style="color: #6f42c1;">sym</span><span class="token"> </span><span class="token" style="color: #032f62;">:username</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">(</span><span class="token" style="color: #6f42c1;">str</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 class="token">
</span></span><span class="line"><span class="token">  </span><span class="token">(</span><span class="token" style="color: #6f42c1;">pair</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">(</span><span class="token" style="color: #6f42c1;">sym</span><span class="token"> </span><span class="token" style="color: #032f62;">:password</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">(</span><span class="token" style="color: #6f42c1;">str</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 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-188"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-186">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-187'
	>
	If you haven’t grasped what’s going on, it really helps reading the Ruby code out loud. Take a look at the last example and try reading every bit of Ruby code in the most descriptive way possible. I said it the first time like this:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-193"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="blockquote block-blockquote__blockquote" data-id="es-189">
	
	<div class="blockquote__content">
		<i
	class="icon blockquote__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='blockquote-24' data-id='es-190'>
	<svg fill='none' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path clip-rule='evenodd' d='m12 24c6.6274 0 12-5.3726 12-12 0-2.79685-.9568-5.37021-2.561-7.41062-.581.22951-1.0832.60583-1.5069 1.12898-.5132.60844-.7698 1.41969-.7698 2.43375v.07605h2.5789v5.59004h-5.6197v-5.01962c0-1.11547.154-2.06616.4619-2.85205.3336-.81125.757-1.48307 1.2702-2.01545.528-.52161 1.1175-.92155 1.7687-1.1998-2.0728-1.70651-4.7279-2.73128-7.6223-2.73128-6.62742 0-12 5.37258-12 12 0 6.6274 5.37258 12 12 12zm-3.53811-18.05347c-.30793.78589-.46189 1.73658-.46189 2.85205v5.01962h5.6197v-5.59004h-2.5789v-.07605c0-1.01406.2566-1.82531.7698-2.43375.5389-.63379 1.1804-1.05209 1.9245-1.2549v-2.28164c-.7441.07605-1.4626.25351-2.1555.53238-.6928.27887-1.3086.68449-1.84752 1.21688-.51321.53238-.9366 1.2042-1.27019 2.01545z' fill='currentColor' fill-rule='evenodd'/></svg></i><p	class='typography typography--size-36-text js-typography blockquote__quote'
	data-id='es-191'
	>
	I have a hash that contains 2 elements, where the first element key is :username and value is “john” and the second element key is :password and value is “doe”.</p>
		<div class="blockquote__caption-wrap">
					</div>
	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-196"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-194">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-195'
	>
	This is not explicit enough, because I didn’t specify the primitive type of the key (symbol) and value (string) of the elements.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-199"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-197">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-198'
	>
	So, let’s investigate the AST of our example:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-201"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-shellscript github-light" data-language="shellscript" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">ruby-parse</span><span class="token"> </span><span class="token" style="color: #005cc5;">-</span><span class="token" style="color: #005cc5;">e</span><span class="token"> </span><span class="token">&amp;</span><span class="token">#8217;attribute :confirmed_at, :datetime, default: Time.zone.now&amp;#8217;
</span></span><span class="line"><span class="token">(</span><span class="token" style="color: #6f42c1;">send</span><span class="token"> </span><span class="token" style="color: #032f62;">nil</span><span class="token"> </span><span class="token" style="color: #032f62;">:attribute</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token">(</span><span class="token" style="color: #6f42c1;">sym</span><span class="token"> </span><span class="token" style="color: #032f62;">:confirmed_at</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token">(</span><span class="token" style="color: #6f42c1;">sym</span><span class="token"> </span><span class="token" style="color: #032f62;">:datetime</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token">(</span><span class="token" style="color: #005cc5;">hash</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">(</span><span class="token" style="color: #6f42c1;">pair</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token">(</span><span class="token" style="color: #6f42c1;">sym</span><span class="token"> </span><span class="token" style="color: #032f62;">:default</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token">(</span><span class="token" style="color: #6f42c1;">send</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">(</span><span class="token" style="color: #6f42c1;">send</span><span class="token">
</span></span><span class="line"><span class="token">          </span><span class="token">(</span><span class="token" style="color: #6f42c1;">const</span><span class="token"> </span><span class="token" style="color: #032f62;">nil</span><span class="token"> </span><span class="token" style="color: #032f62;">:Time</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #6f42c1;">:zone</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #6f42c1;">:now</span><span class="token">)</span><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></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-204"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-202">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-203'
	>
	Looks familiar, doesn’t it? It’s a combination of all the nodes we’ve parsed in the previous examples. Any class that inherits <strong>ApplicationRecord</strong> or includes the <strong>AttributesAPI</strong> module can receive the <em>attribute</em> message that accepts 3 arguments:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-207"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-205">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-206'
	>
	<li><em>symbol</em> confirmed_at</li><li><em>symbol</em> datetime</li><li>keyword argument <em>:default</em> with any value (in our case <em>Time.zone.now</em>)</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-210"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-208">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-209'
	>
	The AST concept gives us the ability to convert source code into data structures. Now we just need another tool that will traverse the tree and find specific nodes in Ruby using pattern matching, or maybe regular expressions?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-213"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-211">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-212'
	>
	Node pattern</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-216"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-214">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-215'
	>
	Fortunately for us, this problem has also been solved with the <a href="https://github.com/rubocop-hq/rubocop-ast/blob/master/docs/modules/ROOT/pages/node_pattern.adoc">Node pattern</a>. It is a DSL for finding specific nodes in the AST using simple strings.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-219"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-217">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-218'
	>
	This is the last step before diving into the implementation of a custom cop &#8211; finding the right string that will match against a specific AST. Here are some examples of the Ruby code, AST, and the pattern.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-222"
	 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-220"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-221">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2020/12/code-quality-rubocop-3-1400x829.webp				media='(max-width: 699px)'
				type=image/webp								height="829"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2020/12/code-quality-rubocop-3.webp"
					class="image__img block-media__image-img"
					alt=""
										height="860"
															width="1452"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-225"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-223">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-224'
	>
	The only real difference between the AST and the pattern is <strong>nil?</strong>, which is a <a href="https://github.com/rubocop-hq/rubocop-ast/blob/master/docs/modules/ROOT/pages/node_pattern.adoc#user-content-nil-or-nil">special case</a> predicate that matches against nil objects. Bear in mind that the goal is to match <strong>arbitrary</strong> code to these patterns, not just our specific examples in the table. We need to take great care of warning of invalid cases while keeping the valid usages unaffected:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-227"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">attribute </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">role</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">string</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">default</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">user</span><span class="token">
</span></span><span class="line"><span class="token">attribute </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">role</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">default</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">user</span><span class="token">
</span></span><span class="line"><span class="token">attribute </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">active</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">boolean</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">default</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">true</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-230"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-228">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-229'
	>
	Sandi Metz gave an <a href="https://youtu.be/29MAL8pJImQ">excellent talk</a> on RailsConf in 2015, where she stated:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-235"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="blockquote block-blockquote__blockquote" data-id="es-231">
	
	<div class="blockquote__content">
		<i
	class="icon blockquote__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='blockquote-24' data-id='es-232'>
	<svg fill='none' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path clip-rule='evenodd' d='m12 24c6.6274 0 12-5.3726 12-12 0-2.79685-.9568-5.37021-2.561-7.41062-.581.22951-1.0832.60583-1.5069 1.12898-.5132.60844-.7698 1.41969-.7698 2.43375v.07605h2.5789v5.59004h-5.6197v-5.01962c0-1.11547.154-2.06616.4619-2.85205.3336-.81125.757-1.48307 1.2702-2.01545.528-.52161 1.1175-.92155 1.7687-1.1998-2.0728-1.70651-4.7279-2.73128-7.6223-2.73128-6.62742 0-12 5.37258-12 12 0 6.6274 5.37258 12 12 12zm-3.53811-18.05347c-.30793.78589-.46189 1.73658-.46189 2.85205v5.01962h5.6197v-5.59004h-2.5789v-.07605c0-1.01406.2566-1.82531.7698-2.43375.5389-.63379 1.1804-1.05209 1.9245-1.2549v-2.28164c-.7441.07605-1.4626.25351-2.1555.53238-.6928.27887-1.3086.68449-1.84752 1.21688-.51321.53238-.9366 1.2042-1.27019 2.01545z' fill='currentColor' fill-rule='evenodd'/></svg></i><p	class='typography typography--size-36-text js-typography blockquote__quote'
	data-id='es-233'
	>
	You can reveal how things are different, by making them more alike.</p>
		<div class="blockquote__caption-wrap">
					</div>
	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-238"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-236">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-237'
	>
	By putting this quote to use, we can spot the static nodes in an infinite range of code possibilities and reveal the pattern:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-240"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">attribute </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">any_name</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">optional_argument</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">default</span><span class="token" style="color: #005cc5;">:</span><span class="token"> any_construct
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-243"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-241">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-242'
	>
	<li><em>attribute</em> &#8211; the class method that never changes, so we keep this as “attribute” in the pattern</li><li><em>any_name</em> &#8211; doesn’t really concern us, as long as it is there because the API requires it as a method parameter. This fits the bill nicely for the _ matcher. It will fit <a href="https://github.com/rubocop-hq/rubocop-ast/blob/master/docs/modules/ROOT/pages/node_pattern.adoc#_-for-any-single-node">any single node</a>.</li><li><em>optional_argument</em> &#8211; also doesn’t matter what it is, but it doesn’t have to exist. The &#8220;?&#8221; matcher limits the match to 0 or 1 nodes, and when used in conjunction with &#8220;_&#8221; you effectively create a pattern for any optional construct &#8220;?_&#8221;</li><li><em>default</em> &#8211; the <a href="https://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute">Attributes API</a> also receives keyword arguments, but we are only interested in the hash when the first node is a symbol with value “default”. This is covered in the Abstract Syntax Tree chapter by parsing the hash.</li><li><em>any_construct</em> &#8211; this is the target we are interested in. If we can get the type of this node we’ll be able to warn the developer for offending cases like a method call, array or hash, because none of those should be used on the class level, since we’re creating an attribute that will be used on the instance level. The $ matcher <a href="https://github.com/rubocop-hq/rubocop-ast/blob/master/docs/modules/ROOT/pages/node_pattern.adoc#-for-captures">captures the node</a>, making it available for processing.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-246"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-244">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-245'
	>
	Let’s use the information and write the pattern that would fit the bill for all cases:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-248"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-shellscript github-light" data-language="shellscript" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">(</span><span class="token" style="color: #6f42c1;">send</span><span class="token"> </span><span class="token" style="color: #032f62;">nil?</span><span class="token"> </span><span class="token" style="color: #032f62;">:attribute</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #6f42c1;">_</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #6f42c1;">?_</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token">(</span><span class="token" style="color: #005cc5;">hash</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">(</span><span class="token" style="color: #6f42c1;">pair</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token">(</span><span class="token" style="color: #6f42c1;">sym</span><span class="token"> </span><span class="token" style="color: #032f62;">:default</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #005cc5;">$</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></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-251"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-249">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-250'
	>
	At this point, you should be confident enough to start writing some code.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-254"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-252">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-253'
	>
	Creating the cop</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-257"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-255">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-256'
	>
	We love writing tests, especially when the tests are fast and easy to understand.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-260"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-258">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-259'
	>
	RuboCop provides a beautiful DSL for testing cops but unfortunately a lot of articles found online don’t have the information how to set up cop tests. Don’t worry, we’ve got you covered this time!</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-263"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-261">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-262'
	>
	Here are some tips for setting up RSpec cop tests:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-266"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-264">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-265'
	>
	Make sure RuboCop is in your Gemfile and bundled up.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-269"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-267">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-268'
	>
	Open <em>spec/rails_helper.rb</em> and add:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-271"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">require</span><span class="token"> </span><span class="token" style="color: #d73a49;">&amp;</span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">8217;rubocop&amp;#8217;</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token" style="color: #d73a49;">require</span><span class="token"> </span><span class="token" style="color: #d73a49;">&amp;</span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">8217;rubocop/rspec/support&amp;#8217;</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><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-274"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-272">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-273'
	>
	Include it globally or specific category of tests (eg. type: :cop):</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-276"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #005cc5;">RSpec</span><span class="token">.</span><span class="token" style="color: #6f42c1;">configure</span><span class="token"> </span><span class="token" style="color: #d73a49;">do</span><span class="token"> </span><span class="token" style="color: #d73a49;">|</span><span class="token">config</span><span class="token" style="color: #d73a49;">|</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">  config</span><span class="token">.</span><span class="token" style="color: #d73a49;">include</span><span class="token"> </span><span class="token" style="color: #005cc5;">RuboCop</span><span class="token">::</span><span class="token" style="color: #005cc5;">RSpec</span><span class="token">::</span><span class="token" style="color: #005cc5;">ExpectOffense</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: #6a737d;">#</span><span class="token" style="color: #6a737d;"> rest of your rspec configuration</span><span class="token" style="color: #6a737d;">
</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-279"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-277">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-278'
	>
	The <strong>ExpectOffense</strong> module provides us with a beautiful way of writing clear and descriptive cop tests. They resemble the actual Ruby code you’re trying to cover:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-281"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">spec/cop/rails/attribute_default_block_value_spec.rb</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">describe </span><span class="token" style="color: #005cc5;">Cop</span><span class="token">::</span><span class="token" style="color: #005cc5;">Rails</span><span class="token">::</span><span class="token" style="color: #005cc5;">AttributeDefaultBlockValue</span><span class="token"> </span><span class="token" style="color: #d73a49;">do</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #6f42c1;">subject</span><span class="token">(</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">cop</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token">described_class</span><span class="token">.</span><span class="token" style="color: #d73a49;">new</span><span class="token">(</span><span class="token">config</span><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><span class="line"><span class="token">  </span><span class="token" style="color: #6f42c1;">let</span><span class="token">(</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">config</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">RuboCop</span><span class="token">::</span><span class="token" style="color: #005cc5;">Config</span><span class="token">.</span><span class="token" style="color: #d73a49;">new</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: #6f42c1;">let</span><span class="token">(</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">message</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #d73a49;">&amp;</span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">8217;Pass method in a block to `:default` option.&amp;#8217; }</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">  it </span><span class="token" style="color: #d73a49;">&amp;</span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">8217;disallows method called from other objects&amp;#8217; do</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6f42c1;">expect_offense</span><span class="token">(</span><span class="token" style="color: #032f62;">&lt;&lt;~RUBY</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">      attribute </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">confirmed_at</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">datetime</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">default</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">Time</span><span class="token">.</span><span class="token" style="color: #6f42c1;">zone</span><span class="token">.</span><span class="token" style="color: #6f42c1;">now</span><span class="token">
</span></span><span class="line"><span class="token">                                                   </span><span class="token" style="color: #d73a49;">^</span><span class="token" style="color: #d73a49;">^</span><span class="token" style="color: #d73a49;">^</span><span class="token" style="color: #d73a49;">^</span><span class="token" style="color: #d73a49;">^</span><span class="token" style="color: #d73a49;">^</span><span class="token" style="color: #d73a49;">^</span><span class="token" style="color: #d73a49;">^</span><span class="token" style="color: #d73a49;">^</span><span class="token" style="color: #d73a49;">^</span><span class="token" style="color: #d73a49;">^</span><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">message</span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #032f62;">    RUBY
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">end</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-284"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-282">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-283'
	>
	Now we can create the cop:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-286"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">lib/cop/rails/attribute_default_block_value.rb</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">module</span><span class="token"> </span><span class="token" style="color: #6f42c1;">Cop</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">module</span><span class="token"> </span><span class="token" style="color: #6f42c1;">Rails</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">class</span><span class="token"> </span><span class="token" style="color: #6f42c1;">AttributeDefaultBlockValue</span><span class="token"> </span><span class="token" style="color: #d73a49;">&lt;</span><span class="token"> </span><span class="token">::</span><span class="token" style="color: #005cc5;">RuboCop</span><span class="token">::</span><span class="token" style="color: #005cc5;">Cop</span><span class="token">::</span><span class="token" style="color: #005cc5;">Cop</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #005cc5;">MSG</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #d73a49;">&amp;</span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">8217;Pass method in a block to `:default` option.&amp;#8217;</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #005cc5;">TYPE_OFFENDERS</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">%i[</span><span class="token" style="color: #005cc5;">send array hash</span><span class="token" style="color: #005cc5;">]</span><span class="token">.</span><span class="token" style="color: #6f42c1;">freeze</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">      def_node_matcher </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">default_attribute</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #032f62;">&lt;&lt;~PATTERN</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #032f62;">        (send nil? :attribute _ ?_ (hash &lt;$#attribute ...&gt;))
</span></span><span class="line"><span class="token" style="color: #032f62;">      PATTERN</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">      def_node_matcher </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">attribute</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #d73a49;">&amp;</span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">8217;(pair (sym :default) $_)&amp;#8217;</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #d73a49;">def</span><span class="token"> </span><span class="token" style="color: #6f42c1;">on_send</span><span class="token">(</span><span class="token">node</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6f42c1;">default_attribute</span><span class="token">(</span><span class="token">node</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">do</span><span class="token"> </span><span class="token" style="color: #d73a49;">|</span><span class="token">attribute</span><span class="token" style="color: #d73a49;">|</span><span class="token">
</span></span><span class="line"><span class="token">          </span><span class="token" style="color: #e36209;">value</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> attribute</span><span class="token">.</span><span class="token" style="color: #6f42c1;">children</span><span class="token">.</span><span class="token" style="color: #6f42c1;">last</span><span class="token">
</span></span><span class="line"><span class="token">          </span><span class="token" style="color: #d73a49;">return</span><span class="token"> </span><span class="token" style="color: #d73a49;">unless</span><span class="token"> </span><span class="token" style="color: #005cc5;">TYPE_OFFENDERS</span><span class="token">.</span><span class="token" style="color: #6f42c1;">any?</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #d73a49;">|</span><span class="token">type</span><span class="token" style="color: #d73a49;">|</span><span class="token"> value</span><span class="token">.</span><span class="token" style="color: #6f42c1;">type</span><span class="token"> </span><span class="token" style="color: #d73a49;">==</span><span class="token"> type </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: #6f42c1;">add_offense</span><span class="token">(</span><span class="token">node</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">location</span><span class="token" style="color: #005cc5;">:</span><span class="token"> value</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">end</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-289"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-287">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-288'
	>
	<em>RuboCop::Cop::Cop</em> provides a bunch of stuff that’s used in all class instance cops.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-292"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-290">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-291'
	>
	The <strong>def_node_matcher</strong> method is used for matching nodes. It requires the name of the matcher and the matching pattern. In the example above I used matcher chaining, but you can just as easily use one matcher with the AST that was defined at the end of the previous chapter:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-294"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">def_node_matcher </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">default_attribute</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #032f62;">&lt;&lt;~PATTERN</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #032f62;">  (send nil? :attribute
</span></span><span class="line"><span class="token" style="color: #032f62;">    _
</span></span><span class="line"><span class="token" style="color: #032f62;">    ?_
</span></span><span class="line"><span class="token" style="color: #032f62;">    (hash
</span></span><span class="line"><span class="token" style="color: #032f62;">      (pair
</span></span><span class="line"><span class="token" style="color: #032f62;">        (sym :default)
</span></span><span class="line"><span class="token" style="color: #032f62;">        $_))
</span></span><span class="line"><span class="token" style="color: #032f62;">PATTERN</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-297"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-295">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-296'
	>
	Callback methods (on_send, on_block, on_class etc…) check whether a node is matched against a pattern. You know what callback to use from the first node AST, which in our case is <strong>send</strong>. We used def on_send(node).</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-300"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-298">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-299'
	>
	Inside of the callback methods you usually start off with the matcher name defined in def_node_matcher in order to get the offending construct. When calling default_attribute(node), you get an instance of a type of <strong>RuboCop::AST::Node</strong> that knows its type and node children, alongside other things.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-303"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-301">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-302'
	>
	The <strong>add_offense</strong> method provides an easy way of adding a warning message, defining the error positioning (^^^) and the severity of the error:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-306"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-304">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-305'
	>
	<li>refactor</li><li>convention</li><li>warning</li><li>error</li><li>fatal</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-309"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-307">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-308'
	>
	I advise you to look at the <a href="https://github.com/rubocop-hq/rubocop">RuboCop source code</a>, because it’s really nicely documented and there’s a lot of examples for learning. The rest is just…Ruby.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-312"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-310">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-311'
	>
	Lastly, include your new cop in <em>.rubocop.yml</em>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-314"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-yaml github-light" data-language="yaml" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #22863a;">r</span><span class="token" style="color: #22863a;">equire</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 class="token" style="color: #032f62;">.</span><span class="token" style="color: #032f62;">/lib/cop/rails/attribute_default_block_value</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token">-</span><span class="token"> </span><span class="token" style="color: #032f62;">r</span><span class="token" style="color: #032f62;">ubocop-infinum</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-317"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-315">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-316'
	>
	Upon reopening or changing a file, you should see the new cop in action.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-320"
	 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-318"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-319">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2020/12/code-quality-rubocop-4-1400x276.webp				media='(max-width: 699px)'
				type=image/webp								height="276"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2020/12/code-quality-rubocop-4.webp"
					class="image__img block-media__image-img"
					alt=""
										height="306"
															width="1550"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-323"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-321">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-322'
	>
	Want cleaner pull requests?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-326"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-324">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-325'
	>
	Code reviews are important and the discussions should focus on strategies used to solve the domain-specific problem, finding edge cases, and pointing out possible design or test improvements. They should have a minimum number of comments related to project conventions, as well as company code conventions, typos, or syntax errors.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-329"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-327">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-328'
	>
	Having a quick feedback loop in your IDE enables all of that, while being much more effective time-wise than PR reviews.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-332"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-330">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-331'
	>
	Another benefit is the feeling of accomplishment when your custom cop gets recognized as useful and gets promoted from a project-specific cop to a company-specific one. Maybe it will even get <a href="https://github.com/rubocop-hq/rubocop-rails/pull/339">merged</a> with the other cops to serve and protect codebases all around the world.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-335"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-333">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-334'
	>
	We use RuboCop at Infinum and have only started down this road, but we see a lot of benefits. Having cleaner pull requests, automated knowledge sharing and being able to engage with open source software makes it a no-brainer.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-338"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-336">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-337'
	>
	The Ruby community is one of the nicest programming-language-related communities out there and we should all actively search for ways to improve it and help other fellow developers write good, clean code.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/code-quality-rubocop/">Improve Code Quality with RuboCop</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
		
	</channel>
</rss>