/ RAILS

Rails 6 ActiveRecord negative enum scopes

Rails 6 ActiveRecord added negative scopes for enums on models. This generates negative scopes for enum types defined for a field on a model.

When enums are used in a model in an Rails application, it generates corresponding scopes in order to easily query or find out if record belongs to the particular enum.

Let’s take an example.

        class Product < ApplicationRecord
            enum status: {
                sold_out:   0,
                active:     1,
                archived:   2
            }
        end

Before Rails 6

As we can see, status of the Product can either be active, inactive or archived. When we use it with enums, it generates scopes on ActiveRecord as given below.

ActiveRecord enum scopes on collection

Product.sold_out
# SELECT "products".* FROM "products" WHERE "products"."status" = $1  [["status", 0]]

Product.active
# SELECT "products".* FROM "products" WHERE "products"."status" = $1  [["status", 1]]

Product.archived
# SELECT "products".* FROM "products" WHERE "products"."status" = $1  [["status", 2]]

This can be used to get active products with the scope generated by enums defined on the model.

After Rails 6

In addition to scopes defined above, we have access to negative scopes as given below.

Product.not_sold_out
# SELECT "products".* FROM "products" WHERE "products"."status" != $1  [["status", 0]]

Product.not_active
# SELECT "products".* FROM "products" WHERE "products"."status" != $1  [["status", 1]]

Product.not_archived
# SELECT "products".* FROM "products" WHERE "products"."status" != $1  [["status", 2]]

As we can see, the scopes generated is a short hand for where.not(column_name: :enum_value).

Reference