【问题标题】:How would you go about in ordering a has_many association based on an association two levels deep?您将如何基于两层深的关联订购 has_many 关联?
【发布时间】:2019-11-19 20:21:32
【问题描述】:

我有 4 个模型

  1. 餐厅
  2. 位置
  3. 城市
  4. 状态

二分法几乎按照这个顺序流动。我遇到了我想订购的一堵墙,餐厅位置按它们所属的州的名称按升序排列。我尝试在我的 has_many 声明中执行以下操作,但出现 SQL 错误:

ArgumentError (Direction "{:state=>{:name=>:asc}}" is invalid. Valid directions are: [:asc, :desc, :ASC, :DESC, "asc", "desc", "ASC", "DESC"])

这就是我的模型的设置方式

class Restaurant < ApplicationRecord
  has_many :locations, -> { order(city: { state: { name: :asc } }) }, dependent: :destroy
end

class Location < ApplicationRecord
  belongs_to :restaurant
  belongs_to :city
end

class City < ApplicationRecord
  belongs_to :state
end

class State < ApplicationRecord
  has_many :states
end

我需要改变什么才能让它工作?

【问题讨论】:

    标签: sql ruby-on-rails postgresql associations


    【解决方案1】:

    这是从任何级别遍历到另一个级别的完整关联集:

    class Restaurant < ApplicationRecord
      has_many :locations, dependent: :destroy
      has_many :cities, through: :locations
      has_many :states, through: :cities
    end
    
    class Location < ApplicationRecord
      belongs_to :restaurant
      belongs_to :city
      has_one :state, through: :city
    end
    
    class City < ApplicationRecord
      belongs_to :state
      has_many :locations
      has_many :restaurants, through: :locations
    end
    
    class State < ApplicationRecord
      has_many :cities
      has_many :locations, through: :cities
      has_many :restaurants, through: :locations
    end
    

    .order 不接受嵌套哈希。它只接受{ foo: :asc, bar: :desc ...} 作为哈希参数和位置参数。您可以使用字符串键指定另一个表.order("states.name" =&gt; :asc) 上的列。请参阅signature 的文档。

    虽然您可以通过使用字符串 .order('states.name ASC') 或字符串键对连接表进行排序,但必须与连接一起完成,但在关联本身中定义它并不是一个好主意,因为它会产生非常令人惊讶的效果例如,如果您调用Restaurant.joins(:locations)...,它会疯狂地开始左右连接其他表并重新排序查询。

    相反,您希望创建一个按特定顺序为您提供记录的范围。

    class Location 
      # ...
      scope :order_by_state, -> { joins(:state).order('states.name ASC') }
    end
    

    【讨论】:

    • 如果我以这种方式使用提供的范围:has_many :locations, -&gt; { order_by_state }, dependent: :destroy 我得到错误:ActiveRecord::ConfigurationError (Can't join 'Location' to association named 'state'; perhaps you misspelled it?)。我是否正确执行此操作?
    • 不要将范围应用于关联。我以为我对那个很清楚。如果您想要按州排序的位置,只需执行Location.order_by_state
    • "无法将 'Location' 加入名为 'state' 的关联;也许你拼错了?"意味着您可能没有添加它应该去的关联,或者您滥用范围在实际定义之前使用它。
    • 谢谢。所以如果我理解正确的话,我必须添加一个关联扩展来在 has_many 声明中使用这个范围?
    • 不,不是。您需要放弃将在关联中使用它的想法。虽然您可以创建与应用的顺序和内容的特殊关联,但默认情况下这样做并不是一个好主意,因为顺序适用于整个查询。
    猜你喜欢
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多