<?xml version="1.0" encoding="utf-8"?>
    <feed xmlns="http://www.w3.org/2005/Atom">
     <title>BigBinary Blog</title>
     <link href="https://www.bigbinary.com/feed.xml" rel="self"/>
     <link href="https://www.bigbinary.com/"/>
     <updated>2026-03-06T03:08:00+00:00</updated>
     <id>https://www.bigbinary.com/</id>
     <entry>
       <title><![CDATA[Recyclable cache keys in Rails]]></title>
       <author><name>Taha Husain</name></author>
      <link href="https://www.bigbinary.com/blog/rails-adds-support-for-recyclable-cache-keys"/>
      <updated>2019-08-06T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-adds-support-for-recyclable-cache-keys</id>
      <content type="html"><![CDATA[<p><a href="https://github.com/rails/rails/pull/29092">Recyclable cache keys</a> or <em>cacheversioning</em> was introduced in Rails 5.2. Large applications frequently need toinvalidate their cache because cache store has limited memory. We can optimizecache storage and minimize cache miss using recyclable cache keys.</p><p>Recyclable cache keys is supported by all<a href="https://guides.rubyonrails.org/caching_with_rails.html#cache-stores">cache stores</a>that ship with Rails.</p><p>Before Rails 5.2, <code>cache_key</code>'s format was <em>{model_name}/{id}-{update_at}</em>. Here<code>model_name</code> and <code>id</code> are always constant for an object and <code>updated_at</code> changeson every update.</p><h4>Rails 5.1</h4><pre><code class="language-ruby">&gt;&gt; post = Post.last&gt;&gt; post.cache_key=&gt; &quot;posts/1-20190522104553296111&quot;# Update post&gt;&gt; post.touch&gt;&gt; post.cache_key=&gt; &quot;posts/1-20190525102103422069&quot; # cache_key changed</code></pre><p>In Rails 5.2, <code>#cache_key</code> returns <em>{model_name}/{id}</em> and new method<code>#cache_version</code> returns <em>{updated_at}</em>.</p><h4>Rails 5.2</h4><pre><code class="language-ruby">&gt;&gt; ActiveRecord::Base.cache_versioning = true&gt;&gt; post = Post.last&gt;&gt; post.cache_key=&gt; &quot;posts/1&quot;&gt;&gt; post.cache_version=&gt; &quot;20190522070715422750&quot;&gt;&gt; post.cache_key_with_version=&gt; &quot;posts/1-20190522070715422750&quot;</code></pre><p>Let's update <code>post</code> instance and check <code>cache_key</code> and <code>cache_version</code>'sbehaviour.</p><pre><code class="language-ruby">&gt;&gt; post.touch&gt;&gt; post.cache_key=&gt; &quot;posts/1&quot; # cache_key remains same&gt;&gt; post.cache_version=&gt; &quot;20190527062249879829&quot; # cache_version changed</code></pre><p>To use cache versioning feature, we have to enable<code>ActiveRecord::Base.cache_versioning</code> configuration. By default<code>cache_versioning</code> config is set to false for backward compatibility.</p><p>We can enable cache versioning configuration globally as shown below.</p><pre><code class="language-ruby">ActiveRecord::Base.cache_versioning = true# orconfig.active_record.cache_versioning = true</code></pre><p>Cache versioning config can be applied at model level.</p><pre><code class="language-ruby">class Post &lt; ActiveRecord::Base  self.cache_versioning = trueend# Or, when setting `#cache_versioning` outside the model -Post.cache_versioning = true</code></pre><p>Let's understand the problem step by step with cache keys before Rails 5.2.</p><h4>Rails 5.1 (without cache versioning)</h4><p><em>1. Write <code>post</code> instance to cache using<a href="https://apidock.com/rails/ActiveSupport/Cache/Store/fetch"><code>fetch</code></a> api.</em></p><pre><code class="language-ruby">&gt;&gt; before_update_cache_key = post.cache_key=&gt; &quot;posts/1-20190527062249879829&quot;&gt;&gt; Rails.cache.fetch(before_update_cache_key) { post }=&gt; #&lt;Post id: 1, title: &quot;First Post&quot;, created_at: &quot;2019-05-22 17:23:22&quot;, updated_at: &quot;2019-05-27 06:22:49&quot;&gt;</code></pre><p><em>2. Update <code>post</code> instance using<a href="https://apidock.com/rails/ActiveRecord/Persistence/touch"><code>touch</code></a>.</em></p><pre><code class="language-ruby">&gt;&gt; post.touch   (0.1ms)  begin transaction  Post Update (1.6ms)  UPDATE &quot;posts&quot; SET &quot;updated_at&quot; = ? WHERE &quot;posts&quot;.&quot;id&quot; = ?  [[&quot;updated_at&quot;, &quot;2019-05-27 08:01:52.975653&quot;], [&quot;id&quot;, 1]]   (1.2ms)  commit transaction=&gt; true</code></pre><p><em>3. Verify stale <code>cache_key</code> in cache store.</em></p><pre><code class="language-ruby">&gt;&gt; Rails.cache.fetch(before_update_cache_key)=&gt; #&lt;Post id: 1, title: &quot;First Post&quot;, created_at: &quot;2019-05-22 17:23:22&quot;, updated_at: &quot;2019-05-27 06:22:49&quot;&gt;</code></pre><p><em>4. Write updated <code>post</code> instance to cache using new <code>cache_key</code>.</em></p><pre><code class="language-ruby">&gt;&gt; after_update_cache_key = post.cache_key=&gt; &quot;posts/1-20190527080152975653&quot;&gt;&gt; Rails.cache.fetch(after_update_cache_key) { post }=&gt; #&lt;Post id: 1, title: &quot;First Post&quot;, created_at: &quot;2019-05-22 17:23:22&quot;, updated_at: &quot;2019-05-27 08:01:52&quot;&gt;</code></pre><p><em>5. Cache store now has two copies of <code>post</code> instance.</em></p><pre><code class="language-ruby">&gt;&gt; Rails.cache.fetch(before_update_cache_key)=&gt; #&lt;Post id: 1, title: &quot;First Post&quot;, created_at: &quot;2019-05-22 17:23:22&quot;, updated_at: &quot;2019-05-27 06:22:49&quot;&gt;&gt;&gt; Rails.cache.fetch(after_update_cache_key)=&gt; #&lt;Post id: 1, title: &quot;First Post&quot;, created_at: &quot;2019-05-22 17:23:22&quot;, updated_at: &quot;2019-05-27 08:01:52&quot;&gt;</code></pre><p><em>cache_key</em> and its associated instance becomes irrelevant as soon as aninstance is updated. But it stays in cache store until it is manuallyinvalidated.</p><p>This sometimes result in overflowing cache store with stale keys and data. Inapplications that extensively use cache store, a huge chunk of cache store getsfilled with stale data frequently.</p><p>Now let's take a look at the same example. This time with <em>cache versioning</em> tounderstand how recyclable cache keys help optimize cache storage.</p><h4>Rails 5.2 (cache versioning)</h4><p><em>1. Write <code>post</code> instance to cache store with <code>version</code> option.</em></p><pre><code class="language-ruby">&gt;&gt; ActiveRecord::Base.cache_versioning = true&gt;&gt; post = Post.last&gt;&gt; cache_key = post.cache_key=&gt; &quot;posts/1&quot;&gt;&gt; before_update_cache_version = post.cache_version=&gt; &quot;20190527080152975653&quot;&gt;&gt; Rails.cache.fetch(cache_key, version: before_update_cache_version) { post }=&gt; #&lt;Post id: 1, title: &quot;First Post&quot;, created_at: &quot;2019-05-22 17:23:22&quot;, updated_at: &quot;2019-05-27 08:01:52&quot;&gt;</code></pre><p><em>2. Update <code>post</code> instance.</em></p><pre><code class="language-ruby">&gt;&gt; post.touch   (0.1ms)  begin transaction  Post Update (0.4ms)  UPDATE &quot;posts&quot; SET &quot;updated_at&quot; = ? WHERE &quot;posts&quot;.&quot;id&quot; = ?  [[&quot;updated_at&quot;, &quot;2019-05-27 09:09:15.651029&quot;], [&quot;id&quot;, 1]]   (0.7ms)  commit transaction=&gt; true</code></pre><p><em>3. Verify stale <code>cache_version</code> in cache store.</em></p><pre><code class="language-ruby">&gt;&gt; Rails.cache.fetch(cache_key, version: before_update_cache_version)=&gt; #&lt;Post id: 1, title: &quot;First Post&quot;, created_at: &quot;2019-05-22 17:23:22&quot;, updated_at: &quot;2019-05-27 08:01:52&quot;&gt;</code></pre><p><em>4. Write updated <code>post</code> instance to cache.</em></p><pre><code class="language-ruby">&gt;&gt; after_update_cache_version = post.cache_version=&gt; &quot;20190527090915651029&quot;&gt;&gt; Rails.cache.fetch(cache_key, version: after_update_cache_version) { post }=&gt; #&lt;Post id: 1, title: &quot;First Post&quot;, created_at: &quot;2019-05-22 17:23:22&quot;, updated_at: &quot;2019-05-27 09:09:15&quot;&gt;</code></pre><p><em>5. Cache store has replaced old copy of <code>post</code> with new version automatically.</em></p><pre><code class="language-ruby">&gt;&gt; Rails.cache.fetch(cache_key, version: before_update_cache_version)=&gt; nil&gt;&gt; Rails.cache.fetch(cache_key, version: after_update_cache_version)=&gt; #&lt;Post id: 1, title: &quot;First Post&quot;, created_at: &quot;2019-05-22 17:23:22&quot;, updated_at: &quot;2019-05-27 09:09:15&quot;&gt;</code></pre><p>Above example shows how recyclable cache keys maintains single, latest copy ofan instance. Stale versions are removed automatically when new version is addedto cache store.</p><p><em>Rails 6</em> added <code>#cache_versioning</code> for <code>ActiveRecord::Relation</code>.</p><p><code>ActiveRecord::Base.collection_cache_versioning</code> configuration should be enabledto use cache versioning feature on collections. It is set to false by default.</p><p>We can enable this configuration as shown below.</p><pre><code class="language-ruby">ActiveRecord::Base.collection_cache_versioning = true# orconfig.active_record.collection_cache_versioning = true</code></pre><p>Before Rails 6, <code>ActiveRecord::Relation</code> had <code>cache_key</code> in format<code>{table_name}/query-{query-hash}-{count}-{max(updated_at)}</code>.</p><p>In Rails 6, cache_key is split in stable part <code>cache_key</code> -<code>{table_name}/query-{query-hash}</code> and volatile part <code>cache_version</code> -<code>{count}-{max(updated_at)}</code>.</p><p>For more information, check out<a href="https://blog.bigbinary.com/2016/02/02/activerecord-relation-cache-key.html">blog on ActiveRecord::Relation#cache_key in Rails 5</a>.</p><h4>Rails 5.2</h4><pre><code class="language-ruby">&gt;&gt; posts = Post.all&gt;&gt; posts.cache_key=&gt; &quot;posts/query-00644b6a00f2ed4b925407d06501c8fb-3-20190522172326885804&quot;</code></pre><h4>Rails 6</h4><pre><code class="language-ruby">&gt;&gt; ActiveRecord::Base.collection_cache_versioning = true&gt;&gt; posts = Post.all&gt;&gt; posts.cache_key=&gt; &quot;posts/query-00644b6a00f2ed4b925407d06501c8fb&quot;&gt;&gt; posts.cache_version=&gt; &quot;3-20190522172326885804&quot;</code></pre><p>Cache versioning works similarly for <code>ActiveRecord::Relation</code> as<code>ActiveRecord::Base</code>.</p><p>In case of <code>ActiveRecord::Relation</code>, if number of records change and/orrecord(s) are updated, then same <code>cache_key</code> is written to cache store with new<code>cache_version</code> and updated records.</p><h2>Conclusion</h2><p>Previously, cache invalidation had to be done manually either by deleting cacheor setting cache expire duration. Cache versioning invalidates stale dataautomatically and keeps latest copy of data, saving on storage and performancedrastically.</p><p>Check out the <a href="https://github.com/rails/rails/pull/29092">pull request</a> and<a href="https://github.com/rails/rails/commit/4f2ac80d4cdb01c4d3c1765637bed76cc91c1e35">commit</a>for more details.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 5.2 DSL for configuring Content Security Policy]]></title>
       <author><name>Sushant Mittal</name></author>
      <link href="https://www.bigbinary.com/blog/rails-5-2-adds-dsl-for-configuring-content-security-policy-header"/>
      <updated>2018-10-23T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-5-2-adds-dsl-for-configuring-content-security-policy-header</id>
      <content type="html"><![CDATA[<p>Content Security Policy (CSP) is an added layer of security that helps to detectand mitigate various types of attacks on our web applications, including CrossSite Scripting (XSS) and data injection attacks.</p><h2>What is XSS ?</h2><p>In this attack, victim's browser may execute malicious scripts because browsertrusts the source of the content even when it's not coming from the correctsource.</p><p><a href="https://blog.bigbinary.com/2012/05/10/xss-and-rails.html">Here is</a> our blog onXSS written sometime back.</p><h2>How CSP can be used to mitigate and report this attack ?</h2><p>By using CSP, we can specify domains that are valid sources of executablescripts. Then a browser with CSP compatibility will only execute those scriptsthat are loaded from these whitelisted domains.</p><p>Please note that CSP makes XSS attack a lot harder but CSP does not make XSSattack impossible. CSP does not stop DOM-based XSS (also known as client-sideXSS). To prevent DOM-based XSS, Javascript code should be carefully written toavoid introducing such vulnerabilities.</p><p>In Rails 5.2, <a href="https://github.com/rails/rails/pull/31162">a DSL was added</a> forconfiguring Content Security Policy header.</p><h2>Let's check the configuration.</h2><p>We can define global policy for the project in an initializer.</p><pre><code class="language-ruby"># config/initializers/content_security_policy.rbRails.application.config.content_security_policy do |policy|policy.default_src :self, :httpspolicy.font_src :self, :https, :datapolicy.img_src :self, :https, :datapolicy.object_src :nonepolicy.script_src :self, :httpspolicy.style_src :self, :https, :unsafe_inlinepolicy.report_uri &quot;/csp-violation-report-endpoint&quot;end</code></pre><p>We can override global policy within a controller as well.</p><pre><code class="language-ruby"># Override policy inlineclass PostsController &lt; ApplicationControllercontent_security_policy do |policy|policy.upgrade_insecure_requests trueendend</code></pre><pre><code class="language-ruby"># Using mixed static and dynamic valuesclass PostsController &lt; ApplicationControllercontent_security_policy do |policy|policy.base_uri :self, -&gt; { &quot;https://#{current_user.domain}.example.com&quot; }endend</code></pre><h2>Content Security Policy can be deployed in report-only mode as well.</h2><p>Here is global setting in an initializer.</p><pre><code class="language-ruby"># config/initializers/content_security_policy.rbRails.application.config.content_security_policy_report_only = true</code></pre><p>Here we are putting an override at controller level.</p><pre><code class="language-ruby">class PostsController &lt; ApplicationControllercontent_security_policy_report_only only: :indexend</code></pre><p>Policy specified in <code>content_security_policy_report_only</code> header will not beenforced, but any violations will be reported to a provided URI. We can providethis violation report URI in <code>report_uri</code> option.</p><pre><code class="language-ruby"># config/initializers/content_security_policy.rbRails.application.config.content_security_policy do |policy|policy.report_uri &quot;/csp-violation-report-endpoint&quot;end</code></pre><p>If both <code>content_security_policy_report_only</code> and <code>content_security_policy</code>headers are present in the same response then policy specified in<code>content_security_policy</code> header will be enforced while<code>content_security_policy_report_only</code> policy will generate reports but will notbe enforced.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 5.2 stops some raw SQL, prevents SQL injections]]></title>
       <author><name>Piyush Tiwari</name></author>
      <link href="https://www.bigbinary.com/blog/rails-5-2-disallows-raw-sql-in-active-record"/>
      <updated>2018-10-16T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-5-2-disallows-raw-sql-in-active-record</id>
      <content type="html"><![CDATA[<p>We sometimes use raw SQL in Active Record methods. This can lead to<a href="https://en.wikipedia.org/wiki/SQL_injection">SQL injection</a> vulnerabilitieswhen we unknowingly pass unsanitized user input to the Active Record method.</p><pre><code class="language-ruby">class UsersController &lt; ApplicationController  def index    User.order(&quot;#{params[:order]} ASC&quot;)  endend</code></pre><p>Although this code is looking fine on the surface, we can see the issues lookingat the example from <a href="http://rails-sqli.org/">rails-sqli</a>.</p><pre><code class="language-ruby">pry(main)&gt; params[:order] = &quot;(CASE SUBSTR(authentication_token, 1, 1) WHEN 'k' THEN 0 else 1 END)&quot;pry(main)&gt; User.order(&quot;#{params[:order]} ASC&quot;)User Load (1.0ms)  SELECT &quot;users&quot;.* FROM &quot;users&quot; ORDER BY (CASE SUBSTR(authentication_token, 1, 1) WHEN 'k' THEN 0 else 1 END) ASC=&gt; [#&lt;User:0x00007fdb7968b508  id: 1,  email: &quot;piyush@example.com&quot;,  authentication_token: &quot;Vkn5jpV_zxhqkNesyKSG&quot;&gt;]</code></pre><p>There are many Active Record methods which are vulnerable to SQL injection andsome of these can be found <a href="http://rails-sqli.org/"><code>here</code></a>.</p><p>However, in Rails 5.2 these APIs are changed and they allow only attributearguments and Rails does not allow raw SQL. With Rails 5.2 it is not mandatorybut the developer would see a deprecation warning to remind about this.</p><pre><code class="language-ruby">irb(main):004:0&gt; params[:order] = &quot;email&quot;=&gt; &quot;email&quot;irb(main):005:0&gt; User.order(params[:order])  User Load (1.0ms)  SELECT  &quot;users&quot;.* FROM &quot;users&quot; ORDER BY email LIMIT $1  [[&quot;LIMIT&quot;, 11]]=&gt; #&lt;ActiveRecord::Relation [#&lt;User id: 1, email: &quot;piyush@example.com&quot;, authentication_token: &quot;Vkn5jpV_zxhqkNesyKSG&quot;&gt;]&gt;irb(main):008:0&gt; params[:order] = &quot;(CASE SUBSTR(authentication_token, 1, 1) WHEN 'k' THEN 0 else 1 END)&quot;irb(main):008:0&gt; User.order(&quot;#{params[:order]} ASC&quot;)DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): &quot;(CASE SUBSTR(authentication_token, 1, 1) WHEN 'k' THEN 0 else 1 END)&quot;. Non-attribute arguments will be disallowed in Rails 6.0. This method should not be called with user-provided values, such as request parameters or model attributes. Known-safe values can be passed by wrapping them in Arel.sql(). (called from irb_binding at (irb):8)  User Load (1.2ms)  SELECT  &quot;users&quot;.* FROM &quot;users&quot; ORDER BY (CASE SUBSTR(authentication_token, 1, 1) WHEN 'k' THEN 0 else 1 END) ASC=&gt; #&lt;ActiveRecord::Relation [#&lt;User id: 1, email: &quot;piyush@example.com&quot;, authentication_token: &quot;Vkn5jpV_zxhqkNesyKSG&quot;&gt;]&gt;</code></pre><p>In Rails 6, this will result into an error.</p><p>In Rails 5.2, if we want to run raw SQL without getting the above warning, wehave to change raw SQL string literals to an <code>Arel::Nodes::SqlLiteral</code> object.</p><pre><code class="language-ruby">irb(main):003:0&gt; Arel.sql('title')=&gt; &quot;title&quot;irb(main):004:0&gt; Arel.sql('title').class=&gt; Arel::Nodes::SqlLiteralirb(main):006:0&gt; User.order(Arel.sql(&quot;#{params[:order]} ASC&quot;))  User Load (1.2ms)  SELECT  &quot;users&quot;.* FROM &quot;users&quot; ORDER BY (CASE SUBSTR(authentication_token, 1, 1) WHEN 'k' THEN 0 else 1 END) ASC=&gt; #&lt;ActiveRecord::Relation [#&lt;User id: 1, email: &quot;piyush@example.com&quot;, authentication_token: &quot;Vkn5jpV_zxhqkNesyKSG&quot;&gt;]&gt;</code></pre><p>This should be done with care and should not be done with user input.</p><p>Here is relevant <a href="https://github.com/rails/rails/pull/27947/files">commit</a> and<a href="https://github.com/rails/rails/pull/27947">discussion</a>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 5.2 added method write_multi to cache store]]></title>
       <author><name>Rohan Pujari</name></author>
      <link href="https://www.bigbinary.com/blog/rails-5.2-adds-write_multi-for-cache-writes"/>
      <updated>2018-07-03T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-5.2-adds-write_multi-for-cache-writes</id>
      <content type="html"><![CDATA[<p>Before 5.2 it was not possible to write multiple entries to cache store in oneshot even though cache stores like Redis has<a href="https://redis.io/commands/mset"><code>MSET</code></a> command to set multiple keys in asingle atomic operation. However we were not able to use this feature of Redisbecause of the way Rails had implemented caching.</p><p>Rails has implemented caching using an abstract class<code>ActiveSupport::Cache::Store</code> which defines the interface that all cache storeclasses should implement. Rails also provides few common functionality that allcache store classes will need.</p><p>Prior to Rails 5.2 <code>ActiveSupport::Cache::Store</code> didn't have any method to setmultiple entities at once.</p><p>In Rails 5.2, <a href="https://github.com/rails/rails/pull/29366">write_multi was added</a>. Each cache store can implement this method and provide the functionality toadd multiple entries at once. If cache store does not implement this method,then the default implementation is to loop over each key value pair and sets itindividually using <code>write_entity</code> method.</p><p>Multiple entities can be set as shown here.</p><pre><code class="language-ruby">Rails.cache.write_multi name: 'Alan Turning', country: 'England'</code></pre><p><a href="https://github.com/redis-store/redis-rails">redis-rails</a> gem provides redis ascache store. However it does not implement <code>write_multi</code> method.</p><p>However if we are using Rails 5.2, then there is no point in using <code>redis-rails</code>gem, as Rails 5.2 comes with built in support for redis cache store, whichimplements <code>write_multi</code> method. It was added by<a href="https://github.com/rails/rails/pull/31134">this PR</a>.</p><p>We need to make following change.</p><pre><code class="language-ruby"># beforeconfig.cache_store = :redis_store# afterconfig.cache_store = :redis_cache_store</code></pre><p><code>redis-rails</code> repo has a<a href="https://github.com/redis-store/redis-rails/pull/81">pull request</a> to notifyusers that development of this gem is ceased. So it's better to use redis cachestore that comes with Rails 5.2.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 5.2 uses AES-256-GCM authenticated encryption]]></title>
       <author><name>Sushant Mittal</name></author>
      <link href="https://www.bigbinary.com/blog/rails-5-2-uses-aes-256-gcm-authenticated-encryption-as-default-cipher-for-encrypting-messages"/>
      <updated>2018-06-26T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-5-2-uses-aes-256-gcm-authenticated-encryption-as-default-cipher-for-encrypting-messages</id>
      <content type="html"><![CDATA[<p>Before Rails 5.2, <code>AES-256-CBC</code> authenticated encryption was the default cipherfor encrypting messages.</p><p>It was proposed to use <code>AES-256-GCM</code> authenticated encryption as the defaultcipher for encrypting messages because of following reasons:</p><ul><li>It produces shorter ciphertexts and performs quick encryption and decryption.</li><li>It is less error prone and more secure.</li></ul><p>So, <code>AES-256-GCM</code> became<a href="https://github.com/rails/rails/pull/29263">default cipher</a> for encryptingmessages in Rails 5.2 .</p><p>If we do not want <code>AES-256-GCM</code> as default cipher for encrypting messages in ourrails application, then we can disable it.</p><pre><code class="language-ruby">Rails.application.config.active_support.use_authenticated_message_encryption = false</code></pre><p>Default Encryption for cookies and sessions was also updated to use<code>AES-256-GCM</code> <a href="https://github.com/rails/rails/pull/28132">in this pull request</a>.</p><p>If we do not want <code>AES-256-GCM</code> as default encryption of cookies and sessions,then we can disable it too.</p><pre><code class="language-ruby">Rails.application.config.active_support.use_authenticated_cookie_encryption = false</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 5.2 adds allow_other_host to redirect_back method]]></title>
       <author><name>Mohit Natoo</name></author>
      <link href="https://www.bigbinary.com/blog/rails-5-2-adds-allow_other_host-option-to-redirect_back-method"/>
      <updated>2018-05-30T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-5-2-adds-allow_other_host-option-to-redirect_back-method</id>
      <content type="html"><![CDATA[<p>Rails 5.0 had introduced<a href="https://blog.bigbinary.com/2016/02/29/rails-5-improves-redirect_to_back-with-redirect-back.html">redirect_back</a>method to perform redirection to path present in <code>HTTP_REFERRER</code>. If there is no<code>HTTP_REFERRER</code> present, then site is redirected to <code>fallback_location</code>.</p><p>Now consider the following scenario.</p><p>In one of the searches on <code>google.com</code>, we see a link to <code>bigbinary.com</code>. Onclicking the link, we are navigated to <code>bigbinary.com</code>.</p><p>When somebody gets redirected to <code>bigbinary.com</code> from <code>google.com</code>, the HTTPREFERRER is set to <code>google.com</code></p><p>If <code>bigbinary.com</code> uses <code>redirect_back</code> in its code then the user will getredirected to <code>google.com</code> which might be undesired behavior for someapplications.</p><p>To avoid such cases, Rails 5.2 has added a flag<a href="https://github.com/rails/rails/pull/30850/commits/0db6a14ae16b143e078375ff7f3c940cf707290b">allow_other_host</a>to not allow redirecting to a different host other than the current site.</p><p>By default, <code>allow_other_host</code> option is set to <code>true</code>. So if you do not wantusers to go back to <code>google.com</code> then you need to explicitly set<code>allow_other_host: false</code>.</p><pre><code class="language-ruby">&gt; request.host#=&gt; &quot;http://www.bigbinary.com&quot;&gt; request.headers[&quot;Referrer&quot;]#=&gt; &quot;http://www.google.com&quot;# This will redirect back to google.comredirect_back(fallback_path: &quot;/&quot;)# This will not redirect back to google.comredirect_back(fallback_path: &quot;/&quot;, allow_other_host: false)</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 5.2 fixes query caching in MySQL & PostgreSQL adapters]]></title>
       <author><name>Sushant Mittal</name></author>
      <link href="https://www.bigbinary.com/blog/rails-5-2-fixes-query-caching-in-mysql-and-postgresql-adapters"/>
      <updated>2018-05-16T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-5-2-fixes-query-caching-in-mysql-and-postgresql-adapters</id>
      <content type="html"><![CDATA[<p>Prior to Rails 5.2, MySQL and PostgreSQL adapters had <code>select_value</code>,<code>select_values</code> &amp; <code>select_rows</code> <code>select_{value,values,rows}</code> methods. Theyimprove the performance by not instantiating <code>ActiveRecord::Result</code>.</p><p>However these methods broke query caching of<code>ActiveRecord::FinderMethods#exists?</code> method. Let's check the issue.</p><pre><code class="language-ruby">&gt;&gt; User.cache do&gt;&gt;   2.times { User.exists?(1) }&gt;&gt; endUser Exists (2.1ms)  SELECT  1 AS one FROM &quot;users&quot; WHERE &quot;users&quot;.&quot;id&quot; = $1 LIMIT $2  [[&quot;id&quot;, 1], [&quot;LIMIT&quot;, 1]]User Exists (2ms)  SELECT  1 AS one FROM &quot;users&quot; WHERE &quot;users&quot;.&quot;id&quot; = $1 LIMIT $2  [[&quot;id&quot;, 1], [&quot;LIMIT&quot;, 1]]</code></pre><p>As we can see, query was not cached and sql was executed second time.</p><p>From Rails 5.2, MySQL and PostgreSQL adapters are<a href="https://github.com/rails/rails/pull/29454">no longer override select_{value,values,rows} methods</a>which fix this query caching issue.</p><p>Also, the performance improvement provided by these methods was marginal and nota hotspot in Active Record, so this change was accepted.</p><p>Let's check query caching of <code>ActiveRecord::FinderMethods#exists?</code> after thechange.</p><pre><code class="language-ruby">&gt;&gt; User.cache do&gt;&gt;   2.times { User.exists?(1) }&gt;&gt; endUser Exists (2.1ms)  SELECT  1 AS one FROM &quot;users&quot; WHERE &quot;users&quot;.&quot;id&quot; = $1 LIMIT $2  [[&quot;id&quot;, 1], [&quot;LIMIT&quot;, 1]]CACHE User Exists (0.0ms)  SELECT  1 AS one FROM &quot;users&quot; WHERE &quot;users&quot;.&quot;id&quot; = $1 LIMIT $2  [[&quot;id&quot;, 1], [&quot;LIMIT&quot;, 1]]</code></pre><p>Now, query has been cached as expected.</p><p>This change has been backported in rails 5.1 from version 5.1.2 as well.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 5.2 sets version in Gemfile & adds .ruby-version]]></title>
       <author><name>Mohit Natoo</name></author>
      <link href="https://www.bigbinary.com/blog/rails-5_2-adds-ruby-version-file-and-ruby-version-to-gemfile-by-default"/>
      <updated>2018-05-07T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-5_2-adds-ruby-version-file-and-ruby-version-to-gemfile-by-default</id>
      <content type="html"><![CDATA[<p>For Ruby developers, it's common to switch between multiple Ruby versions formultiple projects as per the needs of the project. Sometimes, the process ofgoing back and forth with multiple Ruby versions could be frustrating for thedeveloper. To avoid this we add<a href="https://rvm.io/workflow/projects#project-file-ruby-version">.ruby-version files</a>to our projects so that version manager tools such as <code>rvm</code>, <code>rbenv</code> etc. caneasily determine which Ruby version should be used for that particular project.</p><p>One other case that Rails developers have to take care of is ensuring that theRuby version used to run Rails by the deployment tools is the one that isdesired. In order to ensure that we<a href="https://devcenter.heroku.com/articles/ruby-versions">add ruby version to Gemfile</a>.This will help bundler install dependencies scoped to the specified Rubyversion.</p><h3>Good News! Rails 5.2 makes our work easy.</h3><p>In Rails 5.2,<a href="https://github.com/rails/rails/pull/30016">changes have been made</a> to introduce<code>.ruby-version</code> file and also add the Ruby version to Gemfile by default aftercreating an app.</p><p>Let's create a new project with Ruby 2.5 .</p><pre><code class="language-ruby">$ rvm list default  Default Ruby (for new shells)     ruby-2.5 [ x86_64 ]$ rails new my_new_app</code></pre><p>In our new project, we should be able to see <code>.ruby-version</code> in its rootdirectory and it will contain value <code>2.5</code>. Also, we should see following line inthe Gemfile.</p><pre><code class="language-ruby">ruby &quot;2.5&quot;</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 5.2 Date#prev_occurring & Date#next_occurring]]></title>
       <author><name>Sushant Mittal</name></author>
      <link href="https://www.bigbinary.com/blog/rails-5-2-adds-date-methods-to-return-specified-next-or-previous-occurring-day-of-week"/>
      <updated>2018-04-17T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-5-2-adds-date-methods-to-return-specified-next-or-previous-occurring-day-of-week</id>
      <content type="html"><![CDATA[<p>Before Rails 5.2, this is how we would write to find next or previous occurringday of the week.</p><p><strong>Assume that current date is Tue, 27 Feb 2018.</strong></p><pre><code class="language-ruby"># find previous thursday&gt;&gt; Date.yesterday.beginning_of_week(:thursday)=&gt; Thu, 22 Feb 2018# find next thursday&gt;&gt; Date.tomorrow.end_of_week(:friday)=&gt; Thu, 01 Mar 2018</code></pre><p>Rails 5.2 has <a href="https://github.com/rails/rails/pull/26600">introduced methods</a><code>Date#prev_occurring</code> and <code>Date#next_occurring</code> to find next &amp; previousoccurring day of the week.</p><pre><code class="language-ruby"># find previous thursday&gt;&gt; Date.prev_occurring(:thursday)=&gt; Thu, 22 Feb 2018# find next thursday&gt;&gt; Date.next_occurring(:thursday)=&gt; Thu, 01 Mar 2018</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 5.2 default option to module & class attribute accessors]]></title>
       <author><name>Vishal Telangre</name></author>
      <link href="https://www.bigbinary.com/blog/rails-5-2-adds-default-options-to-module-and-class-attribute-accessors"/>
      <updated>2018-02-27T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-5-2-adds-default-options-to-module-and-class-attribute-accessors</id>
      <content type="html"><![CDATA[<p>When DHH introduced<a href="https://blog.bigbinary.com/2018/02/21/rails-5-2-supports-specifying-default-value-for-a-class_attribute.html">support for specifying a default value for class_attribute</a>,Genadi Samokovarov<a href="https://github.com/rails/rails/pull/29270#issuecomment-304705841">brought to notice</a>that the module and class attribute accessor macros also support specifying adefault value but using a block and not with a <code>default</code> option.</p><p>To have consistent and symmetrical behaviour across all the attributeextensions, it was decided to support specifying a default value using <code>default</code>option for all the module and class attribute macros as well.</p><p><code>mattr_accessor</code>, <code>mattr_reader</code> and <code>mattr_writer</code> macros generate getter andsetter methods at the module level.</p><p>Similarly, <code>cattr_accessor</code>, <code>cattr_reader</code>, and <code>cattr_writer</code> macros generategetter and setter methods at the class level.</p><h2>Before Rails 5.2</h2><p>Before Rails 5.2, this is how we would set the default values for the module andclass attribute accessor macros.</p><pre><code class="language-ruby">module ActivityLoggerHelper  mattr_accessor :colorize_logs  mattr_writer :log_ip { false }  self.colorize_logs = trueendclass ActivityLogger  include ActivityLoggerHelper  cattr_writer :logger { Logger.new(STDOUT) }  cattr_accessor :level  cattr_accessor :settings  cattr_reader :pid { Process.pid }  @@level = Logger::DEBUG  self.settings = {}end</code></pre><h2>After Rails 5.2</h2><p>We can still set a default value of a module or class attribute accessor byproviding a block. In this<a href="https://github.com/rails/rails/pull/29294">pull request</a>, support forspecifying a default value using a new <code>default</code> option has been introduced.</p><p>So instead of</p><pre><code class="language-ruby">cattr_writer :logger { Logger.new(STDOUT) }</code></pre><p>or</p><pre><code class="language-ruby">cattr_writer :loggerself.logger = Logger.new(STDOUT)</code></pre><p>or</p><pre><code class="language-ruby">cattr_writer :logger@@logger = Logger.new(STDOUT)</code></pre><p>we can now easily write</p><pre><code class="language-ruby">cattr_writer :logger, default: Logger.new(STDOUT)</code></pre><p>Same applies to the other attribute accessor macros like <code>mattr_accessor</code>,<code>mattr_reader</code>, <code>mattr_writer</code>, <code>cattr_accessor</code>, and <code>cattr_reader</code>.</p><p>Note that, the old way of specifying a default value using the block syntax willwork but will not be documented anywhere.</p><p>Also, note that if we try to set the default value by both ways i.e. byproviding a block as well as by specifying a <code>default</code> option; the valueprovided by <code>default</code> option will always take the precedence.</p><pre><code class="language-ruby">mattr_accessor(:colorize_logs, default: true) { false }</code></pre><p>Here, <code>@@colorize_logs</code> would be set with <code>true</code> as per the above precedencerule.</p><p><a href="https://github.com/rails/rails/blob/b6b0c99ff3e8ace3f42813154dbe4b8ad6a98e6c/activesupport/test/core_ext/module/attribute_accessor_test.rb#L45-L47">Here is a test</a>which verifies this behavior.</p><p>Finally, here is simplified version using the new <code>default</code> option.</p><pre><code class="language-ruby">module ActivityLoggerHelper  mattr_accessor :colorize_logs, default: true  mattr_writer :log_ip, default: falseendclass ActivityLogger  include ActivityLoggerHelper  cattr_writer :logger, default: Logger.new(STDOUT)  cattr_accessor :level, default: Logger::DEBUG  cattr_accessor :settings, default: {}  cattr_reader :pid, default: Process.pidend</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 5.2 specifying default value for class_attribute]]></title>
       <author><name>Vishal Telangre</name></author>
      <link href="https://www.bigbinary.com/blog/rails-5-2-supports-specifying-default-value-for-a-class_attribute"/>
      <updated>2018-02-21T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-5-2-supports-specifying-default-value-for-a-class_attribute</id>
      <content type="html"><![CDATA[<p>It is very common to set a default value for a <code>class_attribute</code>.</p><p>Before Rails 5.2, to specify a default value for a <code>class_attribute</code>, we neededto write like this.</p><pre><code class="language-ruby">class ActivityLoggerclass_attribute :loggerclass_attribute :settingsself.logger = Logger.new(STDOUT)self.settings = {}end</code></pre><p>As we can see above, it requires additional keystrokes to set a default valuefor each <code>class_attribute</code>.</p><p>Rails 5.2 has added support for specifying a default value for a<code>class_attribute</code> using <code>default</code> option.</p><pre><code class="language-ruby">class ActivityLoggerclass_attribute :logger, default: Logger.new(STDOUT)class_attribute :settings, default: {}end</code></pre><p>This enhancement was introduced in this<a href="https://github.com/rails/rails/pull/29270">pull request</a>.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 5.2 allows mailers to use custom Active Job class]]></title>
       <author><name>Prathamesh Sonpatki</name></author>
      <link href="https://www.bigbinary.com/blog/rails-5-2-allows-mailers-to-use-custom-active-job-class"/>
      <updated>2018-01-15T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-5-2-allows-mailers-to-use-custom-active-job-class</id>
      <content type="html"><![CDATA[<p>Rails allows sending emails asynchronously via Active Job.</p><pre><code class="language-ruby">Notifier.welcome(User.first).deliver_later</code></pre><p>It uses <code>ActionMailer::DeliveryJob</code> as the default job class to send emails.This class is<a href="https://github.com/rails/rails/blob/7b4132f4a28d1c264a972b95bf86bf6230869a40/actionmailer/lib/action_mailer/delivery_job.rb#L10">defined internally</a>by Rails.</p><p>The <code>DeliveryJob</code> defines <code>handle_exception_with_mailer_class</code> method to handleexception and to do some housekeeping work.</p><pre><code class="language-ruby">def handle_exception_with_mailer_class(exception)  if klass = mailer_class    klass.handle_exception exception  else    raise exception  endend</code></pre><p>One might need more control on the job class to retry the job under certainconditions or add more logging around exceptions.</p><p>Before Rails 5.2, it was not possible to use a custom job class for thispurpose.</p><p>Rails 5.2 has added a feature to<a href="https://github.com/rails/rails/pull/29457">configure the job class per mailer</a>.</p><pre><code class="language-ruby">class CustomNotifier &lt; ApplicationMailer  self.delivery_job = CustomNotifierDeliveryJobend</code></pre><p>By default, Rails will use the internal <code>DeliveryJob</code> class if the<code>delivery_job</code> configuration is not present in the mailer class.</p><p>Now, Rails will use <code>CustomNotifierDeliveryJob</code> for sending emails forCustomNotifier mailer.</p><pre><code class="language-ruby">CustomNotifier.welcome(User.first).deliver_later</code></pre><p>As mentioned above <code>CustomNotifierDeliveryJob</code> can be further configured forlogging, exception handling and reporting.</p><p>By default, <code>deliver_later</code> will pass following arguments to the <code>perform</code>method of the <code>CustomNotifierDeliveryJob</code>.</p><ul><li>mailer class name</li><li>mailer method name</li><li>mail delivery method</li><li>original arguments with which the mail is to be sent</li></ul><pre><code class="language-ruby">class CustomNotifierDeliveryJob &lt; ApplicationJob  rescue_from StandardError, with: :handle_exception_with_mailer_class  retry_on CustomNotifierException  discard_on ActiveJob::DeserializationError  def perform(mailer, mail_method, delivery_method, *args)    logger.log &quot;Mail delivery started&quot;    klass = mailer.constantize    klass.public_send(mail_method, *args).send(delivery_method)    logger.log &quot;Mail delivery completed&quot;  end  def handle_exception_with_mailer_class(exception)    if klass = mailer_class      klass.handle_exception exception    else      raise exception    end  endend</code></pre><p>We can also simply inherit from the <code>ActionMailer::DeliveryJob</code> and override theretry logic.</p><pre><code class="language-ruby">class CustomNotifierDeliveryJob &lt; ActionMailer::DeliveryJob  retry_on CustomNotifierExceptionend</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 5.2 supports descending indexes for MySQL]]></title>
       <author><name>Chirag Shah</name></author>
      <link href="https://www.bigbinary.com/blog/rails-5-2-supports-descending-indexes-for-mysql"/>
      <updated>2018-01-10T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-5-2-supports-descending-indexes-for-mysql</id>
      <content type="html"><![CDATA[<p>An index is used to speed up the performance of queries on a database.</p><p>Rails allows us to create index on a database column by means of a migration. Bydefault, the sort order for the index is ascending.</p><p>But consider the case where we are fetching reports from the database. And whilequerying the database, we always want to get the latest report. In this case, itis efficient to specify the sort order for the index to be descending.</p><p>We can specify the sort order by adding an index to the required column byadding a migration .</p><pre><code class="language-ruby">add_index :reports, [:user_id, :name], order: { user_id: :asc, name: :desc }</code></pre><h2>PostgreSQL</h2><p>If our Rails application is using postgres database, after running the abovemigration we can verify that the sort order was added in schema.rb</p><pre><code class="language-ruby">create_table &quot;reports&quot;, force: :cascade do |t|  t.string &quot;name&quot;  t.integer &quot;user_id&quot;  t.datetime &quot;created_at&quot;, null: false  t.datetime &quot;updated_at&quot;, null: false  t.index [&quot;user_id&quot;, &quot;name&quot;], name: &quot;index_reports_on_user_id_and_name&quot;, order: { name: :desc }end</code></pre><p>Here, the index for <code>name</code> has sort order in descending. Since the default isascending, the sort order for <code>user_id</code> is not specified in schema.rb.</p><h2>MySQL &lt; 8.0.1</h2><p>For <strong>MySQL &lt; 8.0.1</strong>, running the above migration, would generate the followingschema.rb</p><pre><code class="language-ruby">create_table &quot;reports&quot;, force: :cascade do |t|  t.string &quot;name&quot;  t.integer &quot;user_id&quot;  t.datetime &quot;created_at&quot;, null: false  t.datetime &quot;updated_at&quot;, null: false  t.index [&quot;user_id&quot;, &quot;name&quot;], name: &quot;index_reports_on_user_id_and_name&quot;end</code></pre><p>As we can see, although the migration runs successfully, it ignores the sortorder and the default ascending order is added.</p><h2>Rails 5.2 and MySQL &gt; 8.0.1</h2><p><strong>MySQL 8.0.1</strong><a href="https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-1.html#mysqld-8-0-1-optimizer">added support</a>for descending indices.</p><p>Rails community was quick<a href="https://github.com/rails/rails/pull/28773">to integrate it as well</a>. So now inRails 5.2, we can add descending indexes for MySQL databases.</p><p>Running the above migration would lead to the same output in schema.rb file asthat of the postgres one.</p><pre><code class="language-ruby">create_table &quot;reports&quot;, force: :cascade do |t|  t.string &quot;name&quot;  t.integer &quot;user_id&quot;  t.datetime &quot;created_at&quot;, null: false  t.datetime &quot;updated_at&quot;, null: false  t.index [&quot;user_id&quot;, &quot;name&quot;], name: &quot;index_reports_on_user_id_and_name&quot;, order: { name: :desc }end</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 5.2 pass request params to Action Mailer previews]]></title>
       <author><name>Prathamesh Sonpatki</name></author>
      <link href="https://www.bigbinary.com/blog/rails-5-2-allows-passing-request-params-to-action-mailer-previews"/>
      <updated>2018-01-08T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-5-2-allows-passing-request-params-to-action-mailer-previews</id>
      <content type="html"><![CDATA[<p>Rails has inbuilt feature to preview the emails using<a href="http://guides.rubyonrails.org/action_mailer_basics.html#previewing-emails">Action Mailer previews</a>.</p><p>A preview mailer can be setup as shown here.</p><pre><code class="language-ruby">class NotificationMailer &lt; ApplicationMailerdef notify(email: email, body: body)user = User.find_by(email: email)mail(to: user.email, body: body)endendclass NotificationMailerPreview &lt; ActionMailer::Previewdef notifyNotificationMailer.notify(email: User.first.email, body: &quot;Hi there!&quot;)endend</code></pre><p>This will work as expected. But our email template is displayed differentlybased on user's role. To test this, we need to update the notify method and thencheck the updated preview.</p><p>What if we could just pass the email in the preview URL.</p><pre><code class="language-plaintext">http://localhost:3000/rails/mailers/notification/notify?email=superadmin@example.com</code></pre><p>In Rails 5.2, we can pass the params directly in the URL and<a href="https://github.com/rails/rails/pull/28244">params will be available to the preview mailers</a>.</p><p>Our code can be changed as follows to use the params.</p><pre><code class="language-ruby">class NotificationMailerPreview &lt; ActionMailer::Previewdef notifyemail = params[:email] || User.first.emailNotificationMailer.notify(email: email, body: &quot;Hi there!&quot;)endend</code></pre><p>This allows us to test our mailers with dynamic input as per requirements.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 5.2 adds bootsnap to the app to speed up boot time]]></title>
       <author><name>Prathamesh Sonpatki</name></author>
      <link href="https://www.bigbinary.com/blog/rails-5-2-adds-bootsnap-to-the-app-to-speed-up-boot-time"/>
      <updated>2018-01-01T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-5-2-adds-bootsnap-to-the-app-to-speed-up-boot-time</id>
      <content type="html"><![CDATA[<p>Rails 5.2 beta 1 was recently<a href="http://weblog.rubyonrails.org/2017/11/27/Rails-5-2-Active-Storage-Redis-Cache-Store-HTTP2-Early-Hints-Credentials/">released</a>.</p><p>If we generate a new Rails app using Rails 5.2, we will see bootsnap gem in theGemfile. <a href="https://github.com/Shopify/bootsnap">bootsnap</a> helps in reducing theboot time of the app by caching expensive computations.</p><p>In a new Rails 5.2 app, <code>boot.rb</code> will contain following content:</p><pre><code class="language-ruby">ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)require 'bundler/setup' # Set up gems listed in the Gemfile.require 'bootsnap/setup' # Speed up boot time by caching expensive operations.if %w[s server c console].any? { |a| ARGV.include?(a) }  puts &quot;=&gt; Booting Rails&quot;end</code></pre><p>This sets up bootsnap to start in all environments. We can toggle it perenvironment as required.</p><p>This works out of the box and we don't have do to anything for the new app.</p><p>If we are upgrading an older app which already has bootsnap, then we need tomake sure that we are using bootsnap &gt;= 1.1.0 because new Rails apps ship withthat version constraint.</p><p>If the app doesn't contain the bootsnap gem already then we will need to add itmanually since <code>rails app:update</code> task adds the <code>bootsnap/setup</code> line to<code>boot.rb</code> regardless of its presence in the Gemfile.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 5.2 fetch_values for HashWithIndifferentAccess]]></title>
       <author><name>Mohit Natoo</name></author>
      <link href="https://www.bigbinary.com/blog/rails-5-2-implements-fetch_values-for-hashwithindifferentaccess"/>
      <updated>2017-12-06T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-5-2-implements-fetch_values-for-hashwithindifferentaccess</id>
      <content type="html"><![CDATA[<p>Ruby 2.3 added<a href="https://bugs.ruby-lang.org/issues/10017">fetch_values method to hash</a>.</p><p>By using <code>fetch_values</code> we are able to get values for multiple keys in a hash.</p><pre><code class="language-ruby">capitals = { usa: &quot;Washington DC&quot;,             china: &quot;Beijing&quot;,             india: &quot;New Delhi&quot;,             australia: &quot;Canberra&quot; }capitals.fetch_values(:usa, :india)#=&gt; [&quot;Washington DC&quot;, &quot;New Delhi&quot;]capitals.fetch_values(:usa, :spain) { |country| &quot;N/A&quot; }#=&gt; [&quot;Washington DC&quot;, &quot;N/A&quot;]</code></pre><p>Rails 5.2 introduces method <code>fetch_values</code><a href="https://github.com/rails/rails/pull/28316">on HashWithIndifferentAccess</a>. We'llhence be able to fetch values of multiple keys on any instance ofHashWithIndifferentAccess class.</p><pre><code class="language-ruby">capitals = HashWithIndifferentAccess.newcapitals[:usa] = &quot;Washington DC&quot;capitals[:china] = &quot;Beijing&quot;capitals.fetch_values(&quot;usa&quot;, &quot;china&quot;)#=&gt; [&quot;Washington DC&quot;, &quot;Beijing&quot;]capitals.fetch_values(&quot;usa&quot;, &quot;spain&quot;) { |country| &quot;N/A&quot; }#=&gt; [&quot;Washington DC&quot;, &quot;N/A&quot;]</code></pre>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 5.2 expiry option for signed & encrypted cookies]]></title>
       <author><name>Mohit Natoo</name></author>
      <link href="https://www.bigbinary.com/blog/expirty-option-for-signed-and-encrypted-cookies-in-Rails-5-2"/>
      <updated>2017-10-09T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/expirty-option-for-signed-and-encrypted-cookies-in-Rails-5-2</id>
      <content type="html"><![CDATA[<p>In Rails 5.1 we have option to set expiry for cookies.</p><pre><code class="language-ruby">cookies[:username] = {value: &quot;sam_smith&quot;, expires: Time.now + 4.hours}</code></pre><p>The above code sets cookie which expires in 4 hours.</p><p>The <code>expires</code> option, is not supported for<a href="https://blog.bigbinary.com/2013/03/19/cookies-on-rails.html">signed and encrypted cookies</a>.In other words we are not able to decide on server side when an encrypted orsigned cookie would expire.</p><p>From Rails 5.2, we'll be able to<a href="https://github.com/rails/rails/pull/30121">set expiry for encrypted and signed cookies</a>as well.</p><pre><code class="language-ruby">cookies.encrypted[:firstname] = { value: &quot;Sam&quot;, expires: Time.now + 1.day }# sets string `Sam` in an encrypted `firstname` cookie for 1 day.cookies.signed[:lastname] = {value: &quot;Smith&quot;, expires: Time.now + 1.hour }# sets string `Smith` in a signed `lastname` cookie for 1 hour.</code></pre><p>Apart from this, in Rails 5.1, we needed to provide an absolute date/time valuefor expires option.</p><pre><code class="language-ruby"># setting cookie for 90 minutes from current time.cookies[:username] = {value: &quot;Sam&quot;, expires: Time.now + 90.minutes}</code></pre><p>Starting Rails 5.2, we'll be able to set the <code>expires</code> option by giving arelative duration as value.</p><pre><code class="language-ruby"># setting cookie for 90 minutes from current time.cookies[:username] = { value: &quot;Sam&quot;, expires: 90.minutes }# After 1 hour&gt; cookies[:username]&gt; #=&gt; &quot;Sam&quot;# After 2 hours&gt; cookies[:username]&gt; #=&gt; nil&gt; ~~~</code></pre>]]></content>
    </entry>
     </feed>