Rails 4 - 如何在活动记录查询中为别名()和联接()提供别名

时间:2015-02-18 23:01:59

标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-4 activerecord arel

如何为例如别名提供别名includes()? 以下是:

  • 用户:有效记录模型
  • 学生:活动记录模型,继承自用户(STI)
  • 教师:主动记录模型,继承自用户(STI)
  • 项目:活动记录模型

这里有一些例子:

第一种情况(更多STI协会)

Project.all.includes(:students, :teachers).order('teachers_projects.name ASC') # order on teachers
Project.all.includes(:students, :teachers).order('users.name ASC') # order on students

Rails在SQL中为teachers_projects自动使用别名:teachers。如何覆盖它,以便我可以在SQL中使用别名teachers而不是teachers_projects:students获取别名users

此示例失败:

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')

第二个案例(一个STI协会)

如果我在方法:students中仅使用:teachers(没有includes()),则Rails使用STI基类名users的名称别名(不含_projects附件):students

Project.all.includes(:students).order('users.name ASC') # order on students

此示例失败:

Project.all.includes(:students).order('students.name ASC')
Project.all.includes(:students).order('students_projects.name ASC')

问题

可能存在类似:

Project.all.includes(:students).alias(students: :my_alias)

RAILS ALIAS TRACKER

https://github.com/rails/rails/blob/v4.2.0/activerecord/lib/active_record/associations/alias_tracker.rb#L59

测试应用

https://gist.github.com/phlegx/add77d24ebc57f211e8b

https://github.com/phlegx/rails_query_alias_names

1 个答案:

答案 0 :(得分:1)

我将采用另一种方法解决此问题:我不会尝试使用.alias方法控制查询中的别名,而是让Rails / Arel处理该问题并查看正确的表在范围内需要时,名称(别名与否)。

将此辅助方法添加到模型中,您可以从范围调用以了解范围是否在具有表名别名的JOIN中使用(同一个表上有多个连接) ),或者另一方面,范围没有表名的别名。

def self.current_table_name
  current_table = current_scope.arel.source.left

  case current_table
  when Arel::Table
    current_table.name
  when Arel::Nodes::TableAlias
    current_table.right
  else
    fail
  end
end

这使用current_scope作为查找arel表的基础对象。我在该对象上调用source来获取Arel::SelectManager,然后#left会在Arel::Table上为您提供当前表格。这里有两个选项:要么你有一个#name(没有别名,表名在Arel::Nodes::TableAlias上),要么你#right上有别名order

现在您只需要在Project.all.includes(:students, :teachers).order("#{current_table_name}.name ASC") Project.all.includes(:students, :teachers).order("#{current_table_name}.name ASC") Project.all.includes(:students, :teachers).order("#{current_table_name}.name ASC") 语句(未经测试)上使用它:

{{1}}

相关问题: