<?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-06-15T04:58:32+00:00</updated>
     <id>https://www.bigbinary.com/</id>
     <entry>
       <title><![CDATA[Rails 6.1 adds invert_where method]]></title>
       <author><name>Chimed Palden</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-adds-invert_where"/>
      <updated>2021-05-04T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-adds-invert_where</id>
      <content type="html"><![CDATA[<p>Rails 6.1 adds an <code>invert_where</code> method that will invert all scope conditions.</p><p>Let's see an example.</p><pre><code class="language-ruby">class User  scope :active, -&gt; { where(accepted: true, locked: false) }end&gt;&gt; User.all=&gt; #&lt;ActiveRecord::Relation [#&lt;User id: 1, name: 'Rob', accepted: true, locked: true&gt;#&lt;User id: 2, name: 'Jack', accepted: false, locked: false&gt;#&lt;User id: 3, name: 'Nina', accepted: true, locked: false&gt;#&lt;User id: 4, name: 'Oliver', accepted: false, locked: true&gt;</code></pre><p>Now let's query for active and inactive users</p><pre><code class="language-ruby">&gt;&gt; User.active# SELECT * FROM Users WHERE `accepted` = 1 AND `locked` = 0=&gt; #&lt;ActiveRecord::Relation [#&lt;User id: 3, name: 'Nina', accepted: true, locked: false&gt;]&gt;&gt;&gt; User.active.invert_where# SELECT * FROM Users WHERE NOT (`accepted` = 1 AND `locked` = 0)=&gt; #&lt;ActiveRecord::Relation [#&lt;User id: 1, name: 'Rob', accepted: true, locked: true&gt;#&lt;User id: 2, name: 'Jack', accepted: false, locked: false&gt;#&lt;User id: 4, name: 'Oliver', accepted: false, locked: true&gt;]&gt;</code></pre><p>As we can see above, if we use <code>invert_where</code> with multiple attributes, itapplies logical <code>NOR</code>, which is <code>NOT a OR NOT b</code>, to the WHERE clause of thequery. Using DeMorgan's Law, it can also be written as <code>NOT (a AND b)</code> tomatch the second output.</p><p>Check out the <a href="https://github.com/rails/rails/pull/40249">pull request</a> for moredetails.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 adds support for validating numeric values that fall within a specific range using the `in:` option]]></title>
       <author><name>Akanksha Jain</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-adds-validate-numericality-in-range-option"/>
      <updated>2021-04-14T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-adds-validate-numericality-in-range-option</id>
      <content type="html"><![CDATA[<p>Before Rails 6.1, to validate a numerical value that falls within a specificrange, we had to use <code>greater_than_or_equal_to:</code> and <code>less_than_or_equal_to:</code>.</p><p>In the example below, we want to add a validation that ensures that each item inthe StockItem class has a quantity that ranges from 50 to 100.</p><pre><code class="language-ruby">class StockItem &lt; ApplicationRecord  validates :quantity, numericality: { greater_than_or_equal_to: 50, less_than_or_equal_to: 100 }endStockItem.create! code: 'Shirt-07', quantity: 40#=&gt; ActiveRecord::RecordInvalid (Validation failed: Quantity must be greater than or equal to 50)</code></pre><p>In Rails 6.1, to validate that a numerical value falls within a specific range,we can use the new <code>in:</code> option:</p><pre><code class="language-ruby">class StockItem &lt; ApplicationRecord  validates :quantity, numericality: { in: 50..100 }endStockItem.create! code: 'Shirt-07', quantity: 40#=&gt; ActiveRecord::RecordInvalid (Validation failed: Quantity must be in 50..100)</code></pre><p>Check out the <a href="https://github.com/rails/rails/pull/41022">pull request</a> for moredetails on this feature.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 adds delegated_type to ActiveRecord]]></title>
       <author><name>Akhil Gautam</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-adds-delegated-type-to-active-record"/>
      <updated>2021-04-06T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-adds-delegated-type-to-active-record</id>
      <content type="html"><![CDATA[<p>Rails 6.1 adds <code>delegated_type</code> to ActiveRecord which makesit easier for models to share responsibilities.</p><h2>Before Rails 6.1</h2><p>Let's say we are building softwareto manage the inventory of an automobile company.It produces 2 types of vehicles, <code>Car</code> and <code>Motorcycle</code>.Both have <code>name</code> and <code>mileage</code> attributes.</p><p>Let's look into at least 2 different solutions to design this system.&lt;br/&gt;</p><h3>Single Table Inheritance</h3><p>In this approach, we combine all the attributes of various modelsand store them in a single table.Let's create a <code>Vehicle</code> modelandits corresponding table to store the data of both <code>Car</code> and <code>Motorcycle</code>.</p><pre><code class="language-ruby"># schema of Vehicle {id: Integer, type: String[car or motorcycle], name: String, mileage: Integer}class Vehicle &lt; ApplicationRecord  # put common logic hereendclass Car &lt; Vehicle  # put car specific code &amp; validationendclass Motorcycle &lt; Vehicle  # put motorcycle-specific code &amp; validationend</code></pre><p>This approach fits precisely for this scenariobut when the attributes of the various models differ,it becomes a pain point.Let's say at some point in time we add a <code>bs4_engine</code> boolean columnto track whether a <code>Motorcyle</code> has a <code>bs4_engine</code> or not.In the case of <code>Car</code>, <code>bs4_engine</code> will contain <code>nil</code>.As time passes, a lot of vehicle-specific attributes get addedand the database will be sparsely filled with a lot of <code>nil</code>.</p><h3>Polymorphic Relations</h3><p>With polymorphic associations,a model can belong to more than one other model, on a single association.</p><pre><code class="language-ruby"># schema {name: String, mileage: Integer}class Vehicle &lt; ApplicationRecord  belongs_to :vehicleable, polymorphic: trueend# schema {interior_color: String, adjustable_roof: Boolean}class Car &lt; ApplicationRecord  has_one :vehicle, as: :vehicleableend# schema {bs4_engine: Boolean, tank_color: String}class Motorcycle &lt; ApplicationRecord  has_one :vehicle, as: :vehicleableend</code></pre><p>Here, <code>Vehicle</code> is a class that contains common attributes,while <code>Motorcycle</code> and <code>Car</code> store any diverging attributes.This approach fixes the <code>nil</code> values,butto create a <code>Vehicle</code> record we now have to create a <code>Car</code> or <code>Motorcycle</code> first separately.</p><pre><code class="language-ruby"># creating new records&gt;&gt; bike = Motorcycle.create!( bs4_engine: false, tank_color: '#f2f2f2')#&lt;Motorcycle id: 1, bs4_engine: true, tank_color: '#f2f2f2', created_at: &quot;2021-01-17 ...&quot;&gt;&gt;&gt; vehicle = Vehicle.create!(vehicleable: bike, name: 'TS-1987', mileage: 45)#&lt;Vehicle id: 1, vehicleable_type: &quot;Motorcycle&quot;, vehicleable_id: 1, name: &quot;TS-1987&quot;, mileage: 45, created_at: ...&quot;&gt;# query&gt;&gt; b1 = Motorcycle.find(1) #=&gt; &lt;Motorcycle id: 1, bs4_engine: true, tank_color: '#f2f2f2', created_at: &quot;2021-01-17 ...&quot;&gt;&gt;&gt; b1.vehicle.name  #=&gt; TS-1987&gt;&gt; b1.vehicle.mileage  #=&gt; 45</code></pre><p>Now, let's say, we need to query Vehicles that are Motorcycles,or let's say we want to check whether a Vehicle is a Car or not.For all of these, we will have to write cumbersome logic and queries.</p><h2>Rails 6.1 <code>delegated_type</code></h2><p>Rails 6.1 brings <code>delegated_type</code>which fixes the problem discussed above and adds a lot of helper methods.To use it,we just need to replace polymorphic relation with <code>delegated_types</code>.</p><pre><code class="language-ruby">class Vehicle &lt; ApplicationRecord  delegated_type :vehicleable, types: %w[ Motorcycle Car ]end</code></pre><p>That is the only change we need to make to leverage the <code>delegated_type</code>.With this change,we can create both the delegator and delegatee at the same time.</p><pre><code class="language-ruby"># creating new records&gt;&gt; vehicle1 = Vehicle.create!(vehicleable: Car.new(interior_color: '#fff', adjustable_roof: true), name: 'TS78Z', mileage: 89)#&lt;Vehicle id: 3, vehicleable_type: &quot;Car&quot;, vehicleable_id: 2, name: &quot;TS78Z&quot;, mileage: 89, created_at: ...&quot;&gt;&gt;&gt; vehicle2= Vehicle.create!(vehicleable: Motorcycle.new(bs4_engine: false, tank_color: '#ff00bb'), name: 'BL96', mileage: 45)#&lt;Vehicle id: 4, vehicleable_type: &quot;Motorcycle&quot;, vehicleable_id: 5, name: &quot;BL96&quot;, mileage: 45, created_at: ...&quot;&gt;# Note: Just initializing the delegatee(Car.new/Motorcycle.new) is sufficient.</code></pre><p>When it comes to query capabilities, it adds a lot of delegated type convenience methods.</p><pre><code class="language-ruby"># Get all Vehicles that are Cars&gt;&gt; Vehicle.cars#&lt;ActiveRecord::Relation [#&lt;Vehicle id: 5, vehicleable_type: &quot;Car&quot;, vehicleable_id: 1, name: &quot;TS78Z&quot;, ...&quot;&gt;]&gt;# Get all Vehicles that are Motorcycles&gt;&gt; Vehicle.motorcycles#&lt;ActiveRecord::Relation [#&lt;Vehicle id: 1, vehicleable_type: &quot;Motorcycle&quot;, vehicleable_id: 1, name: &quot;BL96&quot;, ...&quot;&gt;]&gt;&gt;&gt; vehicle = Vehicle.find(3)#&lt;Vehicle id: 3, vehicleable_type: &quot;Car&quot;, vehicleable_id: 2, name: &quot;TS78Z&quot;, mileage: 89, created_at: ...&quot;&gt;# check whether a Vehicle is a Car or Motorcycle&gt;&gt; vehicle.car?  #=&gt; true&gt;&gt; vehicle.motorcylce? #=&gt; false# get vehicleable&gt;&gt; vehicle.car # &lt;Car id: 1, adjustable_roof: true, ...&gt;&gt;&gt; vehicle.motorcycle # nil</code></pre><p>So, <code>delegated_type</code> can be thought of as sugaron top of polymorphic relations that adds convenience methods.</p><p>Check out the<a href="https://github.com/rails/rails/pull/39341/files">pull request</a> to learn more.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 adds nulls_first and nulls_last methods to Arel for PostgreSQL]]></title>
       <author><name>Berin Larson</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-adds-nulls-first-and-nulls-last-to-arel"/>
      <updated>2021-03-09T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-adds-nulls-first-and-nulls-last-to-arel</id>
      <content type="html"><![CDATA[<p>In PostgreSQL, when sorting output rows in descending order,columns with null values will appear first.</p><p>Let's take this example of ordering users by the number of times they have logged in.</p><pre><code class="language-sql">postgres=&gt; SELECT * from users ORDER BY login_count DESC;       name        | login_count-------------------+------------- Johnny Silverhand |        NULL Jackie Welles     |         202 V                 |           1(3 rows)</code></pre><p>This is not useful since most of the time we would want the null values to appear last.</p><p>PostgreSQL provides <code>NULLS FIRST</code> and <code>NULLS LAST</code> options for the <code>ORDER BY</code> clause for this use case.</p><pre><code class="language-ruby">irb&gt; pp User.order(&quot;login_count DESC NULLS LAST&quot;).        pluck(:name, :login_count)(0.9 ms)  SELECT &quot;users&quot;.&quot;name&quot;, &quot;users&quot;.&quot;login_count&quot; FROM &quot;users&quot;          ORDER BY login_count DESC NULLS LAST=&gt; [[&quot;Jackie Welles&quot;, 202],   [&quot;V&quot;, 1],   [&quot;Johnny Silverhand&quot;, nil]]</code></pre><p>In Rails 6.1, we can use the new <code>nulls_first</code> or <code>nulls_last</code> methods to construct the same queryusing Arel.</p><pre><code class="language-ruby">irb&gt; pp User.order(User.arel_table[:login_count].desc.nulls_last).        pluck(:name, :login_count)(0.9 ms)  SELECT &quot;users&quot;.&quot;name&quot;, &quot;users&quot;.&quot;login_count&quot; FROM &quot;users&quot;          ORDER BY login_count DESC NULLS LAST=&gt; [[&quot;Jackie Welles&quot;, 202],   [&quot;V&quot;, 1],   [&quot;Johnny Silverhand&quot;, nil]]</code></pre><p>The resulting code is slightly more verbose for this simple example. But Arel really shines when programmatically constructing complex SQL queries.</p><p>Check out this<a href="https://github.com/rails/rails/pull/38131">pull request</a>for more details.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 adds support for PostgreSQL interval data type]]></title>
       <author><name>Akhil Gautam</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-adds-postgresql-interval-data-type"/>
      <updated>2021-01-26T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-adds-postgresql-interval-data-type</id>
      <content type="html"><![CDATA[<p>&lt;br /&gt;</p><h3>What is PostgreSQL Interval Data Type?</h3><p>PostgreSQL Interval Data Type allows us to store a duration/period of time inyears, months, days, hours, minutes, seconds, etc. It also allows us to performarithmetic operations on that interval.</p><p>There are two input formats for interval data. These formats are used to writeinterval values.</p><ol><li>Verbose format:</li></ol><pre><code class="language-ruby">  &lt;quantity&gt; &lt;unit&gt; [&lt;quantity&gt; &lt;unit&gt;...] [&lt;direction&gt;]  # Examples:  '2 years ago'  '12 hours 13 minutes ago'  '8 years 7 months 2 days 3 hours'</code></pre><ul><li><code>quantity</code> can be any number.</li><li><code>unit</code> can be any granular unit of time in plural or singular form likedays/day, months/month, weeks/week, etc..</li><li><code>direction</code> can be <code>ago</code> or an empty string.</li></ul><ol start="2"><li>ISO 8601 formats:</li></ol><pre><code class="language-ruby">P &lt;quantity&gt; &lt;unit&gt; [ &lt;quantity&gt; &lt;unit&gt; ...] [ T [ &lt;quantity&gt; &lt;unit&gt; ...]]</code></pre><ul><li>ISO 8601 format always starts with <code>P</code>.</li><li><code>quantity</code> and <code>unit</code> before <code>T</code> represents years, months, weeks and days ofan interval.</li><li><code>quantity</code> and <code>unit</code> after <code>T</code> represents the time-of-day unit.</li></ul><pre><code class="language-ruby"># ExamplesP1Y1M1D =&gt; interval of '1 year 1 month 1 day'P3Y1DT2H =&gt; interval of '3 years 1 day 2 hours'P5Y2MT3H2M =&gt; interval of '5 years 2 months 3 hours 2 minutes'# NOTE: If `M` appears before `T`,# it is month/months and if it appears after `T`, it signifies minute/minutes.ORP [ years-months-days ] [ T hours:minutes:seconds ]# ExamplesP0012-07-00T00:09:00 =&gt; interval of '12 years 7 months 9 minutes'P0000-10-00T10:00:00 =&gt; interval of '10 months 10 hours'</code></pre><h4>Arithmetic operations on interval</h4><p>We can easily apply addition, subtraction and multiplication operations oninterval data.</p><pre><code class="language-ruby">'10 hours 10 minutes' + '30 minutes' =&gt; '10 hours 40 minutes''10 hours 10 minutes' - '10 minutes' =&gt; '10 hours'60 * '10 minute' =&gt; '10 hours'</code></pre><h3>Before Rails 6.1</h3><p>PostgreSQL <code>interval</code> data type can be used in Rails but Active Record treats<code>interval</code> as a string. In order to convert it to an <code>ActiveSupport::Duration</code>object, we have to manually alter the <code>IntervalStyle</code> of the database to<code>iso_8601</code> and then parse it as shown below:</p><pre><code class="language-ruby">execute &quot;ALTER DATABASE &lt;our_database_name&gt; SET IntervalStyle = 'iso_8601'&quot;ActiveSupport::Duration.parse(the_iso_8601_formatted_string)</code></pre><h3>Rails 6.1</h3><p>Rails 6.1 adds built-in support for the PostgreSQL <code>interval</code> data type. Itautomatically converts <code>interval</code> to an <code>ActiveSupport::Duration</code> object whenfetched from a database. When a record containing the <code>interval</code> field is saved,it is serialized to an ISO 8601 formatted duration string.</p><p>The following example illustrates how it can be used now:</p><pre><code class="language-ruby"># db/migrate/20201109111850_create_seminars.rbclass CreateSeminars &lt; ActiveRecord::Migration[6.1]  def change    create_table :seminars do |t|      t.string :name      t.interval :duration      t.timestamps    end  endend# app/models/seminar.rbclass Seminar &lt; ApplicationRecord  attribute :duration, :intervalend&gt;&gt; seminar = Seminar.create!(name: 'RubyConf', duration: 5.days)&gt;&gt; seminar=&gt; #&lt;Event id: 1, name: &quot;RubyConf&quot;, duration: 5 days, created_at: ...&gt;&gt;&gt; seminar.duration=&gt; 5 days&gt;&gt; seminar.duration.class=&gt; ActiveSupport::Duration&gt;&gt; seminar.duration.iso8601=&gt; &quot;P5D&quot;# ISO 8601 strings can also be provided as interval's value&gt;&gt; seminar = Seminar.create!(name: 'GopherConIndia', duration: 'P5DT7H6S')&gt;&gt; seminar=&gt; #&lt;Event id: 2, name: &quot;GopherConIndia&quot;, duration: 5 days, 7 hours, and 6 seconds, created_at: ...&gt;# Invalid values to interval are written as NULL in the database.&gt;&gt; seminar = Seminar.create!(name: 'JSConf', duration: '3 days')&gt;&gt; seminar=&gt; #&lt;Event id: 3, name: &quot;JSConf&quot;, duration: nil, created_at: ...&gt;</code></pre><p>If we want to keep the old behaviour where <code>interval</code> is treated as a string, weneed to add the following in the model.</p><pre><code class="language-ruby"># app/models/seminar.rbclass Seminar &lt; ApplicationRecord  attribute :duration, :stringend</code></pre><p>If the <code>attribute</code> is not set in the model, it will throw the followingdeprecation warning.</p><pre><code class="language-plaintext">DEPRECATION WARNING: The behavior of the `:interval` type will be changing in Rails 6.2to return an `ActiveSupport::Duration` object. If you'd like to keepthe old behavior, you can add this line to Event model:  attribute :duration, :stringIf you'd like the new behavior today, you can add this line:  attribute :duration, :interval</code></pre><p>Check out the<a href="https://github.com/rails/rails/commit/0475215d4fa1a6db2a92a0065081fe19c64cc124">commit</a>for more details.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 allows per environment configuration support for Active Storage]]></title>
       <author><name>Shashank</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-allows-per-environment-configuration-support-for-active-storage"/>
      <updated>2021-01-20T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-allows-per-environment-configuration-support-for-active-storage</id>
      <content type="html"><![CDATA[<p>Rails 6.1 allows environment-specific configuration filesto set up Active Storage.</p><p>In development, the <code>config/storage/development.yml</code> filewill take precedence over the <code>config/storage.yml</code> file.Similarly, in production, the <code>config/storage/production.yml</code> filewill take precedence.</p><p>If an environment-specific configuration is not present,Rails will fall back to the configuration declared in <code>config/storage.yml</code>.</p><h2>Why was it needed?</h2><p>Before Rails 6.1, all storage services were defined in one file,each environment could set its preferred service in <code>config.active_storage.service</code>,and that service would be used for all attachments.</p><p>Now we can override the default application-wide storage servicefor any attachment, like this:</p><pre><code class="language-ruby">class User &lt; ApplicationModel  has_one_attached :avatar, service: :amazon_s3end</code></pre><p>And we can declare a custom <code>amazon_s3</code> service in the <code>config/storage.yml</code> file:</p><pre><code class="language-ruby">amazon_s3:  service: S3  bucket: &quot;...&quot;  access_key_id: &quot;...&quot;  secret_access_key: &quot;...&quot;</code></pre><p>But we are still using the same service for storing avatarsin both production and development environments.</p><p>To use a separate service per environment,Rails allows the creation of configuration files for each.</p><h2>How do we do that?</h2><p>Let's change the service to something more generic in the User model:</p><pre><code class="language-ruby">class User &lt; ApplicationModel  has_one_attached :avatar, service: :store_avatarsend</code></pre><p>And add some environment configurations:</p><p>For production we'll add <code>config/storage/production.yml</code>:</p><pre><code class="language-ruby">store_avatars:  service: S3  bucket: &quot;...&quot;  access_key_id: &quot;...&quot;  secret_access_key: &quot;...&quot;</code></pre><p>And for development we'll add <code>config/storage/development.yml</code>:</p><pre><code class="language-ruby">store_avatars:  service: Disk  root: &lt;%= Rails.root.join(&quot;storage&quot;) %&gt;</code></pre><p>This will ensure that Rails will store the avatarsdifferently per environment.</p><p>Check out the<a href="https://github.com/rails/rails/pull/40294">pull request</a>to learn more.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 adds support for belongs_to to has_many inversing]]></title>
       <author><name>Siddharth Shringi</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-adds-support-for-belongs_to-to-has_many-inversing"/>
      <updated>2021-01-19T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-adds-support-for-belongs_to-to-has_many-inversing</id>
      <content type="html"><![CDATA[<p>Before Rails 6.1,we could only traverse the object chainin one direction - from has_many to belongs_to.Now we can traverse the chain bi-directionally.</p><p>The <code>inverse_of</code> option, both in <code>belongs_to</code> and <code>has_many</code> isused to specify the name of the inverse association.</p><p>Let's see an example.</p><pre><code class="language-ruby">class Author &lt; ApplicationRecord  has_many :books, inverse_of: :authorendclass Book &lt; ApplicationRecord  belongs_to :author, inverse_of: :booksend</code></pre><h3>Before Rails 6.1</h3><h4>has_many to belongs_to inversing</h4><pre><code class="language-ruby">irb(main):001:0&gt; author = Author.newirb(main):002:0&gt; book = author.books.buildirb(main):003:0&gt; author == book.author=&gt; true</code></pre><p>In the above code,first we created the <code>author</code> and thena <code>book</code> instance through the <code>has_many</code> association.</p><p>In line 3,we traverse the object chainback to the author using the <code>belongs_to</code> association methodon the book instance.</p><h4>belongs_to to has_many inversing</h4><pre><code class="language-ruby">irb(main):001:0&gt; book = Book.newirb(main):002:0&gt; author = book.build_authorirb(main):003:0&gt; author.books=&gt; #&lt;ActiveRecord::Associations::CollectionProxy []&gt;</code></pre><p>In the above case,we created the <code>book</code> instance and thenwe created the <code>author</code> instance usingthe method added by <code>belongs_to</code> association.</p><p>But when we tried to traverse the object chainthrough the <code>has_many</code> association,we got an empty collectioninstead of one with the <code>book</code> instance.</p><h3>After changes in Rails 6.1</h3><p>The <code>belongs_to</code> inversing can now be traversedin the same way as the <code>has_many</code> inversing.</p><pre><code class="language-ruby">irb(main):001:0&gt; book = Book.newirb(main):002:0&gt; author = book.build_authorirb(main):003:0&gt; author.books=&gt; #&lt;ActiveRecord::Associations::CollectionProxy [#&lt;Book id: nil, author_id: nil, created_at: nil, updated_at: nil&gt;]&gt;</code></pre><p>Here we get the collection with the <code>book</code> instanceinstead of an empty collection.</p><p>We can also verify using a test.</p><pre><code class="language-ruby">class InverseTest &lt; ActiveSupport::TestCase  def test_book_inverse_of_author    author = Author.new    book = author.books.build    assert_equal book.author, author  end  def test_author_inverse_of_book    book = Book.new    author = book.build_author    assert_includes author.books, book  endend</code></pre><p>In previous Rails versions, the test cases would fail.</p><pre><code class="language-shell"># Running:.FFailure:InverseTest#test_author_inverse_of_bookExpected #&lt;ActiveRecord::Associations::CollectionProxy []&gt; to include #&lt;Book id: nil, author_id: nil, created_at: nil, updated_at: nil&gt;.Finished in 0.292532s, 6.8369 runs/s, 10.2553 assertions/s.2 runs, 3 assertions, 1 failures, 0 errors, 0 skips</code></pre><p>In Rails 6.1, both the tests will pass.</p><pre><code class="language-shell"># Running:..Finished in 0.317668s, 6.2959 runs/s, 9.4438 assertions/s.2 runs, 3 assertions, 0 failures, 0 errors, 0 skips</code></pre><p>Check out this<a href="https://github.com/rails/rails/pull/34533">pull request</a>for more details.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Additional database-specific rake tasks for multi-database users]]></title>
       <author><name>Amit Gupta</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-adds-additional-database-specific-tasks"/>
      <updated>2021-01-13T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-adds-additional-database-specific-tasks</id>
      <content type="html"><![CDATA[<p>Rails 6.1 provides additional tasks to work with a specific database whenworking in a multi database setup.</p><p>Before Rails 6.1, only the following tasks worked on a specific database.</p><ul><li>rails db:migrate:primary</li><li>rails db:create:primary</li><li>rails db:drop:primary</li></ul><p>But some tasks that could be applied to a specific database were missing. Let'scheckout an example.</p><p>Before Rails 6.1, running a top level migration on a multi-database project,dumped the schema for all the configured databases, but if a database specificmigration was run, the schema was not dumped. And there were no tasks tomanually dump the schema of a specific database.</p><pre><code class="language-ruby">&gt; rails db:schema:dump:primaryrails aborted!Don't know how to build task `db:schema:dump:primary` (See the list of available tasks with `rails --tasks`)Did you mean? db:schema:dump</code></pre><p>Therefore, in Rails 6.1, the following database specific tasks were introduced.</p><ul><li>rails db:schema:dump:primary</li><li>rails db:schema:load:primary</li><li>rails db:test:prepare:primary</li></ul><p>Check out the <a href="https://github.com/rails/rails/pull/38449">pull request</a> for moredetails.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 adds strict_loading to warn lazy loading associations]]></title>
       <author><name>Dinesh Panda</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-adds-strict_loading-to-warn-lazy-loading-associations"/>
      <updated>2021-01-06T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-adds-strict_loading-to-warn-lazy-loading-associations</id>
      <content type="html"><![CDATA[<p>Rails 6.1 adds <code>strict_loading</code> mode which can be enabled per record,association, model or across the whole application.</p><p><code>strict_loading</code> mode is an optional setup and it helps in finding <code>N+1</code>queries.</p><p>Let's consider the following example.</p><pre><code class="language-ruby">class Article &lt; ApplicationRecord  has_many :commentsendclass Comment &lt; ApplicationRecord  belongs_to :articleend</code></pre><h4>Mark a record for strict_loading</h4><p>When <code>strict_loading</code> mode is enabled for a record then its associations have tobe eager loaded otherwise Rails raises<code>ActiveRecord::StrictLoadingViolationError</code>.</p><p>Let's see this use case by setting <code>strict_loading</code> mode for an <code>article</code>record.</p><pre><code class="language-ruby">2.7.2 :001 &gt; article = Article.strict_loading.first  Article Load (0.2ms)  SELECT &quot;articles&quot;.* FROM &quot;articles&quot; ORDER BY &quot;articles&quot;.&quot;id&quot; ASC LIMIT ?  [[&quot;LIMIT&quot;, 1]] =&gt; #&lt;Article id: 1, title: &quot;First article&quot;, content: &quot;First content&quot;, created_at: &quot;2020-12-01 07:23:38.446867000 +0000&quot;, updated_at: &quot;2020-12-01 07:23:38.446867000 +0000&quot;&gt;2.7.2 :002 &gt; article.strict_loading? =&gt; true2.7.2 :003 &gt; article.commentsTraceback (most recent call last):ActiveRecord::StrictLoadingViolationError (`Comment` called on `Article` is marked for strict_loading and cannot be lazily loaded.)</code></pre><p><code>strict_loading</code> mode forces us to eager load the associated comments by raisingthe <code>ActiveRecord::StrictLoadingViolationError</code> error.</p><p>Let's fix the <code>strict_loading</code> violation error.</p><pre><code class="language-ruby">2.7.2 :004 &gt; article = Article.includes(:comments).strict_loading.first  Article Load (0.7ms)  SELECT &quot;articles&quot;.* FROM &quot;articles&quot; ORDER BY &quot;articles&quot;.&quot;id&quot; ASC LIMIT ?  [[&quot;LIMIT&quot;, 1]]  Comment Load (0.2ms)  SELECT &quot;comments&quot;.* FROM &quot;comments&quot; WHERE &quot;comments&quot;.&quot;article_id&quot; = ?  [[&quot;article_id&quot;, 1]] =&gt; #&lt;Article id: 1, title: &quot;First article&quot;, content: &quot;First content&quot;, created_at: &quot;2020-12-01 07:23:38.446867000 +0000&quot;, updated_at: &quot;2020-12-01 07:23:38.446867000 +0000&quot;&gt;2.7.2 :005 &gt; article.comments =&gt; #&lt;ActiveRecord::Associations::CollectionProxy [#&lt;Comment id: 1, desc: &quot;Great article&quot;, article_id: 1, created_at: &quot;2020-12-01 07:23:58.832869000 +0000&quot;, updated_at: &quot;2020-12-01 07:23:58.832869000 +0000&quot;&gt;  , #&lt;Comment id: 2, desc: &quot;Well written&quot;, article_id: 1, created_at: &quot;2020-12-01 07:24:02.853376000 +0000&quot;, updated_at: &quot;2020-12-01 07:24:02.853376000 +0000&quot;&gt;]&gt;</code></pre><p><code>strict_loading</code> mode on <code>article</code> record automatically sets <code>strict_loading</code>mode for all the associated <code>comments</code> as well.</p><p>Let's verify this in Rails console.</p><pre><code class="language-ruby">2.7.2 :006 &gt; article.comments.all?(&amp;:strict_loading?) =&gt; true</code></pre><h4>Mark an association for strict_loading</h4><p><code>strict_loading</code> mode can be set up for a specific association.</p><p>Let's update our example to see <code>strict_loading</code> in action when it is passed asan option to associations.</p><pre><code class="language-ruby">class Article &lt; ApplicationRecord  has_many :comments, strict_loading: trueendclass Comment &lt; ApplicationRecord  belongs_to :articleend</code></pre><p>Let's verify this in Rails console.</p><pre><code class="language-ruby">2.7.2 :001 &gt; article = Article.first  Article Load (0.2ms)  SELECT &quot;articles&quot;.* FROM &quot;articles&quot; ORDER BY &quot;articles&quot;.&quot;id&quot; ASC LIMIT ?  [[&quot;LIMIT&quot;, 1]] =&gt; #&lt;Article id: 1, title: &quot;First article&quot;, content: &quot;First content&quot;, created_at: &quot;2020-12-01 07:23:38.446867000 +0000&quot;, updated_at: &quot;2020-12-01 07:23:38.446867000 +0000&quot;&gt;2.7.2 :002 &gt; article.strict_loading? =&gt; false2.7.2 :003 &gt; article.commentsTraceback (most recent call last):ActiveRecord::StrictLoadingViolationError (`comments` called on `Article` is marked for strict_loading and cannot be lazily loaded.)2.7.2 :004 &gt; article = Article.includes(:comments).first  Article Load (0.2ms)  SELECT &quot;articles&quot;.* FROM &quot;articles&quot; ORDER BY &quot;articles&quot;.&quot;id&quot; ASC LIMIT ?  [[&quot;LIMIT&quot;, 1]]  Comment Load (0.2ms)  SELECT &quot;comments&quot;.* FROM &quot;comments&quot; WHERE &quot;comments&quot;.&quot;article_id&quot; = ?  [[&quot;article_id&quot;, 1]] =&gt; #&lt;Article id: 1, title: &quot;First article&quot;, content: &quot;First content&quot;, created_at: &quot;2020-12-01 07:23:38.446867000 +0000&quot;, updated_at: &quot;2020-12-01 07:23:38.446867000 +0000&quot;&gt;2.7.2 :005 &gt; article.comments =&gt; #&lt;ActiveRecord::Associations::CollectionProxy [#&lt;Comment id: 1, desc: &quot;Great article&quot;, article_id: 1, created_at: &quot;2020-12-01 07:23:58.832869000 +0000&quot;, updated_at: &quot;2020-12-01 07:23:58.832869000 +0000&quot;&gt;, #&lt;Comment id: 2, desc: &quot;Well written&quot;, article_id: 1, created_at: &quot;2020-12-01 07:24:02.853376000 +0000&quot;, updated_at: &quot;2020-12-01 07:24:02.853376000 +0000&quot;&gt;]&gt;</code></pre><h4>Configure strict_loading per model</h4><p>We can set <code>strict_loading_by_default</code> option per model to mark all of itsrecords and associations for <code>strict_loading</code>.</p><p>Let's update our example to set <code>strict_loading_by_default</code> for the <code>Article</code>model.</p><pre><code class="language-ruby">class Article &lt; ApplicationRecord  self.strict_loading_by_default = true  has_many :commentsendclass Comment &lt; ApplicationRecord  belongs_to :articleend</code></pre><p>Let's verify this setting in the <code>Article</code> model.</p><pre><code class="language-ruby">2.7.2 :001 &gt; article = Article.includes(:comments).first  Article Load (0.2ms)  SELECT &quot;articles&quot;.* FROM &quot;articles&quot; ORDER BY &quot;articles&quot;.&quot;id&quot; ASC LIMIT ?  [[&quot;LIMIT&quot;, 1]]  Comment Load (0.2ms)  SELECT &quot;comments&quot;.* FROM &quot;comments&quot; WHERE &quot;comments&quot;.&quot;article_id&quot; = ?  [[&quot;article_id&quot;, 1]] =&gt; #&lt;Article id: 1, title: &quot;First article&quot;, content: &quot;First content&quot;, created_at: &quot;2020-12-01 07:23:38.446867000 +0000&quot;, updated_at: &quot;2020-12-01 07:23:38.446867000 +0000&quot;&gt;2.7.2 :002 &gt; article.strict_loading? =&gt; true2.7.2 :003 &gt; article.comments.all?(&amp;:strict_loading?) =&gt; false2.7.2 :004 &gt; article.comments =&gt; #&lt;ActiveRecord::Associations::CollectionProxy [#&lt;Comment id: 1, desc: &quot;Great article&quot;, article_id: 1, created_at: &quot;2020-12-01 07:23:58.832869000 +0000&quot;, updated_at: &quot;2020-12-01 07:23:58.832869000 +0000&quot;&gt;, #&lt;Comment id: 2, desc: &quot;Well written&quot;, article_id: 1, created_at: &quot;2020-12-01 07:24:02.853376000 +0000&quot;, updated_at: &quot;2020-12-01 07:24:02.853376000 +0000&quot;&gt;]&gt;</code></pre><h4>Make strict_loading default across all models</h4><p>We can make <code>strict_loading</code> default across all models by adding the followingline to the Rails configuration file.</p><pre><code class="language-ruby">config.active_record.strict_loading_by_default = true</code></pre><hr><h2>Configure strict_loading violations to show only in logs</h2><p>By default, associations marked for strict loading always raise<code>ActiveRecord::StrictLoadingViolationError</code> for lazy loading.</p><p>However, we may prefer to log such violations in our <code>production</code> environmentinstead of raising errors.</p><p>We can add the following line to the environment configuration file.</p><pre><code class="language-ruby">config.active_record.action_on_strict_loading_violation = :log</code></pre><p>Check out pull requests <a href="https://github.com/rails/rails/pull/37400">#37400</a>,<a href="https://github.com/rails/rails/pull/38541">#38541</a>,<a href="https://github.com/rails/rails/pull/39491">#39491</a> and<a href="https://github.com/rails/rails/pull/40511">#40511</a> for more details.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 allows default_scope to be run on all queries]]></title>
       <author><name>Unnikrishnan KP</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-allows-default_scope-to-be-run-on-all-queries"/>
      <updated>2020-12-29T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-allows-default_scope-to-be-run-on-all-queries</id>
      <content type="html"><![CDATA[<p>Before Rails 6.1 if a <code>default_scope</code> was defined in a model it would be appliedonly for <code>select</code> and <code>insert</code> queries. Rails 6.1 adds an option<code>all_queries: true</code> that could be passed to <code>default_scope</code> to make the scopeapplicable for all queries.</p><pre><code class="language-ruby">default_scope -&gt; { where(...) }, all_queries: true</code></pre><p>Consider the Article class below.</p><pre><code class="language-ruby">class Article  default_scope -&gt; { where(organization_id: Current.organization_id) }end@article.update title: &quot;Hello World&quot;@article.delete</code></pre><p>The <code>update</code> and <code>delete</code> methods would generate SQL queries as shown below. Aswe can see that <code>default_scope</code> is missing from these queries.</p><pre><code class="language-sql">UPDATE &quot;articles&quot; SET &quot;title&quot; = $1 WHERE &quot;articles&quot;.&quot;id&quot; = $2 [[&quot;title&quot;, &quot;Hello World&quot;], [&quot;id&quot;, 146]]DELETE FROM &quot;articles&quot; WHERE &quot;articles&quot;.&quot;id&quot; = $1  [[&quot;id&quot;, 146]]</code></pre><p>In Rails 6.1 we can solve this problem by passing <code>all_queries: true</code> to the<code>default_scope</code>.</p><pre><code class="language-ruby">class Article  default_scope -&gt; { where(organization_id: Current.organization_id) }, all_queries: trueend</code></pre><p>Then the generated SQL changes to this:</p><pre><code class="language-sql">UPDATE &quot;articles&quot; SET &quot;title&quot; = $1 WHERE &quot;articles&quot;.&quot;id&quot; = $2 AND &quot;articles&quot;.&quot;organization_id&quot; = $3  [[&quot;title&quot;, &quot;Hello World&quot;], [&quot;id&quot;, 146], [&quot;organization_id&quot;, 314]]DELETE FROM &quot;articles&quot; WHERE &quot;articles&quot;.&quot;id&quot; = $1 AND &quot;articles&quot;.&quot;organization_id&quot; = $2  [[&quot;id&quot;, 146], [&quot;organization_id&quot;, 314]]</code></pre><p>Ability to make default_scopes applicable to all queries is particularly usefulin the case of multi-tenanted applications, where an <code>organization_id</code> or<code>repository_id</code> is added to the tables to support sharding.</p><p>Check out the <a href="https://github.com/rails/rails/pull/40720">pull request</a> for moredetails on this feature.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 adds where.associated to check association presence]]></title>
       <author><name>Nithin Krishna</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-adds-where-associated-to-check-association-presence"/>
      <updated>2020-12-18T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-adds-where-associated-to-check-association-presence</id>
      <content type="html"><![CDATA[<p>Rails 6.1 simplifies how to check whether an association exists by adding a new <code>associated</code> method.</p><p>Let's see an example of it.</p><pre><code class="language-ruby">class Account &lt; ApplicationRecord  has_many :users, -&gt; { joins(:contact).where.not(contact_id: nil) }end</code></pre><p>This will return all users with contacts.If we rephrase that sentence then we can say that &quot;this will return all users who are associated with contacts&quot;.</p><p>Let's see how we can do the same with the new <code>associated</code> method.</p><pre><code class="language-ruby">class Account &lt; ApplicationRecord  has_many :users, -&gt; { where.associated(:contact) }end</code></pre><p>Now we can see that the usage of <code>associated</code> decreases some of the  syntactic noise we saw in the first example. This method is essentially a syntactic sugar over the <code>inner_joins(:contact)</code>.</p><p>Check out the<a href="https://github.com/rails/rails/pull/40696">pull request</a>for more details.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 raises an error for impossible camelcase inflections]]></title>
       <author><name>Yedhin Kizhakkethara</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-raises-error-for-impossible-camelcase-inflections"/>
      <updated>2020-12-15T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-raises-error-for-impossible-camelcase-inflections</id>
      <content type="html"><![CDATA[<p>From Rails 6.1 onwards, the default behaviorof the Rails generatorwhen encountering an impossible &quot;camelCase&quot; inflectionwould be to raise an error, rather than generatinga name that will cause problems.</p><h3>What are impossible &quot;camelCase&quot; inflections?</h3><p>The<a href="https://api.rubyonrails.org/classes/ActiveSupport/Inflector/Inflections.html">Rails Inflector</a>is part of the <code>ActiveSupport</code> module,and it comes shipped with patterns to transform Ruby strings.This library is responsible for pluralization and/or singularizationof strings.</p><p>The Inflector tries its best to provide the desired result givena string. But sometimes, with certain words, it can't provide saythe pluralized version out of the box.</p><p>Let's say for example the string is <code>DSL</code>.The desired plural form is <code>DSLs</code>.But the Inflector gets confused on what exactly isthe desired plural form or more accurately whatexactly is the underscore resource nameandit used to generate inconsistent class names.</p><h3>Before Rails 6.1</h3><p>Let's try out the following example.</p><pre><code class="language-bash">bundle exec rails g scaffold DSL field</code></pre><p>In the output we can see that the controller filenameis <code>ds_ls_controller.rb</code>andthe controller class name is:</p><pre><code class="language-ruby">class DsLsController &lt; ApplicationController</code></pre><p>And the routes file is populated with:</p><pre><code class="language-ruby">resources :dsls</code></pre><p>You see the problem right?</p><p>The generated route <code>:dsls</code>expects a <code>DslsController</code> controller but the controller generated is <code>DsLsController</code>.This will lead to a routing error.</p><h3>How Rails 6.1 solves this problem?</h3><p>The Rails team decided that it would be better toterminate the generation process with an errorrather than generating classes that are internally inconsistent.</p><p>Thus Rails now raises an error in the following two scenarioswhere the casing is impossible to be inflected:</p><p>The first case is when &quot;camelCased&quot; model name is passed to a generator.The second case is when the full round trip from pluralize to singularize does notmatch with the original singular value. Rails checks for the following condition.</p><pre><code class="language-ruby">name.pluralize.underscore.singularize != name.underscore.singularize</code></pre><p>We can try out the same example that we did in the previous sectionand it will provide the following output:</p><pre><code class="language-text">Rails cannot recover the underscored form from its camelcase form 'DSL'.Please use an underscored name instead, either 'dsl' or 'ds_l'.Or set up custom inflection rules for this noun before running the generator in config/initializers/inflections.rb.</code></pre><p>This allows the developers to either rephrase the resource namewith an underscored name from the very beginning itselforfollow the suggestion, that is to create a custom inflection.</p><h3>Creating a custom inflection</h3><p><code>ActiveSupport::Inflector</code> provides us with the <code>inflections</code> methodin order to create our own custom inflections.This method can even accept an optional locale,which comes in handy when we are writinginflection rules for languages other than <code>:en</code>,which is the default locale.</p><p>You can have a detailed look into the inflection methods over<a href="https://api.rubyonrails.org/classes/ActiveSupport/Inflector/Inflections.html">here</a>.</p><p>Let's try to make the above example workandget the desired underscore namefor the string <code>DSL</code>.Were dealing with an irregular inflection.Thus we can make use of the <code>irregular</code> method,which takes two arguments:the singular and the plural form of the word as strings.</p><p>Let's just add the custom inflection into<code>config/initializers/inflections.rb</code>:</p><pre><code class="language-ruby"># We provide the string in lowercase formatActiveSupport::Inflector.inflections(:en) do |inflect| inflect.irregular 'dsl', 'dsls'end</code></pre><p>Voila!That's it.</p><p>Now if we run <code>rails g scaffold DSL</code>,we will be able to get the correct file and class names.</p><p>Check out the<a href="https://github.com/rails/rails/pull/39832">pull request</a>and<a href="https://github.com/rails/rails/issues/39117">the issue</a>for more details.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 allows associations to be destroyed asynchronously]]></title>
       <author><name>Srijan Kapoor</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-allows-associations-to-support-destroy_async-option-with-dependent-key"/>
      <updated>2020-12-08T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-allows-associations-to-support-destroy_async-option-with-dependent-key</id>
      <content type="html"><![CDATA[<p>In Rails 6.1, Rails will enqueue a background job to destroy associated recordsif <code>dependent: :destroy_async</code> is setup.</p><p>Let's consider the following example.</p><pre><code class="language-ruby">class Team &lt; ApplicationRecord  has_many :players, dependent: :destroy_asyncendclass Player &lt; ApplicationRecord  belongs_to :teamend</code></pre><p>Now, if we call the <code>destroy</code> method on an instance of class <code>Team</code> Rails wouldenqueue an asynchronous job to delete the associated <code>players</code> records.</p><p>We can verify this asynchronous job with the following test case.</p><pre><code class="language-ruby">class TeamTest &lt; ActiveSupport::TestCase  include ActiveJob::TestHelper  test &quot;destroying a record destroys the associations using a background job&quot; do    team = Team.create!(name: &quot;Portugal&quot;, manager: &quot;Fernando Santos&quot;)    player1 = Player.new(name: &quot;Bernardo Silva&quot;)    player2 = Player.new(name: &quot;Diogo Jota&quot;)    team.players &lt;&lt; [player1, player2]    team.save!    team.destroy    assert_enqueued_jobs 1    assert_difference -&gt; { Player.count }, -2 do      perform_enqueued_jobs    end  endendFinished in 0.232213s, 4.3064 runs/s, 8.6128 assertions/s.1 runs, 2 assertions, 0 failures, 0 errors, 0 skips</code></pre><p>Alternatively, this enqueue behavior can also be demonstrated in<code>rails console</code>.</p><pre><code class="language-ruby">irb(main):011:0&gt; team.destroy  TRANSACTION (0.1ms)  begin transaction  Player Load (0.6ms)  SELECT &quot;players&quot;.* FROM &quot;players&quot; WHERE &quot;players&quot;.&quot;team_id&quot; = ?  [[&quot;team_id&quot;, 6]]Enqueued ActiveRecord::DestroyAssociationAsyncJob (Job ID: 4df07c2d-f55b-48c9-8c20-545b086adca2) to Async(active_record_destroy) with arguments: {:owner_model_name=&gt;&quot;Team&quot;, :owner_id=&gt;6, :association_class=&gt;&quot;Player&quot;, :association_ids=&gt;[1, 2], :association_primary_key_column=&gt;:id, :ensuring_owner_was_method=&gt;nil}Performed ActiveRecord::DestroyAssociationAsyncJob (Job ID: 4df07c2d-f55b-48c9-8c20-545b086adca2) from Async(active_record_destroy) in 34.5ms</code></pre><p>However, this behaviour is inconsistent and the <code>destroy_async</code> option shouldnot be used when the association is backed by foreign key constraints in thedatabase.</p><p>Let us consider another example.</p><p><strong>CASE:</strong> With a simple foreign key on the <code>team_id</code> column in place.</p><pre><code class="language-ruby">irb(main):015:0&gt; team.destroy  TRANSACTION (0.1ms)  begin transaction  Player Load (0.1ms)  SELECT &quot;players&quot;.* FROM &quot;players&quot; WHERE &quot;players&quot;.&quot;team_id&quot; = ?  [[&quot;team_id&quot;, 7]]Enqueued ActiveRecord::DestroyAssociationAsyncJob (Job ID: 69e51e5f-5b59-4095-92db-90aab73a7f65) to Async(default) with arguments: {:owner_model_name=&gt;&quot;Team&quot;, :owner_id=&gt;7, :association_class=&gt;&quot;Player&quot;, :association_ids=&gt;[1], :association_primary_key_column=&gt;:id, :ensuring_owner_was_method=&gt;nil}  Team Destroy (0.9ms)  DELETE FROM &quot;teams&quot; WHERE &quot;teams&quot;.&quot;id&quot; = ?  [[&quot;id&quot;, 7]]  TRANSACTION (1.1ms)  rollback transactionPerforming ActiveRecord::DestroyAssociationAsyncJob (Job ID: 69e51e5f-5b59-4095-92db-90aab73a7f65) from Async(default) enqueued at 2021-01-03T21:10:21Z with arguments: {:owner_model_name=&gt;&quot;Team&quot;, :owner_id=&gt;7, :association_class=&gt;&quot;Player&quot;, :association_ids=&gt;[1], :association_primary_key_column=&gt;:id, :ensuring_owner_was_method=&gt;nil}Traceback (most recent call last):        1: from (irb):15ActiveRecord::InvalidForeignKey (SQLite3::ConstraintException: FOREIGN KEY constraint failed)</code></pre><p>An exception is raised by Rails and the record is not destroyed.</p><p><strong>CASE:</strong> With a cascading foreign key using <code>on_delete: :cascade</code></p><p>Here, even though <code>ActiveRecord::DestroyAssociationAsyncJob</code> would run tosuccessful completion, the associated <code>players</code> records would already be deletedinside the same transaction block destroying the <code>team</code> record, and it wouldskip any destroy callbacks like <code>before_destroy</code>, <code>after_destroy</code> or<code>after_commit on: :destroy</code>.</p><p>This makes using <code>destroy_async</code> redundant in such a case.</p><p>Check out the <a href="https://github.com/rails/rails/pull/40157">pull request</a> for moredetails.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 adds values_at attribute method for Active Record]]></title>
       <author><name>Chetan Gawai</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-adds-values_at-attribute-method-for-active-record"/>
      <updated>2020-11-17T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-adds-values_at-attribute-method-for-active-record</id>
      <content type="html"><![CDATA[<p>Rails 6.1 simplifies retrieving values of attributes on the Active Record modelinstance by adding the <code>values_at</code> attribute method. This is similar to the<code>values_at</code> method in <code>Hash</code> and <code>Array</code>.</p><p>Let's check out an example of extracting values from a <code>User</code> model instance.</p><pre><code class="language-ruby">class User &lt; ApplicationRecord  def full_name    &quot;#{self.first_name} #{self.last_name}&quot;  endend &gt;&gt; user = User.new(first_name: 'Era', last_name: 'Das' , email: 'era@gmail.com')=&gt; User id: nil, first_name: &quot;Era&quot;, last_name: &quot;Das&quot;, created_at: nil, updated_at: nil, email: &quot;era@gmail.com&quot;, password_digest: nil</code></pre><h4>Before Rails 6.1</h4><p>As shown below using <code>values_at</code> for <code>full_name</code>, which is a method, returns<code>nil</code>.</p><pre><code class="language-ruby">&gt;&gt; user.attributes.values_at(&quot;first_name&quot;, &quot;full_name&quot;)=&gt; [&quot;Era&quot;, nil]</code></pre><h4>After changes in Rails 6.1</h4><p>Rails 6.1 added the <code>values_at</code> method on Active Record which returns an arraycontaining the values associated with the given methods.</p><pre><code class="language-ruby">&gt;&gt; user.values_at(&quot;first_name&quot;, &quot;full_name&quot;)=&gt; [&quot;Era&quot;, &quot;Era Das&quot;]</code></pre><p>Check out the <a href="https://github.com/rails/rails/pull/36481">pull request</a> for moredetails.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Database tasks can skip test database using SKIP_TEST_DATABASE]]></title>
       <author><name>Sandip Mane</name></author>
      <link href="https://www.bigbinary.com/blog/database-tasks-can-skip_test_database-with-an-environment-variable"/>
      <updated>2020-10-27T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/database-tasks-can-skip_test_database-with-an-environment-variable</id>
      <content type="html"><![CDATA[<p>In Rails 6.1, Rails will skip modifications to the test database if<code>SKIP_TEST_DATABASE</code> is set to <code>true</code>.</p><h2>Without the environment variable</h2><pre><code class="language-bash">&gt; bundle exec rake db:createCreated database 'app_name_development'Created database 'app_name_test'</code></pre><h2>With the environment variable</h2><pre><code class="language-bash">&gt; SKIP_TEST_DATABASE=true bundle exec rake db:createCreated database 'app_name_development'</code></pre><p>As we can see in the first example, both a <code>development</code> and a <code>test</code> databasewere created, which is unexpected when directly invoking <code>db:create</code>. Oneobvious solution to this problem is to force the <code>development</code> environment toonly create a <code>development</code> database. However this solution will break<code>bin/setup</code> as mentioned in<a href="https://github.com/rails/rails/commit/6ca9031ba3c389f71366c3e6abf069c6924c5acf">this commit</a>.Hence the need for an environment variable to skip <code>test</code> database creation.</p><p>Check out the <a href="https://github.com/rails/rails/pull/39027">pull request</a> for moredetails.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 supports ORDER BY clause for batch processing methods]]></title>
       <author><name>Sagar Patil</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-supports-order-desc-for-find_each-find_in_batches-and-in_batches"/>
      <updated>2020-10-22T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-supports-order-desc-for-find_each-find_in_batches-and-in_batches</id>
      <content type="html"><![CDATA[<p>Before Rails 6.1, batch processing methods like <em>find_each</em>, <em>find_in_batches</em>and <em>in_batches</em> didn't support the <em>ORDER BY</em> clause. By default the order wasset to <em>id ASC</em>.</p><pre><code class="language-ruby">&gt; User.find_each{|user| puts user.inspect}User Load (0.4ms)  SELECT &quot;users&quot;.* FROM &quot;users&quot; ORDER BY &quot;users&quot;.&quot;id&quot; ASC LIMIT ?  [[&quot;LIMIT&quot;, 1000]]</code></pre><p>Rails 6.1 now supports <em>ORDER BY id</em> for ActiveRecord batch processing methodslike <em>find_each</em>, <em>find_in_batches</em>, and <em>in_batches</em>. This would allow us toretrieve the records in ascending or descending order of <em>ID</em>.</p><pre><code class="language-ruby">&gt; User.find_each(order: :desc){|user| puts user.inspect}User Load (0.4ms)  SELECT &quot;users&quot;.* FROM &quot;users&quot; ORDER BY &quot;users&quot;.&quot;id&quot; DESC LIMIT ?  [[&quot;LIMIT&quot;, 1000]]</code></pre><pre><code class="language-ruby">&gt; User.find_in_batches(order: :desc) do |users|&gt;   users.each do |user|&gt;     puts user.inspect&gt;   end&gt; endUser Load (0.3ms)  SELECT &quot;users&quot;.* FROM &quot;users&quot; ORDER BY &quot;users&quot;.&quot;id&quot; DESC LIMIT ?  [[&quot;LIMIT&quot;, 1000]]</code></pre><pre><code class="language-ruby">&gt; User.in_batches(order: :desc) do |users|&gt;   users.each do |user|&gt;     puts user.inspect&gt;   end&gt; end(0.2ms)  SELECT &quot;users&quot;.&quot;id&quot; FROM &quot;users&quot; ORDER BY &quot;users&quot;.&quot;id&quot; DESC LIMIT ?  [[&quot;LIMIT&quot;, 1000]]User Load (0.2ms)  SELECT &quot;users&quot;.* FROM &quot;users&quot; WHERE &quot;users&quot;.&quot;id&quot; = ?  [[&quot;id&quot;, 101]]</code></pre><p>Points to remember:</p><ul><li>The <em>ORDER BY</em> clause only works with the primary key column.</li><li>Valid values for the <em>ORDER BY</em> clause are <em>[:asc,:desc]</em> and it's casesensitive. If we use caps or title case (like <em>DESC</em> or <em>Asc</em>) then we'll getan <em>ArgumentError</em> as shown below.</li></ul><pre><code class="language-ruby">&gt; User.find_in_batches(order: :DESC) do |users|&gt;   users.each do |user|&gt;     puts user.inspect&gt;   end&gt; endTraceback (most recent call last):        2: from (irb):5        1: from (irb):6:in `rescue in irb_binding'ArgumentError (unknown keyword: :order)</code></pre><p>Check out the <a href="https://github.com/rails/rails/pull/30590">pull request</a> for moredetails.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 deprecates structure:dump/load rake tasks]]></title>
       <author><name>Chetan Gawai</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-deprecates-rails-db-structure-dump"/>
      <updated>2020-09-22T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-deprecates-rails-db-structure-dump</id>
      <content type="html"><![CDATA[<p>Rails 6.1 <a href="https://github.com/rails/rails/pull/39470">deprecates</a><code>rails db:structure:load</code> and <code>rails db:structure:dump</code> tasks.</p><p>Before Rails 6.1, executing <code>rake db:schema:dump</code> would dump <code>db/schema.rb</code>file. And executing <code>rake db:structure:dump</code> would dump <code>db/structure.sql</code> file.</p><p>Rails provides <code>config.active_record.schema_format</code> setting for which the validvalues are <code>:ruby</code> or <code>:sql</code>. However, since there are specific tasks for<code>db:structure</code> and <code>db:schema</code> this value was not really being used.</p><h4>Changes in Rails 6.1</h4><p>In Rails 6.1 the Rails team decided to combine the two different tasks into asingle task. In Rails 6.1 <code>rails db:structure:dump</code> and<code>rails db:structure:load</code> have been deprecated and the following message wouldbe shown.</p><pre><code class="language-ruby">Using `bin/rails db:structure:dump` is deprecated and will be removed in Rails 6.2. Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:dump` instead.</code></pre><p>Now Rails will start taking into the account value set for<code>config.active_record.schema_format</code>.</p><p><code>rails db:schema:dump</code> and <code>rails db:schema:load</code> would do the right thing basedon the value set for <code>config.active_record.schema_format</code>.</p><p>Check out the <a href="https://github.com/rails/rails/pull/39470">pull request</a> for moredetails on this.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 adds --minimal option support]]></title>
       <author><name>Sandip Mane</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-adds-minimal-option-support"/>
      <updated>2020-09-08T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-adds-minimal-option-support</id>
      <content type="html"><![CDATA[<p><code>rails new my_app</code> creates a new Rails application fully loaded with all thefeatures.</p><p>If we want to omit some of the features then we needed to skip them like this.</p><pre><code class="language-bash"># before Rails 6.1$ rails new tiny_app    --skip-action-cable    --skip-action-mailer    --skip-action-mailbox    --skip-action-text    --skip-active-storage    --skip-bootsnap    --skip-javascript    --skip-spring    --skip-system-test    --skip-webpack-install    --skip-turbolinks</code></pre><p>Before Rails 6.1 it was not possible to skip things like <code>active_job</code> and<code>jbuilder</code>.</p><h2>Rails 6.1</h2><p>Rails 6.1 added a new option <code>--minimal</code>.</p><pre><code class="language-bash">$ rails new tiny_app --minimal</code></pre><p>All the following are excluded from this minimal Rails application.</p><ul><li>action_cable</li><li>action_mailbox</li><li>action_mailer</li><li>action_text</li><li>active_job</li><li>active_storage</li><li>bootsnap</li><li>jbuilder</li><li>spring</li><li>system_tests</li><li>turbolinks</li><li>webpack</li></ul><p>We can bundle webpack in this minimal app like this.</p><pre><code class="language-bash">$ rails new tiny_app --minimal webpack=react</code></pre><p>Database option can also be passed.</p><pre><code class="language-bash">$ rails new tiny_app --minimal --database postgresql webpack=react</code></pre><p>Check out the <a href="https://github.com/rails/rails/pull/39282">pull request</a> for moredetails on this.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 raises error on rollback when using multiple database]]></title>
       <author><name>Srijan Kapoor</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-raises-on-db-rollback-for-multiple-database-applications"/>
      <updated>2020-08-12T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-raises-on-db-rollback-for-multiple-database-applications</id>
      <content type="html"><![CDATA[<p>Rails 6.1 adds support to handle <code>db:rollback</code> in case of multiple databaseapplication.</p><p>Prior to this change, on executing <code>db:rollback</code> Rails used to rollback thelatest migration from the primary database. If we passed on a <code>[:NAME]</code> optionalong with to specify the database, we used to get an error. Check out the<a href="https://github.com/rails/rails/issues/38513">issue</a> for more details.</p><h4>Rails 6.0.0</h4><pre><code class="language-ruby">&gt; rails db:rollback:secondaryrails aborted!Don't know how to build task `db:rollback:secondary` (See the list of available tasks with `rails --tasks`)Did you mean?  db:rollback</code></pre><p>Staring with Rails 6.1, we need to pass the database name along with<code>db:rollback:[NAME]</code> otherwise a <code>RuntimeError</code> is raised.</p><h4>Rails 6.1.0</h4><pre><code class="language-ruby">&gt; rails db:rollbackrails aborted!You're using a multiple database application. To use `db:migrate:rollback` you must run the namespaced task with a VERSION. Available tasks are db:migrate:rollback:primary and db:migrate:rollback:secondary.&gt; rails db:rollback:primary== 20200731130500 CreateTeams: reverting ======================================-- drop_table(:teams)   -&gt; 0.0060s== 20200731130500 CreateTeams: reverted (0.0104s) =============================</code></pre><p>Check out the <a href="https://github.com/rails/rails/pull/38770">pull request</a> for moredetails on this.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 deprecates the use of exit statements in transaction]]></title>
       <author><name>Sandip Mane</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-deprecates-the-use-of-return-break-or-throw-to-exit-a-transaction-block"/>
      <updated>2020-08-04T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-deprecates-the-use-of-return-break-or-throw-to-exit-a-transaction-block</id>
      <content type="html"><![CDATA[<p>Rails 6.1 deprecates the use of <code>return</code>, <code>break</code> or <code>throw</code> to exit atransaction block.</p><h4>return / break</h4><pre><code class="language-ruby">&gt;&gt; Post.transaction do&gt;&gt;   @post.update(post_params)&gt;&gt;&gt;&gt;   break # or return&gt;&gt; end# =&gt; TRANSACTION (0.1ms)  begin transaction# =&gt; DEPRECATION WARNING: Using `return`, `break` or `throw` to exit a transaction block is# =&gt; deprecated without replacement. If the `throw` came from# =&gt; `Timeout.timeout(duration)`, pass an exception class as a second# =&gt; argument so it doesn't use `throw` to abort its block. This results# =&gt; in the transaction being committed, but in the next release of Rails# =&gt; it will rollback.# =&gt; TRANSACTION (0.8ms)  commit transaction</code></pre><h4>throw</h4><pre><code class="language-ruby">&gt;&gt; Timeout.timeout(1) do&gt;&gt;   Post.transaction do&gt;&gt;     @post.update(post_params)&gt;&gt;&gt;&gt;     sleep 3 # simulate slow request&gt;&gt;   end&gt;&gt; end# =&gt; TRANSACTION (0.1ms)  begin transaction# =&gt; DEPRECATION WARNING: Using `return`, `break` or `throw` to exit a transaction block is# =&gt; deprecated without replacement. If the `throw` came from# =&gt; `Timeout.timeout(duration)`, pass an exception class as a second# =&gt; argument so it doesn't use `throw` to abort its block. This results# =&gt; in the transaction being committed, but in the next release of Rails# =&gt; it will rollback.# =&gt; TRANSACTION (1.6ms)  commit transaction# =&gt; Completed 500 Internal Server Error in 1022ms (ActiveRecord: 3.2ms | Allocations: 9736)# =&gt; Timeout::Error (execution expired)</code></pre><p>Here, even when the error was thrown the transaction is committed. This issomething which is going to change in the future versions.</p><p>This is done because currently, when a transaction block is wrapped in<code>Timeout.timeout(duration)</code> i.e. without second argument(an exception class)then it uses <code>throw</code> to exit the transaction.</p><h4>Solution</h4><pre><code class="language-ruby">&gt;&gt; Timeout.timeout(1, Timeout::Error) do&gt;&gt;   Post.transaction do&gt;&gt;     @post.update(post_params)&gt;&gt;&gt;&gt;     sleep 3 # simulate slow request&gt;&gt;   end&gt;&gt; end# =&gt; TRANSACTION (0.1ms)  begin transaction# =&gt; TRANSACTION (0.7ms)  rollback transaction# =&gt; Timeout::Error (execution expired)</code></pre><p>Check out the <a href="https://github.com/rails/rails/pull/29333">pull request</a> for moredetails on this.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 creates abstract classes in multiple database mode]]></title>
       <author><name>Akhil Gautam</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-automatically-generates-abstract-class-when-using-multiple-databases"/>
      <updated>2020-08-04T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-automatically-generates-abstract-class-when-using-multiple-databases</id>
      <content type="html"><![CDATA[<p>Rails started supporting multiple databases from Rails 6.0. To use a specificdatabase, we can specify the database connection in the model using<code>connects_to</code>. In the following case we want <code>Person</code> model to connect to <code>crm</code>database.</p><pre><code class="language-ruby">class Person &lt; ApplicationRecordconnects_to database: { writing: :crm }end</code></pre><p>As the application grows, more and more models start sharing the same database.Now a lot of models may contain <code>connects_to</code> call to the same database.</p><pre><code class="language-ruby">class Person &lt; ApplicationRecordconnects_to database: { writing: :crm }endclass Order &lt; ApplicationRecordconnects_to database: { writing: :crm }endclass Sale &lt; ApplicationRecordconnects_to database: { writing: :crm }end</code></pre><p>In order to avoid the duplication, we can create an abstract class connecting toa database and manually inherit all other models from that class. This couldlook like this.</p><pre><code class="language-ruby">class CrmRecord &lt; ApplicationRecordself.abstract_class = trueconnects_to database: { writing: :crm }endclass Person &lt; CrmRecordendclass Order &lt; CrmRecordendclass Sale &lt; CrmRecordend</code></pre><h4>Rails 6.1</h4><p>Before Rails 6.1 we had no choice but to create that abstract class manually.Rails 6.1 allows us to generate an abstract class when we are generating a modelusing <code>scaffold</code>.</p><pre><code class="language-bash">$ rails g scaffold Person name:string --database=crm</code></pre><p>It creates an abstract class with the database's name appended with <code>Record</code>.The generated model automatically inherits from the new abstract class.</p><pre><code class="language-ruby"># app/models/users_record.rbclass CrmRecord &lt; ApplicationRecordself.abstract_class = trueconnects_to database: { writing: :crm }end# app/models/admin.rbclass Person &lt; CrmRecordend</code></pre><p>If the abstract class already exists, it is not created again. We can also usean existing class as the abstract class by passing <code>parent</code> option to thescaffold command.</p><pre><code class="language-bash">$ rails g scaffold Customer name:string --database=crm --parent=PrimaryRecord</code></pre><p>This skips generating <code>CrmRecord</code> class as we have specified Rails to use<code>PrimaryRecord</code> abstract class as its parent.</p><p>Check out the <a href="https://github.com/rails/rails/pull/39866">pull request</a> for moredetails on this.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 adds annotate_rendered_view_with_filenames for views]]></title>
       <author><name>Akhil Gautam</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-adds-annotate_rendered_view_with_filenames-to-annotate-html-output"/>
      <updated>2020-07-29T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-adds-annotate_rendered_view_with_filenames-to-annotate-html-output</id>
      <content type="html"><![CDATA[<p>Rails 6.1 makes it easier to debug rendered HTML by adding the name of eachtemplate used.</p><h4>Rails 6.1</h4><p>Add the following line in <code>development.rb</code> file to enable this feature.</p><pre><code class="language-ruby">config.action_view.annotate_rendered_view_with_filenames = true</code></pre><p>Now the rendered HTML will contain comment indicating the beginning and end ofeach template.</p><p>Here is an example.</p><p><img src="/blog/images/images_used_in_blog/2020/rails-6-1-adds-annotate_rendered_view_with_filenames-to-annotate-html-output/annotate_html_with_template_name.png" alt="Annotated HTML output"></p><p>In the image we can see the <code>begin</code> and <code>end</code> for each of the templates. Ithelps a lot in debugging webpages to find out which template is rendered. Checkout the <a href="https://github.com/rails/rails/pull/38848">pull request</a> for moredetails on this.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 allows configuring default value of enum attributes]]></title>
       <author><name>Abhay Nikam</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-allows-enums-attributes-to-have-default-value"/>
      <updated>2020-07-21T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-allows-enums-attributes-to-have-default-value</id>
      <content type="html"><![CDATA[<p>Rails 6.1 makes it easier to configure a default value for Active Record enumattributes.</p><p>Let's take an example of blog posts with status and category columns.</p><pre><code class="language-ruby">class Post &lt; ApplicationRecord  enum status: %i[draft reviewed published]  enum category: { rails: &quot;Rails&quot;, react: &quot;React&quot; }end</code></pre><p>Before Rails 6.1, defaults for enum attributes can be configured by applying<code>default</code> on the database level.</p><pre><code class="language-ruby">class AddColumnStatusToPosts &lt; ActiveRecord::Migration[6.0]  def change    add_column :posts, :status, :integer, default: 0    add_column :posts, :category, :string, default: &quot;Rails&quot;  endend</code></pre><p>After Rails 6.1, defaults for enum attributes can be configured directly in thePost model using <code>_default</code> option.</p><pre><code class="language-ruby">class Post &lt; ApplicationRecord  enum status: %i[draft reviewed published], _default: &quot;draft&quot;  enum category: { rails: &quot;Rails&quot;, react: &quot;React&quot; }, _default: &quot;Rails&quot;end</code></pre><p>The new approach to set enum defaults has following advantages. Let's understandkeeping the context of Post model with category as an example.</p><ul><li>When the category default value changes from <code>Rails</code> to <code>React</code>. We have toadd a new migration in Rails 6 and previous versions to update the databasecolumn default.</li><li>Let say the default value for post category(i.e: <code>Rails</code>) is removed from theenum from Post model. Rails 6 and previous versions wouldn't throw anexception and continue to work without setting any default value. Rails 6.1with new syntax would raise an exception.</li></ul><p>Check out the <a href="https://github.com/rails/rails/pull/39820">pull request</a> for moredetails on this.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 adds support for where with a comparison operator]]></title>
       <author><name>Abhay Nikam</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-adds-support-for-where-with-comparison-operator"/>
      <updated>2020-07-14T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-adds-support-for-where-with-comparison-operator</id>
      <content type="html"><![CDATA[<p><strong><em>Please note that the PR discussed in this blog was<a href="https://github.com/rails/rails/issues/41271">reverted</a>.</em></strong></p><p>Rails 6.1 adds support to comparison operator in the <code>where</code> clause. The fourcomparison operators supported are:</p><ul><li>Greater than (&gt;).</li><li>Greater than equal to (&gt;=).</li><li>Less than (&lt;).</li><li>Less than equal to (&lt;=).</li></ul><p>The comparison operator is also supported by the finder methods in ActiveRecordwhich internally uses where clause, for example: <code>find_by</code>, <code>destroy_by</code>,<code>delete_by</code>.</p><p>The new style for comparisons has to follow advantages:</p><ul><li>The <code>where</code> clause with the comparison operator doesn't raise an exceptionwhen <code>ActiveRecord::Relation</code> uses ambiguous column name.</li><li>The <code>where</code> clause with the comparison operator handle proper precision of thedatabase columns.</li></ul><p>Before Rails 6.1, to add a condition with comparison in where clause, we had toadd raw SQL notation.</p><h4>Rails 6.0.0</h4><pre><code class="language-ruby">&gt;&gt; Post.where(&quot;DATE(published_at) &gt; DATE(?)&quot;, Date.today)# =&gt; &lt;ActiveRecord::Relation [...]&gt;&gt;&gt; Post.find_by(&quot;likes &lt; ?&quot;, 10)# =&gt; &lt;ActiveRecord::Relation [...]&gt;# Following query on execution would raise exception.&gt;&gt; Post.joins(:comments).where(&quot;likes &gt; 10&quot;)# =&gt; ambiguous column name: id</code></pre><h4>Rails 6.1.0</h4><pre><code class="language-ruby">&gt;&gt; Post.where(&quot;published_at &gt;&quot;: Date.today)# =&gt; &lt;ActiveRecord::Relation [...]&gt;&gt;&gt; Post.find_by(&quot;likes &lt;&quot;: 10)# =&gt; &lt;ActiveRecord::Relation [...]&gt;# Following query on execution would NOT raise exception.&gt;&gt; Post.joins(:comments).where(&quot;likes &gt;&quot;: 10)# =&gt; &lt;ActiveRecord::Relation [...]&gt;</code></pre><p>Check out the <a href="https://github.com/rails/rails/pull/39613">pull request</a> for moredetails on this.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 tracks Active Storage variant in the database]]></title>
       <author><name>Abhay Nikam</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-tracks-active-storage-variant-in-the-database"/>
      <updated>2020-06-30T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-tracks-active-storage-variant-in-the-database</id>
      <content type="html"><![CDATA[<p>Active Storage variants are the transformation of the original image. Thesevariants can be used as thumbnails, avatars, etc.</p><p>Active Storage generates variants <strong>on demand</strong> by downloading the originalimage. The image is transformed into a variant and is stored to the third partyservices like S3.</p><p>When a request to fetch a variant for an Active Storage object is made, Railschecks if the variant is already been processed and is already available on S3or not. But to do so Rails has to make a call to find out if the variant isavailable on S3. This extra call adds to the latency.</p><p>Active Storage has to wait until the image variant check call is completedbecause S3 might not return the image when a GET request is made due to eventual<a href="https://docs.aws.amazon.com/AmazonS3/latest/dev/Introduction.html#ConsistencyModel">consistency</a>.This way Rails avoid downloading a broken image from S3 and uploading brokenimage variant to S3 in case the variant is not present.</p><p>In Rails 6.1, Active Storage tracks the presence of the variant in the database.This change avoids unnecessary variant presence remote request made to the S3and directly fetches or generates a image variant.</p><p>In Rails 6.1, the configuration to allow variant tracking in the database is bydefault set to true.</p><pre><code class="language-ruby">config.active_storage.track_variants: true</code></pre><p>Check out the <a href="https://github.com/rails/rails/pull/37901">pull request</a> for moredetails on this.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 introduces class_names helper]]></title>
       <author><name>Abhay Nikam</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-introduces-class_names-helper"/>
      <updated>2020-02-04T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-introduces-class_names-helper</id>
      <content type="html"><![CDATA[<p>Rails 6.1 adds <a href="https://github.com/rails/rails/pull/37918">class_names</a> viewhelper method to conditionally add CSS classes. <code>class_names</code> helper acceptsString, Hash and Array as arguments and returns string of class names built fromarguments.</p><p>Before Rails 6.1, conditional classes were added by using conditionalstatements. Let's take an example of adding an active class to navigation linkbased on the current page.</p><h4>Rails 6.0.0</h4><pre><code class="language-erb">&lt;li class=&quot;&lt;%= current_page?(dashboards_path) ? 'active' : '' %&gt;&quot;&gt;  &lt;%= link_to &quot;Home&quot;, dashboards_path %&gt;&lt;/li&gt;</code></pre><h4>Rails 6.1.0</h4><pre><code class="language-ruby">&gt;&gt; class_names(active: current_page?(dashboards_path))=&gt; &quot;active&quot;# Default classes can be added with conditional classes&gt;&gt; class_names('navbar', { active: current_page?(dashboards_path) })=&gt; &quot;navbar active&quot;# class_names helper rejects empty strings, nil, false arguments.&gt;&gt; class_names(nil, '', false, 'navbar', {active: current_page?(dashboards_path)})=&gt; &quot;navbar active&quot;</code></pre><pre><code class="language-erb">&lt;li class=&quot;&lt;%= class_names(active: current_page?(dashboards_path)) %&gt;&quot;&gt;  &lt;%= link_to &quot;Home&quot;, dashboards_path %&gt;&lt;/li&gt;</code></pre><p>Check out the <a href="https://github.com/rails/rails/pull/37918">pull request</a> for moredetails on this.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Rails 6.1 adds *_previously_was attribute methods]]></title>
       <author><name>Abhay Nikam</name></author>
      <link href="https://www.bigbinary.com/blog/rails-6-1-adds-_previously_was-attribute-methods"/>
      <updated>2019-12-03T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/rails-6-1-adds-_previously_was-attribute-methods</id>
      <content type="html"><![CDATA[<p>Rails 6.1 adds <a href="https://github.com/rails/rails/pull/36836">*_previously_was</a>attribute methods for dirty tracking the previous attribute value after themodel is saved or reset. <code>*_previously_was</code> returns the previous attribute valuethat was changed before the model was saved</p><p>Before Rails 6.1, to retrieve the previous attribute value, we used<code>*_previous_change</code> or<a href="https://apidock.com/rails/ActiveModel/Dirty/previous_changes">previous_changes</a>.</p><p>Here is how it can be used.</p><h4>Rails 6.0.0</h4><pre><code class="language-ruby">&gt;&gt; user = User.new=&gt; #&lt;User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil&gt;&gt;&gt; user.name = &quot;Sam&quot;# *_was returns the original value. In this example, the name was initially nil.&gt;&gt; user.name_was=&gt; nil&gt;&gt; user.save!# After save, the original value is set to &quot;Sam&quot;. To retrieve the# previous value, we had to use `previous_changes`.&gt;&gt; user.previous_changes[:name]=&gt; [nil, &quot;Sam&quot;]</code></pre><h4>Rails 6.1.0</h4><pre><code class="language-ruby">&gt;&gt; user = User.find_by(name: &quot;Sam&quot;)=&gt; #&lt;User id: 1, name: &quot;Sam&quot;, email: nil, created_at: &quot;2019-10-14 17:53:06&quot;, updated_at: &quot;2019-10-14 17:53:06&quot;&gt;&gt;&gt; user.name = &quot;Nick&quot;&gt;&gt; user.name_was=&gt; &quot;Sam&quot;&gt;&gt; user.save!&gt;&gt; user.previous_changes[:name]=&gt; [&quot;Sam&quot;, &quot;Nick&quot;]# *_previously_was returns the previous value.&gt;&gt; user.name_previously_was=&gt; &quot;Sam&quot;# After reload, all the dirty tracking# attributes is reset.&gt;&gt; user.reload&gt;&gt; user.name_previously_was=&gt; nil</code></pre><p>Check out the <a href="https://github.com/rails/rails/pull/36836">pull request</a> for moredetails on this.</p>]]></content>
    </entry>
     </feed>