Rails 6.1.1 allows `where` to reference associations via joined table alias name...
source link: https://blog.saeloun.com/2021/01/25/rails-6-allow-where-clause-reference-association-by-alias-name
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Rails 6.1 has added a feature wherein we can
specify an alias name of the model in the where
clause.
Let’s say we have an Employee
model as below:
class Employee < ActiveRecord::Base
has_many :subordinates, class_name: "Employee", foreign_key: :manager_id
belongs_to :manager, class_name: "Employee"
end
Employees without a manager will have manager_id
as nil
.
Before
Let’s take a scenario where we need to fetch all employees whose manager name is Sam
.
There can be two ways to fetch this data.
Employee.find_by(name: "Sam").subordinates
SELECT "employees".* FROM "employees" WHERE "employees"."name" = $1 LIMIT $2 [["name", "Sam"], ["LIMIT", 1]]
SELECT "employees".* FROM "employees" WHERE "employees"."manager_id" = $1 /* loading for inspect */ LIMIT $2 [["manager_id", "e4f2c753-6057-4952-9947-d1a543b2d1c7"], ["LIMIT", 11]]
=> #<ActiveRecord::AssociationRelation [#<Employee id: "3e584548......
Employee.joins(:manager).where(manager: { name: "Sam" })
ActiveRecord::StatementInvalid (PG::UndefinedTable: ERROR: missing FROM-clause entry for table "manager")
LINE 1: ..._employees"."id" = "employees"."manager_id" WHERE "manager"....
The second query throws an error of missing FROM-clause entry
.
It expects manager
to reference the employees
table, which Rails was not able to figure out.
After
To fix the above issue, Rails 6.1.1 added a fix that allows the alias name to be used
as a reference for the employees
table in the where
clause.
Employee.find_by(name: "Sam").subordinates
SELECT "employees".* FROM "employees" WHERE "employees"."name" = $1 LIMIT $2 [["name", "Sam"], ["LIMIT", 1]]
SELECT "employees".* FROM "employees" WHERE "employees"."manager_id" = $1 /* loading for inspect */ LIMIT $2 [["manager_id", "e4f2c753-6057-4952-9947-d1a543b2d1c7"], ["LIMIT", 11]]
=> #<ActiveRecord::AssociationRelation [#<Employee id: "3e584548......
Employee.joins(:manager).where(manager: { name: "Sam" })
SELECT "employees".* FROM "employees" INNER JOIN "employees" manager ON manager."id" = "employees"."manager_id" WHERE "manager"."name" = $1 /* loading for inspect */ LIMIT $2 [["name", "Sam"], ["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Employee id: "3e584548......
This use-case is mostly useful for self-referential models and aliased tables.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK