3 Lesser-Known Rails Features for Querying Databases

Improve your Rails app’s performance, flexibility, and data integrity with these three useful features.

ActiveRecord Excluding

The .excluding method of Active Record 5.0 is a new powerful tool added in Rails 7, that allows you to exclude specific columns from a query result.

This method can be used in a variety of situations, such as:

Let’s assume you have a list of users and you want to send an email to your entire database, except for this list.

Usually, you would do something like:

1
User.where.not(id: users.map(&:id)

The .excluding is more concise and easier to read. It is also more efficient.

1
User.all.excluding(users)

ActiveRecord Strict Loading

It is a feature introduced in Rails 6.1 that allows you to force associations to be loaded eagerly.

Eager loading is a technique that loads all of an object’s associations at the time it is loaded. This can improve the performance of applications by avoiding N + 1 queries.

ActiveRecord Strict Loading works by enabling the strict_loading mode for an association. When the strict_loading mode is enabled, Active Record will raise an exception if the association is loaded lazily.

1
2
3
class Post < ApplicationRecord
  has_many :comments, strict_loading: true
end
1
2
3
4
5
post = Post.first
post.comments

# => ActiveRecord::StrictLoadingViolationError
# "Post" is marked as strict_loading. The Post association named ":comments" cannot be lazily loaded.
1
2
3
4
5
6
7
8
post = Post.includes(:comments).first

# => Post Load (0.3ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT ? [["LIMIT", 1]]
# => Comment Load (0.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ? [["post_id", 1]]

#=> <Post:0x00000001054af780 id: 1>
post.comments
#=> [<Comment:0x00000001054aed80 id: 1, project_id: 1, body: "Great Post">]

ActiveRecord Strict Loading can be useful for applications that need to guarantee that all associations are loaded eagerly. However, it is important to note that strict loading can reduce the flexibility of your code.

Here are some examples of how ActiveRecord Strict Loading can be used:

Generated Columns

Generated columns are a feature introduced in Postgres 12 that is now supported by Rails 7. It allows you to create columns of data that are calculated dynamically.

To create a generated column in a migration, use the add_column method with the :virtual argument.

There are two different types of generated columns: Virtual (computed at read) Stored (computed and cached at write – create/update)

For example, the following code creates a generated column called full_name that calculates the full name of a user:

1
2
3
4
5
6
7
8
9
class AddNameVirtualColumnToUsers < ActiveRecord::Migration [7.0]
  def change
    add_column :users, :full_name, :virtual,
      type: string,
      as: "first_name || ' ' || last_name",
      stored: true
    end
  end
end

This code creates a generated column called full_name that stores the full name of a user. The value of the column is calculated using the expression first_name || ' ' || last_name.

The value of the generated column can be stored in memory or in the database. To store the value of the generated column in memory, use the :stored argument with the value false. To store the value of the generated column in the database, use the :stored argument with the value true.