<?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>Author at Infinum</title>
		<atom:link href="https://infinum.com/blog/author/damir-svrtan/feed/" rel="self" type="application/rss+xml" />
		<link></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>7908https://infinum.com/uploads/2017/02/better-login-forms-without-security-risks-0.webp</url>
				</image>
				<title>Better Login Forms Without Security Risks</title>
				<link>https://infinum.com/blog/better-login-forms-without-security-risks/</link>
				<pubDate>Tue, 29 Nov 2016 15:10:00 +0000</pubDate>
				<dc:creator>Damir Svrtan</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/better-login-forms-without-security-risks/</guid>
				<description>
					<![CDATA[<p>However, more often than not, various implementations trade-off good UX for security assumptions that are out of place.</p>
<p>The post <a href="https://infinum.com/blog/better-login-forms-without-security-risks/">Better Login Forms Without Security Risks</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-199"
	 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'
	>
	It goes without saying that good login and registration forms are essential to providing a great user experience.</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'
	>
	However, more often than not, various implementations trade-off good UX for security assumptions that are out of place.</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-auto" data-id="es-100">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2017/02/better-login-forms-without-security-risks-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="543"
															width="1000"
										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'
	>
	Let’s take a look at 3 easy steps to improve your authentication UX and comment on how to tweak the defaults set in <a href="https://github.com/plataformatec/devise">Devise</a>, the most popular out-of-the-box authentication solution in Rails.</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-heading" data-id="es-105">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-106'
	>
	Get rid of the ambiguous login failure message</h2></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'
	>
	Usually, login forms show the same error message upon a failed login attempt, regardless of whether you’ve mistyped the email or the password:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-112"
	 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: #005cc5;">Invalid</span><span class="token"> </span><span class="token" style="color: #005cc5;">email</span><span class="token"> </span><span class="token" style="color: #005cc5;">address</span><span class="token" style="color: #d73a49;">/</span><span class="token" style="color: #005cc5;">password</span><span class="token"> </span><span class="token" style="color: #005cc5;">combination</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-115"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-113">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-114'
	>
	I’ve personally changed multiple emails through the last couple of years so sometimes I don’t know which email I’ve used on a certain service (mostly on services I haven’t used for some time or don’t have them in my LastPass vault yet). The process of getting the right email and password combination can get downright irritating, so oftentimes I resort to trying to send myself a password reset email to the right email address.</p></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'
	>
	A better approach for websites would be to say <strong>which of the two is actually wrong</strong>:</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'
	>
	– An account with the given email address does not exist.</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-paragraph" data-id="es-122">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-123'
	>
	– The given password mismatches the one stored for that particular user.</p></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'
	>
	If the security skeptic inside you now thinks this is a <strong>obvious security issue</strong> since the internet villains could easily find out which emails are in use and which are not, you’re somewhat wrong:</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'
	>
	<strong>You probably have a user registration form, so it’s really easy to find out if an email is in use by trying to register with that email address.</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-133"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-131">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-132'
	>
	If you still think that this approach is wrong, some of the best-known sites in the world use it – check out how <a href="https://accounts.google.com/ServiceLogin#identifier">Google</a>, <a href="https://www.netflix.com/us/Login">Netflix</a>, <a href="https://www.facebook.com/login">Facebook</a>, <a href="https://www.pinterest.com/login/">Pinterest</a> or <a href="https://www.eventbrite.com/">Eventbrite</a> handle invalid login attempts.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-auto" data-id="es-135">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2016/05/better-login-forms-without-security-risks-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="374"
															width="410"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-139"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-137">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-138'
	>
	Devise Implementation</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-142"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-140">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-141'
	>
	Devise hands out an easy way to tweak these messages with the I18n internationalization and localization framework, and it’s a configurable YAML file:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-144"
	 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;">e</span><span class="token" style="color: #22863a;">n</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #22863a;">d</span><span class="token" style="color: #22863a;">evise</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #22863a;">f</span><span class="token" style="color: #22863a;">ailure</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #22863a;">n</span><span class="token" style="color: #22863a;">ot_found_in_database</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">W</span><span class="token" style="color: #032f62;">e couldn’t find an account for that email address.</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #22863a;">i</span><span class="token" style="color: #22863a;">nvalid</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">S</span><span class="token" style="color: #032f62;">orry, your password was incorrect. Please double-check your password.</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-147"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-145">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-146'
	>
	It’s good practice to link back to the registration form after an unsuccessful login occurs due to the email not existing in the database.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-150"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-148">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-149'
	>
	Ditch the password confirmation field</h2></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'
	>
	Your user conversion rate is proportional to the simplicity of your registration form. Some of the simplest registration forms (excluding social logins with Facebook, Twitter, etc.) only contain three fields: an email, password, and a password confirmation field.</p></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'
	>
	<strong>Can it get any simpler than that? Sure it can, ditch the password confirmation.</strong></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'
	>
	When was the last time your password and password confirmation field mismatched? I think I <strong>never</strong> actually got that error. And if your users manage to mistype their password, it’s easy for them to reset their password since Devise offers that functionality out-of-the-box.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-162"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-160">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-161'
	>
	Devise Implementation</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-165"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-163">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-164'
	>
	This one’s even easier to accomplish – just remove the password confirmation field from your HTML form (<code>views/devise/registration/new.html.erb</code>) and Devise will automatically ignore it since it’s <strong>nil</strong> (unlike when you submit a blank confirmation field through the form, then it’s an empty string).</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-168"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-166">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-167'
	>
	Show if the email exists when resetting your user’s passwords</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-171"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-169">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-170'
	>
	Regardless of whether the email address exists or not, some websites show the same message after requesting a password reset:</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-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: #005cc5;">An</span><span class="token"> </span><span class="token" style="color: #005cc5;">email</span><span class="token"> </span><span class="token" style="color: #005cc5;">with</span><span class="token"> </span><span class="token" style="color: #005cc5;">a</span><span class="token"> </span><span class="token" style="color: #005cc5;">password</span><span class="token"> </span><span class="token" style="color: #005cc5;">reset</span><span class="token"> </span><span class="token" style="color: #005cc5;">link</span><span class="token"> </span><span class="token" style="color: #005cc5;">has</span><span class="token"> </span><span class="token" style="color: #005cc5;">been</span><span class="token"> </span><span class="token" style="color: #005cc5;">sent</span><span class="token"> </span><span class="token" style="color: #005cc5;">to</span><span class="token"> </span><span class="token" style="color: #005cc5;">you</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-176"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-174">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-175'
	>
	The security implication behind this ambiguous message is that we don’t want to show nosy people whether an email is used on our website or not. The reason to ditch this behavior is the same as before – people can still use the registration form to find which emails were already used.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-179"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-177">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-178'
	>
	Devise Implementation</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-182"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-180">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-181'
	>
	By default, Devise shows whether the email address exists or not, so there’s nothing to do here.</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-heading" data-id="es-183">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-184'
	>
	Important Note</h3></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'
	>
	Showing whether an email address exists on login and forgot password forms isn’t a security risk if you have a registration form showing the exact same thing. However, you might have an invitation-based system and no registration form. In that case, you’re not exposing the user’s email, so the same security assumption doesn’t imply.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-191"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-189">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-190'
	>
	No ambiguous error messages</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-194"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-192">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-193'
	>
	If you want to prevent malicious attacks, don’t try doing it through ambiguous error messages. Instead, use 2FA (<a href="https://github.com/tinfoil/devise-two-factor">devise-two-factor</a>) or throttle your requests with <a href="https://github.com/kickstarter/rack-attack">Rack Attack</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-197"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-195">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-196'
	>
	These are three easy wins. If you’ve got any similar ones up your sleeve, feel free to share your comments below.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/better-login-forms-without-security-risks/">Better Login Forms Without Security Risks</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>7978https://infinum.com/uploads/2017/02/whitelisting-with-the-lesser-known-presence-in-method-0.webp</url>
				</image>
				<title>Whitelisting with the Lesser-Known #presence_in Method</title>
				<link>https://infinum.com/blog/whitelisting-with-the-lesser-known-presence-in-method/</link>
				<pubDate>Tue, 05 Apr 2016 13:56:00 +0000</pubDate>
				<dc:creator>Damir Svrtan</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/whitelisting-with-the-lesser-known-presence-in-method/</guid>
				<description>
					<![CDATA[<p>Have a look at this hidden ActiveSupport #presence_in method that provides a convenient way to do whitelisting in just one line.</p>
<p>The post <a href="https://infinum.com/blog/whitelisting-with-the-lesser-known-presence-in-method/">Whitelisting with the Lesser-Known #presence_in Method</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-260"
	 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-200">
	</div>

<div class="block-blog-content-main">
	
<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'
	>
	Quite often when writing Rails applications we need to do some kind of user input sanitization. We usually end up doing some dull checks across multiple lines. Have a look at this hidden ActiveSupport #presence_in method that provides a convenient way to do whitelisting in just one line.</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-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-204"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-205">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2017/02/whitelisting-with-the-lesser-known-presence-in-method-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="550"
															width="1000"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-209"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-207">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-208'
	>
	Let’s say your app presents a list of articles and offers multiple ways of sorting them: by upload date, by the number of upvotes and number of comments. One of the possible techniques to support this behavior is defining three types of scopes on your Article model:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-211"
	 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;">Article</span><span class="token"> </span><span class="token">&lt;</span><span class="token"> </span><span class="token" style="color: #6f42c1;">ActiveRecord</span><span class="token" style="color: #6f42c1;">::</span><span class="token" style="color: #6f42c1;">Base</span><span class="token">
</span></span><span class="line"><span class="token">  scope </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">newest</span><span class="token">,</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: #6f42c1;">order</span><span class="token">(</span><span class="token" style="color: #005cc5;">updated_at</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;">desc</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">  scope </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">top</span><span class="token">,</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: #6f42c1;">order</span><span class="token">(</span><span class="token" style="color: #005cc5;">upvotes_count</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;">desc</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">  scope </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">most_commented</span><span class="token">,</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: #6f42c1;">order</span><span class="token">(</span><span class="token" style="color: #005cc5;">comments_count</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;">desc</span><span class="token">)</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-214"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-212">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-213'
	>
	You’ll want to call those scopes depending on the query parameter passed to your controller, e.g. <code>/articles?sort_by=newest</code>.</p></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'
	>
	The easiest way to implement this in our controller would be:</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-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;">ArticlesController</span><span class="token"> </span><span class="token">&lt;</span><span class="token"> </span><span class="token" style="color: #6f42c1;">ApplicationController</span><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;">index</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #24292e;">@</span><span class="token" style="color: #24292e;">articles</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">Article</span><span class="token">.</span><span class="token" style="color: #6f42c1;">public_send</span><span class="token">(</span><span class="token">params</span><span class="token">[</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">sort_by</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;">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-222"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-220">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-221'
	>
	However, you don’t want to send those user inputs directly to your model because you would leave yourself <code>vulnerable to remote code execution</code>. An evildoer could send you a request such as <code>/articles?sort_by=destroy_all</code> and destroy your records.</p></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'
	>
	As a responsible developer, you sanitize that input:</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" style="color: #d73a49;">class</span><span class="token"> </span><span class="token" style="color: #6f42c1;">ArticlesController</span><span class="token"> </span><span class="token">&lt;</span><span class="token"> </span><span class="token" style="color: #6f42c1;">ApplicationController</span><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;">index</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #24292e;">@</span><span class="token" style="color: #24292e;">articles</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">Article</span><span class="token">.</span><span class="token" style="color: #6f42c1;">public_send</span><span class="token">(</span><span class="token">sorting_technique</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><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">private</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;">def</span><span class="token"> </span><span class="token" style="color: #6f42c1;">sorting_technique</span><span class="token">
</span></span><span class="line"><span class="token">     </span><span class="token" style="color: #d73a49;">if</span><span class="token"> </span><span class="token" style="color: #032f62;">%w(</span><span class="token" style="color: #032f62;">newest most_commented top</span><span class="token" style="color: #032f62;">)</span><span class="token">.</span><span class="token" style="color: #6f42c1;">include?</span><span class="token"> params</span><span class="token">[</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">sort_by</span><span class="token">]</span><span class="token">
</span></span><span class="line"><span class="token">       params</span><span class="token">[</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">sort_by</span><span class="token">]</span><span class="token">
</span></span><span class="line"><span class="token">     </span><span class="token" style="color: #d73a49;">else</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;">newest</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-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'
	>
	Although this code provides safety, it’s still not very nice. I’ve written similar code many times and have never felt happy about it because I believed it could be shorter.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-233"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-231">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-232'
	>
	The #presence_in method to the rescue</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-236"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-234">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-235'
	>
	That’s where the lesser-known method from the <a href="http://guides.rubyonrails.org/active_support_core_extensions.html">ActiveSupport</a> module called <a href="http://api.rubyonrails.org/classes/Object.html#method-i-presence_in">Object#presence_in</a> comes in.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-239"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-237">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-238'
	>
	Description:</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-242"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-240">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-241'
	>
	<em>Returns the receiver if it’s included in the argument. Otherwise, it returns nil. The argument has to be any object which responds to #include?.</em></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-245"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-243">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-244'
	>
	Source:</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-247"
	 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;">def</span><span class="token"> </span><span class="token" style="color: #6f42c1;">presence_in</span><span class="token">(</span><span class="token">another_object</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #005cc5;">self</span><span class="token">.</span><span class="token" style="color: #6f42c1;">in?</span><span class="token">(</span><span class="token">another_object</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">?</span><span class="token"> </span><span class="token" style="color: #005cc5;">self</span><span class="token"> </span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">nil</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-250"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-248">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-249'
	>
	Usage:</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-253"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-251">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-252'
	>
	With the <code>presence_in</code> method we can write our <code>sorting_technique</code> method with a nice one-liner:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-255"
	 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;">def</span><span class="token"> </span><span class="token" style="color: #6f42c1;">sorting_technique</span><span class="token">
</span></span><span class="line"><span class="token">  params</span><span class="token">[</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">sort_by</span><span class="token">]</span><span class="token">.</span><span class="token" style="color: #6f42c1;">presence_in</span><span class="token">(</span><span class="token" style="color: #032f62;">%w(</span><span class="token" style="color: #032f62;">newest most_commented top</span><span class="token" style="color: #032f62;">)</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">||</span><span class="token"> </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">newest</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-258"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-256">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-257'
	>
	Its usage doesn’t stop here, but I’ve found it to be most useful when sanitizing user input.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/whitelisting-with-the-lesser-known-presence-in-method/">Whitelisting with the Lesser-Known #presence_in Method</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>7952https://infinum.com/uploads/2017/02/multiline-strings-ruby-2-3-0-the-squiggly-heredoc-0.webp</url>
				</image>
				<title>Multiline Strings in Ruby 2.3  the Squiggly Heredoc</title>
				<link>https://infinum.com/blog/multiline-strings-ruby-2-3-0-the-squiggly-heredoc/</link>
				<pubDate>Tue, 22 Dec 2015 11:00:00 +0000</pubDate>
				<dc:creator>Damir Svrtan</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/multiline-strings-ruby-2-3-0-the-squiggly-heredoc/</guid>
				<description>
					<![CDATA[<p>Did you ever have to write a nicely indented multiline string in Ruby? There was no out-of-the-box solution until the squiggly heredoc was introduced.</p>
<p>The post <a href="https://infinum.com/blog/multiline-strings-ruby-2-3-0-the-squiggly-heredoc/">Multiline Strings in Ruby 2.3  the Squiggly Heredoc</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-315"
	 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-261">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-264"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-262">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-263'
	>
	Have you ever had to write a <strong>nicely indented multiline string</strong> in Ruby? If you have, you already know that Ruby <strong>doesn’t have a nice out-of-the-box solution</strong> for this problem. At least it hadn’t until a week ago when the squiggly heredoc was introduced…</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-267"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-265">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-266'
	>
	To be honest, I actually rarely need to use multiline strings, but when I do, it <strong>really gets on my nerves</strong> that <a href="https://infinum.com/blog/becoming-a-ruby-on-rails-developer/">Ruby</a> lacks an upfront way to do them. Every time I need to write a multiline string, I google it and hope that someone has found a way to write it without performing ugly ‘hacks’ that can be found in this <a href="http://stackoverflow.com/questions/2337510/ruby-can-i-write-multi-line-string-with-no-concatenation">Stack Overflow post</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-270"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-268">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-269'
	>
	The first thing that comes to mind when doing multiline strings is using the <code>HEREDOC</code> syntax.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-272"
	 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;">Subscription</span><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;">warning_message</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #032f62;">&lt;&lt;-HEREDOC</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #032f62;">      Subscription expiring soon!
</span></span><span class="line"><span class="token" style="color: #032f62;">      Your free trial will expire in </span><span class="token" style="color: #032f62;">#{</span><span class="token" style="color: #032f62;">days_until_expiration</span><span class="token" style="color: #032f62;">}</span><span class="token" style="color: #032f62;"> days.
</span></span><span class="line"><span class="token" style="color: #032f62;">      Please update your billing information.
</span></span><span class="line"><span class="token" style="color: #032f62;">    HEREDOC</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-275"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-273">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-274'
	>
	Unfortunately, the string inside the heredoc is going to be output with 6 leading spaces, and so far that’s <strong>never</strong> been the expected behavior for me:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-277"
	 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;">text</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #6f42c1;">Subscription</span><span class="token"> </span><span class="token" style="color: #032f62;">expiring</span><span class="token"> </span><span class="token" style="color: #032f62;">soon!</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #6f42c1;">Your</span><span class="token"> </span><span class="token" style="color: #032f62;">free</span><span class="token"> </span><span class="token" style="color: #032f62;">trial</span><span class="token"> </span><span class="token" style="color: #032f62;">will</span><span class="token"> </span><span class="token" style="color: #032f62;">expire</span><span class="token"> </span><span class="token" style="color: #032f62;">in</span><span class="token"> </span><span class="token" style="color: #005cc5;">5</span><span class="token"> </span><span class="token" style="color: #032f62;">days.</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #6f42c1;">Please</span><span class="token"> </span><span class="token" style="color: #032f62;">update</span><span class="token"> </span><span class="token" style="color: #032f62;">your</span><span class="token"> </span><span class="token" style="color: #032f62;">billing</span><span class="token"> </span><span class="token" style="color: #032f62;">information.</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-280"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-278">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-279'
	>
	One solution for this would be to indent the string to the left margin, but that leaves our code looking <strong>really ugly and badly indented</strong>:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-282"
	 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;">Subscription</span><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;">warning_message</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #032f62;">&lt;&lt;-HEREDOC</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #032f62;">Subscription expiring soon!
</span></span><span class="line"><span class="token" style="color: #032f62;">Your free trial will expire in </span><span class="token" style="color: #032f62;">#{</span><span class="token" style="color: #032f62;">days_until_expiration</span><span class="token" style="color: #032f62;">}</span><span class="token" style="color: #032f62;"> days.
</span></span><span class="line"><span class="token" style="color: #032f62;">Please update your billing information.
</span></span><span class="line"><span class="token" style="color: #032f62;">    HEREDOC</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-285"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-283">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-284'
	>
	Other ways like removing multiple leading whitespace characters with <code>#gsub</code>, appending multiple strings to each other and so on can be found in the above mentioned Stack Overflow post. There isn’t a nice way to do this in pure Ruby, however Rails does have a ’patch’ to support this behavior with the <a href="http://apidock.com/rails/String/strip_heredoc">#strip_heredoc</a> method, but it’s one method call too much to support a simple behavior like this.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-288"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-286">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-287'
	>
	Meet the squiggly heredoc</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-291"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-289">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-290'
	>
	Besides numerous new features in Ruby 2.3, such as the safe navigation operator or <code>Hash#dig</code> (read more about new features in Ruby 2.3 in <a href="http://nithinbekal.com/posts/ruby-2-3-features/">this post</a>), there will be a new and improved HEREDOC syntax called the <strong>squiggly HEREDOC</strong> that does what I’ve always expected the regular HEREDOC syntax to do &#8211; <strong>it strips the leading whitespace</strong> (similar to the <code>#strip_heredoc</code> method in Rails)</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-paragraph" data-id="es-292">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-293'
	>
	It looks quite similar to HEREDOC, except instead of writing <code>&lt;&lt;-HEREDOC</code>, you will substitute the hyphen with a <strong>tilda</strong>: <code>&lt;&lt;~HEREDOC</code>.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-296">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2017/02/multiline-strings-ruby-2-3-0-the-squiggly-heredoc-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="488"
															width="728"
										loading="lazy"
					 />
					</picture>

	</figure></div></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'
	>
	We can finally write our multiline strings in a nice manner with a minimal change (squint hard, you can barely notice it):</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-302"
	 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;">Subscription</span><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;">warning_message</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #032f62;">&lt;&lt;~HEREDOC</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #032f62;">      Subscription expiring soon!
</span></span><span class="line"><span class="token" style="color: #032f62;">      Your free trial will expire in </span><span class="token" style="color: #032f62;">#{</span><span class="token" style="color: #032f62;">days_until_expiration</span><span class="token" style="color: #032f62;">}</span><span class="token" style="color: #032f62;"> days.
</span></span><span class="line"><span class="token" style="color: #032f62;">      Please update your billing information.
</span></span><span class="line"><span class="token" style="color: #032f62;">    HEREDOC</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-305"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-303">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-304'
	>
	The rule for stripping enough whitespace:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-307"
	 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;">The</span><span class="token"> </span><span class="token" style="color: #032f62;">indentation</span><span class="token"> </span><span class="token" style="color: #032f62;">of</span><span class="token"> </span><span class="token" style="color: #032f62;">the</span><span class="token"> </span><span class="token" style="color: #032f62;">least-indented</span><span class="token"> </span><span class="token" style="color: #032f62;">line</span><span class="token"> </span><span class="token" style="color: #032f62;">will</span><span class="token"> </span><span class="token" style="color: #032f62;">be</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #6f42c1;">removed</span><span class="token"> </span><span class="token" style="color: #032f62;">from</span><span class="token"> </span><span class="token" style="color: #032f62;">each</span><span class="token"> </span><span class="token" style="color: #032f62;">line</span><span class="token"> </span><span class="token" style="color: #032f62;">of</span><span class="token"> </span><span class="token" style="color: #032f62;">the</span><span class="token"> </span><span class="token" style="color: #032f62;">content.</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-310"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-308">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-309'
	>
	This feature was <a href="https://bugs.ruby-lang.org/issues/9098">suggested</a> by <a href="https://twitter.com/sikachu">Sikachu</a> 2 years ago, merged to Ruby on December 7th, and you can read more about it in this <a href="https://github.com/ruby/ruby/pull/878">pull request</a> by <a href="https://twitter.com/bjmllr">Ben Miller</a> and this <a href="https://github.com/ruby/ruby/commit/9a28a29b870b5f45d370bc8f16c431b435f0bbb3">commit</a> by <a href="https://www.youtube.com/watch?v=yqyIi0pwRO4">Nobu</a>, the mysterious No. 1 committer to the Ruby core.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-313"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-311">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-312'
	>
	You can check out all the new features in Ruby 2.3 by installing <code>ruby 2.3.0preview2</code>, or simply wait until Christmas when the new official minor version will be released.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/multiline-strings-ruby-2-3-0-the-squiggly-heredoc/">Multiline Strings in Ruby 2.3  the Squiggly Heredoc</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>8020https://infinum.com/uploads/2017/02/tips-for-participating-in-the-rails-rumble-0.webp</url>
				</image>
				<title>Tips for Participating in the Rails Rumble</title>
				<link>https://infinum.com/blog/tips-for-participating-in-the-rails-rumble/</link>
				<pubDate>Tue, 18 Aug 2015 09:00:00 +0000</pubDate>
				<dc:creator>Damir Svrtan</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/tips-for-participating-in-the-rails-rumble/</guid>
				<description>
					<![CDATA[<p>Rails Rumble is the biggest international Rails hackathon; over 500 teams from across the globe, four members fabricating an awesome Rails app in 48 hours. </p>
<p>The post <a href="https://infinum.com/blog/tips-for-participating-in-the-rails-rumble/">Tips for Participating in the Rails Rumble</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-446"
	 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-316">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-319"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-317">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-318'
	>
	The Rails Rumble is the biggest international Rails hackathon and it’s organized once a year – over 500 teams distributed across the globe, each with 4 members fabricating an awesome Rails app in 48 hours. The best part is that everyone can join, everybody’s in it for the fun. The next one is on the 7th and 8th of November!</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-322"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-320">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-321'
	>
	Last year, the three of us from Infinum entered the Rails Rumble for the first time. We had no troubles coming up with the idea of what to create – at that time we were in between switching our apps from MySQL to Postgres and were having problems finding a slick desktop client for Postgres. We got spoiled by using <a href="https://github.com/sequelpro/sequelpro">SequelPro</a> for MySQL and the Postgres alternatives weren’t as nearly as nice.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-325"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-323">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-324'
	>
	Since this was a Rails hackathon, we decided to create a Postgres manipulation client built as a Rails engine. We called it <a href="https://github.com/pg-pancakes/pancakes">Pancakes</a>. Since we’ve managed to learn a lot from the whole experience, here are some protips to help you perform best on the big day.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-328"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-326">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-327'
	>
	Do as much planning as you can before the hackathon</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-331"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-329">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-330'
	>
	One of the few things you are allowed to do before the hackathon is to agree on an idea. The four of us had met at a bar 2 days before the hackathon to decide what we would do. However, we hadn’t completely ironed-out the implementation and we felt this during the hackathon.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-334"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-332">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-333'
	>
	Try to do the architecture of the whole system before the beginning; write user scenarios, draw up a class diagram or an ER diagram of your database – the only rule is that you don’t write any code before Saturday!</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-337"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-335">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-336'
	>
	Once you start rumbling, it’s easy to take a whiteboard to list and assign all tasks:</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-339">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2017/02/tips-for-participating-in-the-rails-rumble-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="750"
															width="1000"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			 Our rumble whiteboard		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-343"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-341">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-342'
	>
	Organize your time!</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-346"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-344">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-345'
	>
	The Rails Rumble starts on Saturday at 00:00 UTC and finishes exactly 48 hours later. We live in Zagreb (UTC+2), so that means we could’ve started on Saturday at 2 am, but we decided to start with the hackathon 4 hours later – somewhere around 6 am. Even though that made the hackathon 4 hours shorter for us from the beginning, at least we got a good night’s sleep and kicked the first day off quite fresh. I think I’ll let myself sleep until 8 am for the next one and be even fresher.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-349"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-347">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-348'
	>
	Meet in one place and dress like you’re at home</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-352"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-350">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-351'
	>
	We decided to meet at our office and hack our way through 48 hours from there. It’s really better for everyone to be in one place to share ideas and have fun together.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-355"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-353">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-354'
	>
	Another recommendation would be to dress like you’re at home – bring your sweats and some comfy shirts – no one wants to wear jeans for 48 hours.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-357">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2017/02/tips-for-participating-in-the-rails-rumble-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="750"
															width="1000"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			 Our hackathon arrangement in the office		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-361"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-359">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-360'
	>
	Time for camping</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-364"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-362">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-363'
	>
	One other thing we did that helped minimize time wasting and keep the team morale high was sleeping at our office. If we had went home, we would have lost at least 4 hours more to regroup back at the office and risked more outside distractions.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-367"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-365">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-366'
	>
	Thinking back, it’s a good idea to make your sleep as comfy as possible. If you have couches in your office – bring your own pillow and blanket. If not, maybe bring/borrow a sleeping bag and a sleeping pad (the thingie you put under the bag to put something between the bag and the floor). Did someone mention camping?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-370"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-368">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-369'
	>
	Install all of your prerequisites before Saturday</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-373"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-371">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-372'
	>
	Before entering the Rumble, agree with the rest of your teammates on the versions of Ruby and Rails you’re going to use. In reality it doesn’t matter which versions you use, just pick some and send an email saying: `We’re going to use Ruby 2.2.3 and Rails 4.2.3, please install it’. We had some short debugging sessions while using different minor versions of Ruby inside the team. If you could skip that, it would be awesome.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-376"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-374">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-375'
	>
	Also, agree on which database you’re going to use, and make sure everybody has it installed. Same goes for extra services such as Elasticsearch, Redis or whatever. You don’t want somebody wasting time during the hackathon.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-379"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-377">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-378'
	>
	Don’t go big! / Less is more</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-382"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-380">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-381'
	>
	Try to create a minimalistic app with only a few basic features and do them really well – it’s better to create an app with one or two impressive features than have 10 sloppy features.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-385"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-383">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-384'
	>
	Participants are also the jury and every participant needs to go through all the applications and judge them – no one has the time to check out dozens of features. If you finish before the deadline, it’s better to polish your UX than to add extra functions.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-388"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-386">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-387'
	>
	Also, try to make your app understandable to everyone. If you can’t pitch it in a sentence or two on your homepage, it’s probably too complicated and no one will have the time to try to figure out what it does.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-391"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-389">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-390'
	>
	Bring a designer</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-394"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-392">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-393'
	>
	To be honest, no one wants to see an app that’s designed by a Rails developer, and you’re more likely to create a better app with a really good designer. Although the hackathon is called the Rails Rumble, you’ll probably be better off with a good design than with a clean codebase. Check out the awesome design from last year’s winners:</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-396">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2017/02/tips-for-participating-in-the-rails-rumble-3.webp"
					class="image__img block-media__image-img"
					alt=""
										height="497"
															width="1000"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			 Awesomely designed refactorcop		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-400"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-398">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-399'
	>
	Besides designing the system’s architecture, you can have your design finished before the hackathon begins. That will also force you to keep track of all of your goals.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-402">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2017/02/tips-for-participating-in-the-rails-rumble-4.webp"
					class="image__img block-media__image-img"
					alt=""
										height="425"
															width="961"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			 Pancakes interface		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-406"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-404">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-405'
	>
	Bring a front-end developer</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-409"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-407">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-408'
	>
	Once again, despite the event name, you’ll probably be better off with a good front-end developer than a back-end developer hacking through your CSS. In most cases, the first will be faster and better.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-412"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-410">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-411'
	>
	Since we did an app with a heavy back end, we thought it would be okay for all of us to be Rails developers. In the end, we would’ve been faster if we had had a front-end developer.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-415"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-413">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-414'
	>
	Deploy often!</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-418"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-416">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-417'
	>
	Two rules:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-422"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--number bullet__color--black block-bullet__bullet" data-id="es-419">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-420'
	>
	1</p>	<div class="bullet__content">
		<p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-421'
	>
	<strong>Don’t wait with your first deploy until the last hour</strong> &#8211; we deployed everything at the end of the first day and ended up with a debugging session. You don&#8217;t want that to happen in the last hour when everybody gets jumpy.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-426"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--number bullet__color--black block-bullet__bullet" data-id="es-423">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-424'
	>
	2</p>	<div class="bullet__content">
		<p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-425'
	>
	<strong><strong>Don’t deploy anything last minute</strong></strong> &#8211; try to leave at least 10 or even 15 minutes to fix the deploy if something goes wrong. ANY submissions after 23:59UTC Sunday will result in a direct disqualification.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-429"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-427">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-428'
	>
	Create a chat room for sharing links</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-432"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-430">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-431'
	>
	We created a slack organization (it’s free) and it was really useful:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-435"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-433">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-434'
	>
	<li>easy way to share links between ourselves</li><li>we added hooks to get notified when we deploy</li><li>we added hooks to get notified when someone pushes to the Github repo</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-438"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-436">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-437'
	>
	Don’t take yourself too seriously</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-441"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-439">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-440'
	>
	The three of us remember this as an excellent experience and still tell stories from those two days – tired dementia conversations, weird stuff going on when hyped on Red Bulls and what not. We’ve bonded more than before and just had pure, clean fun.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-444"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-442">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-443'
	>
	Lastly, take a day off on Monday – you’re gonna need it ?</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/tips-for-participating-in-the-rails-rumble/">Tips for Participating in the Rails Rumble</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>7979https://infinum.com/uploads/2015/07/best-ruby-on-rails-refactoring-talks-0.webp</url>
				</image>
				<title>Best Ruby On Rails Refactoring Talks</title>
				<link>https://infinum.com/blog/best-ruby-on-rails-refactoring-talks/</link>
				<pubDate>Tue, 21 Jul 2015 12:15:00 +0000</pubDate>
				<dc:creator>Damir Svrtan</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/best-ruby-on-rails-refactoring-talks/</guid>
				<description>
					<![CDATA[<p>Refactoring is the craft of improving the design of an existing code without changing its external behavior. </p>
<p>The post <a href="https://infinum.com/blog/best-ruby-on-rails-refactoring-talks/">Best Ruby On Rails Refactoring Talks</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-512"
	 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-447">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-450"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-448">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-449'
	>
	Refactoring is the craft of improving the design of an existing code without changing its external behavior. Just like with everything else, you get better at it with practice and continuous learning.<br>Check out a couple of talks given by some of the best Ruby developers that point out common mistakes and how to deal with them.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-453"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-451">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-452'
	>
	I’ve curated five of my favorite talks on code refactoring taking into consideration the information presented, the quality of examples and the quality of the presentation itself.<br>Some of the talks are closely tied to Ruby on Rails, but most refactoring techniques are often language agnostic, so even if you’re not in the Ruby world, don’t hesitate to watch them.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-455">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2015/07/best-ruby-on-rails-refactoring-talks-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="881"
															width="1400"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-459"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-457">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-458'
	>
	Sandi Metz – <a href="https://www.youtube.com/watch?v=9lv2lBq6x4A">Nothing is something</a></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-462"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-460">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-461'
	>
	Sandi Metz gave this talk at multiple conferences this year and it gained a lot of traction – and for a reason – it’s awesome! The first half of the talk is more oriented on her animosity towards conditionals, the dirtiness of nil checks and advocating the use of the Null Object pattern.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-465"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-463">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-464'
	>
	The second part is a real life example of the misleading usage of inheritance (used for shared behavior instead of specialization) and a step-by-step explanation on how to refactor the given code using composition with dependency injection.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-468"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-466">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-467'
	>
	If you like this talk, be sure to check out Sandi’s <a href="https://www.youtube.com/watch?v=8bZh5LMaSmE">All the little things</a> from Railsconf 2014, where Sandi explains on a real world example how to thoroughly refactor a stale and procedural code.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-471"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-469">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-470'
	>
	Bryan Helmkamp – <a href="https://www.youtube.com/watch?v=5yX6ADjyqyE">Refactoring Fat Models with Patterns</a></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-474"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-472">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-473'
	>
	Bryan Helmkamp, the CEO of <a href="https://codeclimate.com">Code Climate</a>, gave this talk at the Ruby Conference in 2013, where he explained how to run from the methodology of Thin Controllers, Fat Models and presented other options such as Form Objects, Service Objects, Decorators, etc. There is also an <a href="http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/">associated blogpost</a> if you’re not up for watching the video.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-477"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-475">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-476'
	>
	There are some gems that Bryan doesn’t mention that can come quite in handy when implementing these patterns in Rails:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-480"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-478">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-479'
	>
	<li>Form Objects – <a href="https://github.com/apotonick/reform">Reform</a></li><li>Service Objects – <a href="https://github.com/collectiveidea/interactor">Interactor</a></li><li>Decorators – <a href="https://github.com/drapergem/draper">Draper</a></li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-483"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-481">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-482'
	>
	Ben Orenstein – <a href="https://www.youtube.com/watch?v=DC-pQPq0acs">Refactoring from Good to Great</a></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-486"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-484">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-485'
	>
	<a href="https://thoughtbot.com">Thoughtbot</a>’s Ben Orenstein kicked ass with this talk at the <a href="https://twitter.com/aloharubyconf">Aloha Ruby Conf</a> in 2012. If you want to know the basics of patterns such as the single responsibility principle, the <a href="https://robots.thoughtbot.com/tell-dont-ask">tell don’t ask principle</a>, the null object pattern or anti-patterns like Shotgun surgery, this is the talk for you.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-489"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-487">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-488'
	>
	Avdi Grimm – <a href="https://www.youtube.com/watch?v=T8J0j2xJFgQ">Confident Code</a></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-492"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-490">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-491'
	>
	This is a talk that Avdi Grimm gave back in 2011 at <a href="http://www.rubymidwest.com/">Ruby Midwest</a>. It’s an excellent talk on how to construct methods and separate them into 4 parts:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-495"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-493">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-494'
	>
	<li>gather input,</li><li>perform work,</li><li>deliver results,</li><li>handle failures.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-498"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-496">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-497'
	>
	There are examples of each part of a method, common mistakes that are usually made and how to fix them: embracing duck typing instead of using class checks, refactoring case equality statements with type coercion, using Hash#fetch for easier debugging, the Black Hole NilObject Pattern, etc.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-501"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-499">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-500'
	>
	If you want to find out more about the stuff he’s been talking about beyond this video, check out his book called Confident Ruby.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-504"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-502">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-503'
	>
	Aja Hammerly – <a href="https://www.youtube.com/watch?v=Oxd_DBuX8R8">N design patterns you might actually use</a></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-507"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-505">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-506'
	>
	Knowing your design patterns is the mother of all refactoring. Aja talks about design patterns you might actually use in Ruby. She goes fast through the examples in a sarcastic manner and wastes no time covering the following patterns: template, strategy, composite, command and decorators. For each, she gives real world examples and hands out code snippets.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-510"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-508">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-509'
	>
	She mentions how the <a href="https://www.wikiwand.com/en/Design_Patterns">Gang Of Four book</a> is always lying around her office and recommends Rubyists to read a more applicable <a href="http://designpatternsinruby.com/">book on design patterns</a> by Russ Olsen. <a href="https://twitter.com/dougyun">Doug Yun</a> from Dockyard covered most of them well in a <a href="https://dockyard.com/blog/authors/doug-yun">series of blog posts on design patterns</a>.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/best-ruby-on-rails-refactoring-talks/">Best Ruby On Rails Refactoring Talks</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>8115https://infinum.com/uploads/2014/09/top-8-tools-for-ruby-on-rails-code-optimization-and-cleanup-0.webp</url>
				</image>
				<title>Top 8 Tools for Ruby on Rails Code Optimization and Cleanup</title>
				<link>https://infinum.com/blog/top-8-tools-for-ruby-on-rails-code-optimization-and-cleanup/</link>
				<pubDate>Mon, 06 Oct 2014 00:52:00 +0000</pubDate>
				<dc:creator>Damir Svrtan</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/top-8-tools-for-ruby-on-rails-code-optimization-and-cleanup/</guid>
				<description>
					<![CDATA[<p>Keeping your code clean and organized while developing a large Rails application can be quite a challenge, even for an experienced developer. </p>
<p>The post <a href="https://infinum.com/blog/top-8-tools-for-ruby-on-rails-code-optimization-and-cleanup/">Top 8 Tools for Ruby on Rails Code Optimization and Cleanup</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-638"
	 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-513">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-516"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-514">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-515'
	>
	Keeping your code clean and organized while developing a large Rails application can be quite a challenge, even for an experienced developer. Fortunately, there is a whole category of gems that make this job much easier.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-519"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-517">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-518'
	>
	For most people, <a href="http://en.wikipedia.org/wiki/Dead_code">dead</a>/inefficient code will build up over time. Others will find themselves in a similar predicament when they take over someone else’s project.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-522"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-520">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-521'
	>
	Actually, my own experience with code cleaning/polishing gems stems from having to optimize someone else’s Rails application. Considering its size and complexity, manual code refactoring was bound to be tedious and time consuming, so I decided to help myself as much I could with third-party tools.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-525"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-523">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-524'
	>
	<strong>If you want to keep your code maintainable, secure and optimized, take a look at some gems that have been doing the job for me:</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-528"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-526">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-527'
	>
	<li><a href="#traceroute">traceroute</a></li><li><a href="#rack-mini-profiler">rack-mini-profiler</a></li><li><a href="#Bullet">Bullet</a></li><li><a href="#brakeman">brakeman</a></li><li><a href="#deadweight">deadweight</a></li><li><a href="#rails-best-practices">rails best practices</a></li><li><a href="#rubocop">rubocop</a></li><li><a href="#rubycritic">rubycritic</a></li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-531"
	 data-animation='slideFade' data-animation-target='inner-items'>
				<div class="wrapper__anchor" id="traceroute"></div>
	
			<div class="block-heading" data-id="es-529">
	<h2	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-530'
	>
	<a href="https://github.com/amatsuda/traceroute">Traceroute</a></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-534"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-532">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-533'
	>
	Traceroute is a route cleaning tool for Rails applications. It provides a simple rake task for checking which routes are mapped to non existing controller actions, and finds out which controller actions are not reachable.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-537"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-535">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-536'
	>
	You will also be required to keep your controller helper methods and various before/after filters private, since they shouldn’t be a part of the public API. It sometimes has problems with showing false positives on mountable engines, but they can be easily overlooked.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-539">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/09/top-8-tools-for-ruby-on-rails-code-optimization-and-cleanup-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="401"
															width="320"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-543"
	 data-animation='slideFade' data-animation-target='inner-items'>
				<div class="wrapper__anchor" id="rack-mini-profiler"></div>
	
			<div class="block-heading" data-id="es-541">
	<h2	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-542'
	>
	<a href="https://github.com/MiniProfiler/rack-mini-profiler">rack-mini-profiler</a></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-546"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-544">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-545'
	>
	This is a nice tool used for finding bottlenecks of your applications. It does a live speed analysis of how long it took for the request to be processed and how much of that time it was doing various renderings, database queries and DOM loading. Just plug it into your Gemfile and you’ll get a small window in the upper left corner of your page, showing you all of these information.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-548">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/09/top-8-tools-for-ruby-on-rails-code-optimization-and-cleanup-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="300"
															width="503"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-552"
	 data-animation='slideFade' data-animation-target='inner-items'>
				<div class="wrapper__anchor" id="Bullet"></div>
	
			<div class="block-heading" data-id="es-550">
	<h2	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-551'
	>
	<a href="https://github.com/flyerhzm/bullet">Bullet</a></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-555"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-553">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-554'
	>
	This one particularly blew my mind. The bullet gem helps you kill all the N+1 queries, as well as unnecessarily eager loaded relations. Once you install it and start visiting various routes in development, alert boxes with warnings indicating database queries that need to be optimized will pop out. It works right out of the box and is extremely helpful for optimizing your application.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-557">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/09/top-8-tools-for-ruby-on-rails-code-optimization-and-cleanup-3.webp"
					class="image__img block-media__image-img"
					alt=""
										height="216"
															width="472"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-561"
	 data-animation='slideFade' data-animation-target='inner-items'>
				<div class="wrapper__anchor" id="brakeman"></div>
	
			<div class="block-heading" data-id="es-559">
	<h2	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-560'
	>
	<a href="https://github.com/presidentbeef/brakeman">Brakeman</a></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-564"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-562">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-563'
	>
	A security analysis tool for your Rails applications. It scans through your application and outputs a nicely formatted table of possible vulnerabilities. Security warnings are grouped according to their severity (High, Medium and Low). You can learn more about their meanings on <a href="http://brakemanscanner.org/docs/warning_types/">brakeman’s list of warnings</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-567"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-565">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-566'
	>
	Note that even if you end up not having any warnings, it doesn’t mean that your app is secure, since brakeman sometimes overlooks some basic security pitfalls.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-569">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/09/top-8-tools-for-ruby-on-rails-code-optimization-and-cleanup-4.webp"
					class="image__img block-media__image-img"
					alt=""
										height="392"
															width="1156"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-573"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-571">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-572'
	>
	Security-wise, there is also a gem called <a href="https://github.com/rubysec/bundler-audit#readme">bundler-audit</a>, used for checking vulnerable versions of gems in your Gemfile.lock.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-576"
	 data-animation='slideFade' data-animation-target='inner-items'>
				<div class="wrapper__anchor" id="deadweight"></div>
	
			<div class="block-heading" data-id="es-574">
	<h2	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-575'
	>
	<a href="https://github.com/aanand/deadweight">Deadweight</a></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-579"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-577">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-578'
	>
	Deadweight is used for cleaning unused CSS selectors. You have to hand out a set of your application’s style sheets and HTML pages, and it will report which CSS selectors are safe to remove.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-582"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-580">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-581'
	>
	The gem won’t work out of the box in Rails, since most pages have dynamic content, but Jason Morrison from Thoughtbot wrote a <a href="http://robots.thoughtbot.com/use-deadweight-and-your-integration-suite-to">blog post</a> on how to create a Rack Middleware and integrate it into your test suite to collect all the HTML content in one place.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-585"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-583">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-584'
	>
	If you’re using precompilers such as Sass or Less, you should compile all of your style sheets and hand them out as simple CSS files to the deadweight task. It is recommended that you remove all the vendor/third-party css files (such as Bootstrap files and similar) since they will end up clogging your output.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-587">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/09/top-8-tools-for-ruby-on-rails-code-optimization-and-cleanup-5.webp"
					class="image__img block-media__image-img"
					alt=""
										height="319"
															width="813"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-591"
	 data-animation='slideFade' data-animation-target='inner-items'>
				<div class="wrapper__anchor" id="rails-best-practices"></div>
	
			<div class="block-heading" data-id="es-589">
	<h2	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-590'
	>
	<a href="https://github.com/flyerhzm/rails-bestpractices.com">Rails best practices</a></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-594"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-592">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-593'
	>
	Static code analyzer for finding Rails specific <a href="http://en.wikipedia.org/wiki/Code_smell">code smells</a>. It offers a variety of suggestions; use scope access, restrict auto-generated routes, add database indexes, etc. For a full list of suggestions, check out the rails-best-pratices <a href="https://rails-bestpractices.com/">official page</a>.<br />
Unfortunately, sometimes it reports lots of false positives, such as unused methods. Nevertheless, it contains lots of nice suggestions that will give you a better perspective on how to refactor your code and learn some best practices.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-596">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/09/top-8-tools-for-ruby-on-rails-code-optimization-and-cleanup-6.webp"
					class="image__img block-media__image-img"
					alt=""
										height="186"
															width="668"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-600"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-598">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-599'
	>
	If you like the suggestions that rails best practices gives, you also might find <a href="http://robots.thoughtbot.com/sandi-metz-rules-for-developers">Sandi Metz’s rules for developers</a> quite interesting. You can check if your code complies to Sandi’s standards with the <a href="https://github.com/makaroni4/sandi_meter">sandi_meter</a> gem.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-603"
	 data-animation='slideFade' data-animation-target='inner-items'>
				<div class="wrapper__anchor" id="rubocop"></div>
	
			<div class="block-heading" data-id="es-601">
	<h2	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-602'
	>
	<a href="https://github.com/bbatsov/rubocop#cops">Rubocop</a></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-606"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-604">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-605'
	>
	A Ruby static code analyzer which you can use to check if your code complies with the <a href="https://github.com/bbatsov/ruby-style-guide">Ruby community code guidelines</a>. The gem reports style violations through the command line, with lots of useful code refactoring goodies such as <em>useless variable assignment</em>, <em>redundant use of Object#to_s in interpolation</em> or even <em>unused method argument</em>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-609"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-607">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-608'
	>
	A good thing is that it’s highly configurable, since the analyzer can be quite irritating if you’re not following the Ruby style guide 100% (i.e. you have lots of trailing whitespaces or you double quote your strings even when not interpolating, etc.).</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-612"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-610">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-611'
	>
	It’s divided into 4 sub-analyzers (called cops): Style, Lint, Metrics and Rails. You can define which cops to use, as well as which files to exclude/include and tweak various other configuration options in a .rubocop.yml file.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-614">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/09/top-8-tools-for-ruby-on-rails-code-optimization-and-cleanup-7.webp"
					class="image__img block-media__image-img"
					alt=""
										height="468"
															width="682"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-618"
	 data-animation='slideFade' data-animation-target='inner-items'>
				<div class="wrapper__anchor" id="rubycritic"></div>
	
			<div class="block-heading" data-id="es-616">
	<h2	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-617'
	>
	<a href="https://github.com/whitesmith/rubycritic">Rubycritic</a></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-621"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-619">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-620'
	>
	A relatively new gem that wraps around three static analysis gems &#8211; <a href="https://github.com/troessner/reek">Reek</a> (ruby code smells), <a href="https://github.com/seattlerb/flay">Flay</a> (code duplication detection) and <a href="https://github.com/seattlerb/flog">Flog</a> (ABC metrics). It creates nicely structured HTML files so you can browse through your smelly code and start refactoring. Out of all of the mentioned static code analysis tools, because of it’s nice output, it’s most convenient to overview and comment with your colleagues.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-623">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/09/top-8-tools-for-ruby-on-rails-code-optimization-and-cleanup-8.webp"
					class="image__img block-media__image-img"
					alt=""
										height="474"
															width="745"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-627"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-625">
	<h2	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-626'
	>
	Conclusion</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-630"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-628">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-629'
	>
	If you’re working on an open source project or can afford to automate the process of running all of these static code analyzers on every commit, I would suggest using the <a href="https://codeclimate.com/">code climate</a> service. In case you decide to go down this route, I suggest reading <a href="https://infinum.com/blog/a-ruby-on-rails-continous-integration-process-using-semaphore-github-codeclimate-and-hipchat/">&#8220;A Ruby on Rails Continuous Integration process using Github, Semaphore, CodeClimate and HipChat&#8221;</a>, a blog post written by my colleague, Jan Varljen.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-633"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-631">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-632'
	>
	Most of the functionalities that the listed static code analyzers can offer you is already wrapped inside it. Besides code quality reports, there is an optional code coverage report (basically what <a href="https://github.com/colszowka/simplecov">simplecov</a> does).</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-636"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-634">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-635'
	>
	One thing to note is that you shouldn’t take each warning issued by these static code analyzers too seriously. Most of them will throw lots of stuff at you that you will probably never refactor because it will take you forever, and for some you just shouldn’t care (such as final newline missing or spruceing up your auto generated schema.rb). Sometimes they can generate lots of rubbish, but that can be prevented by doing code reviews on a regular basis and by tweaking their configuration options.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/top-8-tools-for-ruby-on-rails-code-optimization-and-cleanup/">Top 8 Tools for Ruby on Rails Code Optimization and Cleanup</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>8062https://infinum.com/uploads/2013/11/simple-ruby-on-rails-content-editing-0.webp</url>
				</image>
				<title>Simple Ruby on Rails Content Editing</title>
				<link>https://infinum.com/blog/simple-ruby-on-rails-content-editing/</link>
				<pubDate>Wed, 20 Nov 2013 06:34:00 +0000</pubDate>
				<dc:creator>Damir Svrtan</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/simple-ruby-on-rails-content-editing/</guid>
				<description>
					<![CDATA[<p>When your client asks for some copy editing on their website, does it take too much of your time? </p>
<p>The post <a href="https://infinum.com/blog/simple-ruby-on-rails-content-editing/">Simple Ruby on Rails Content Editing</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-710"
	 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-639">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-642"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-640">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-641'
	>
	When your client asks for some copy editing on their website, does it take too much of your time? Or maybe you’re the client and every time you ask your devs to change one sentence on your website, it takes them a week?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-645"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-643">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-644'
	>
	You’ve all probably been there – you’re creating a simple website, a couple of pages, mostly HTML and CSS, maybe a marketing site/one-pager for a product or service. You feel a full-fledged Ruby on Rails <a href="http://en.wikipedia.org/wiki/Content_management_system">Content management system</a> would be more of a distraction than it would provide real business value to the client, but manually editing the code is a waste of your time and money.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-648"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-646">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-647'
	>
	Phrasing</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-651"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-649">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-650'
	>
	Phrasing is an <strong>inline live content editing library</strong> that can be installed to any website so anyone can manage content and get a preview of what those changes will look like in real time.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-654"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-652">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-653'
	>
	Take a look at this short intro video below:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-657"
	 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-655"
	 data-media-type='embed'>

	<div class="embed block-media__embed" data-id=es-656>
	<iframe
		class="embed__iframe block-media__embed-iframe"
		src="https://www.youtube.com/embed/wOqzulEzNsY?vq=hd1080&#038;rel=0"
		frameborder="0"
		aria-label="Embed iframe"
		allow="autoplay; accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture;"
		allowfullscreen>
	</iframe>
</div></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-660"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-658">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-659'
	>
	The name <a href="http://infinum.github.io/phrasing/">Phrasing</a> originated from <a href="http://www.youtube.com/watch?v=hyLWrKh2fB0">Archer</a>, a popular animated comedy series. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-663"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-661">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-662'
	>
	We build all of our websites using <a href="http://rubyonrails.org/">Ruby on Rails</a>, so we created a gem to solve this problem. In the Ruby world, a <strong>gem</strong> is the name for a reusable library which can easily be installed to any application.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-666"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-664">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-665'
	>
	Getting started</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-669"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-667">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-668'
	>
	If you are thinking by now that a micro CMS does the same thing, you’re not far off.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-671">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2013/11/simple-ruby-on-rails-content-editing-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="433"
															width="744"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-675"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-673">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-674'
	>
	The gem is open sourced on <a href="http://github.com/infinum/phrasing">Github</a>, so anyone can use it. The setup process is very quick and straightforward &#8211; it shouldn’t take you more than 3 minutes to get it up and running.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-678"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-676">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-677'
	>
	After a short initial setup where you include some code and configure who will be able to edit phrases, you can start placing phrases all over your website. Just mark each editable region (phrase) with a key (such as <strong>post-title</strong> or <strong>about-us-description</strong>) in the HTML and set an initial value later.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-681"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-679">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-680'
	>
	Finally, you can show your client the website and enjoy them patting you on the back.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-684"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-682">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-683'
	>
	Features</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-687"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-685">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-686'
	>
	There’s a floating status window in the bottom right corner of the web page. Here you can track whether all the changes you’ve made are saved, and also switch from <strong>edit mode</strong> to <strong>read-only mode</strong>. The read-only mode shows you what the page looks like to a regular user.</p></div>	</div>

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

	<figure class="image block-media__image-figure image--size-auto" data-id="es-689">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2013/11/simple-ruby-on-rails-content-editing-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="290"
															width="181"
										loading="lazy"
					 />
					</picture>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-693"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-691">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-692'
	>
	Other features</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-696"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-694">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-695'
	>
	Alongside the basics I describe here, Phrasing has a couple of other features:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-699"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-697">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-698'
	>
	<li>A flexible authorization system</li><li>Internationalization and localization support</li><li>Inline editing of any attribute from any database table (this is pretty cool, check it out)</li><li>Download all the phrases for offline editing and upload them afterwards</li><li>Handling security issues</li><li>Phrase versioning</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-702"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-700">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-701'
	>
	Happy ending (Phrasing!)</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-705"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-703">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-704'
	>
	Since Phrasing is built on two other libraries called <a href="https://github.com/Zorros/copycat">Copycat</a> and <a href="http://www.zenpen.io/">ZenPen</a>, I want to thank all of the authors and contributors of both libraries for making them awesome, well documented and open sourced!</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-708"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-706">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-707'
	>
	If you are interested in using the Phrasing gem in your own application, just <a href="http://infinum.github.io/phrasing/">follow the instructions on this page</a>. In a couple of minutes, your clients will be able to edit content, and you can get back to doing productive work.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/simple-ruby-on-rails-content-editing/">Simple Ruby on Rails Content Editing</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
		
	</channel>
</rss>