Rails ActiveRecord's 'none' method
29 November 2024
The none
query method in Rails ActiveRecord is a hidden gem I hadn’t come
across until this week.
It creates a relation that returns no results unless combined with other
conditions. Without using none
I’d have typically created a relation with a
where("1=0")
condition, and chained .or
and .merge
calls off it.
The none
method provides a cleaner way to do this. If no other conditions are
added to the chain it returns an empty result set without querying the database.
If other conditions are added, it drops the superfluous WHERE 1=0
condition
from the resulting SQL.
Here’s an example
projects = Project.none
projects.to_sql
# => "SELECT `projects`.* FROM `projects` WHERE (1=0)"
# if iterated, no query would actually execute
if include_active?
projects = projects.or(Project.active)
projects.to_sql
# => "SELECT `projects`.* FROM `projects`
# WHERE `projects`.`deleted` = FALSE
# AND `projects`.`archived` = FALSE"
end
if include_archived?
projects = projects.or(Project.archived)
projects.to_sql
# => "SELECT `projects`.* FROM `projects`
# WHERE (`projects`.`deleted` = FALSE
# AND `projects`.`archived` = FALSE
# OR `projects`.`archived` = TRUE)
# ORDER BY name ASC"
end
Note on the generated SQL. It may seem at first glance that the two archived checks are superfluous, but the operator precedence of the AND means that both deleted and archived need to be false to match the first condition.
When this is executed, the resulting SQL doesn’t include a straggling
WHERE 1=0
condition, and if no conditions are added to the chain it would just
return an empty result set without even querying the database.