Rails 4 - how to give alias names to includes() and joins() in active record querying

前端 未结 2 1764
日久生厌
日久生厌 2021-02-02 15:08

How can I give an alias name for e.g. includes()? Following is given:

  • User: active record model
  • Student: active record model, inherits from
2条回答
  •  滥情空心
    2021-02-02 15:46

    I'm going to take another approach to this issue: instead of trying to control the alias names on your queries with an .alias method, I'll let Rails / Arel handle that and just look the correct table name (aliased or not) up whenever there is need for it within a scope.

    Add this helper method to your model, that you'd be able to call from an scope to know if the scope is being used within a JOIN that has the table name aliased (multiple joins on the same table), or if on the other hand the scope has no alias for the table name.

    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
    

    This uses current_scope as the base object to look for the arel table. I'm calling source on that object to obtain an Arel::SelectManager that in turn will give you the current table on the #left. There are two options there: either you have there an Arel::Table (no alias, table name is on #name) or you have an Arel::Nodes::TableAlias with the alias on its #right.

    Now you only need to use that on your order statements (untested):

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

    Related questions:

    • ActiveRecord query with alias'd table names (where I first used this approach).
    • Join the same table twice with conditions

提交回复
热议问题