Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save phlegx/add77d24ebc57f211e8b to your computer and use it in GitHub Desktop.
Save phlegx/add77d24ebc57f211e8b to your computer and use it in GitHub Desktop.
Rails 4 - how to give alias names to includes() and joins() in active record quering
See question on stack overflow: http://stackoverflow.com/questions/28595636/rails-4-how-to-give-alias-names-to-includes-and-joins-in-active-record-que
- Model Student and model Teacher are both STI models with super class model User
- Model Place is a STI model with super class model Location
- includes() and joins(), both fails
Rails alias naming convention (includes() and joins())
- One model as parameter
- is base model (includes(:users))
-> alias name is class name of base name (in plural)
- is STI model (includes(:students))
-> alias name is class name of base name (in plural)
- More models as parameters
- have more STI models with same base class name (includes(:students, :teachers))
- first parameter (STI) -> alias name is class name of base name (in plural)
- all other parameters (STI) -> alias name is {STI name plural}_projects
- One base model and one STI model with same base model (includes(:users, :teachers))
- first parameter (base) -> alias name is class name of base name (in plural)
- second parameter (STI) -> alias name is {STI name plural}_projects
- More STI models with different base model (includes(:students, :places))
-> alias name is class name of base name (in plural)
The alias name depends on the parameter order in includes() or joins() and if the parameters have another parameter with same base class.
# all models
class Project < ActiveRecord::Base
has_many :students
has_many :teachers
has_many :places
end
class Location < ActiveRecord::Base
belongs_to :project
end
class Place < Location
end
class User < ActiveRecord::Base
belongs_to :project
end
class Student < User
end
class Teacher < User
end
# CASE ONE (single STI model include)
# This examples works:
Project.all.includes(:students).order('users.name ASC') # order on students
Project.all.joins(:students).order('users.name ASC') # order on students
# This examples fails
Project.all.includes(:students).order('students.name ASC')
Project.all.includes(:students).order('students_projects.name ASC')
Project.all.joins(:students).order('students.name ASC')
Project.all.joins(:students).order('students_projects.name ASC')
# CASE TWO (double STI model include with same base model)
# This examples works:
Project.all.includes(:students, :teachers).order('users.name ASC') # order on students
Project.all.includes(:students, :teachers).order('teachers_projects.name ASC') # order on teachers
Project.all.includes(:students, :places).order('locations.name ASC') # order on places
Project.all.joins(:students, :teachers).order('users.name ASC') # order on students
Project.all.joins(:students, :teachers).order('teachers_projects.name ASC') # order on teachers
Project.all.joins(:students, :places).order('locations.name ASC') # order on places
# This examples fails:
Project.all.includes(:students, :teachers).order('teachers.name ASC')
Project.all.includes(:students, :teachers).order('students.name ASC')
Project.all.includes(:students, :teachers).order('students_projects.name ASC')
Project.all.includes(:students, :places).order('places.name ASC')
Project.all.joins(:students, :teachers).order('teachers.name ASC')
Project.all.joins(:students, :teachers).order('students.name ASC')
Project.all.joins(:students, :teachers).order('students_projects.name ASC')
Project.all.joins(:students, :places).order('places.name ASC')
@bartlomiejmatlega
Copy link

Thanks 👍 Really useful.
Is it possible to force JOIN alias? It would be really useful for dynamically created queries

Then these two would work:

Project.all.joins(:students, :teachers).order('teachers_projects.name ASC') # fails
Project.all.joins(:students, :teachers).order('students_projects.name ASC') # works

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment