【问题标题】:Rails 4 scope through status on related objects?Rails 4范围通过相关对象的状态?
【发布时间】:2014-03-13 02:26:01
【问题描述】:

我想在我编写的 rails 作用域中删除一个实例方法,这样我就可以拥有一个更好的、可链接的作用域。

我有一个模型 Offeringhas_many :assetsAssets 有一个列 status。我在Offering 上创建了一个范围,如下所示:

scope :available, -> { where(approved_for_sale: true).reject{|offering| !offering.assets_ready} }

其中assets_readyOffering 上的一个方法:

def assets_ready
  assets.inject(1) {|memo, asset| memo && asset.ready_status_symbol == :ready}
end

由于拒绝返回一个数组,我想找到一种方法来编写不需要实例方法的范围。

【问题讨论】:

    标签: sql ruby-on-rails scope


    【解决方案1】:

    试试这个:

    scope :available, -> { 
                          where(approved_for_sale: true)
                          .where("NOT EXISTS (SELECT 1 from assets a WHERE 
                            a.offering_id = offerings.id AND a.ready_status <> 'ready')")
                         }
    

    受蒂姆在此处对 SQL 问题的回答启发的解决方案:Select parent if all children meet criteria

    Market 的答案适用于某些用例,但 group 子句通过链接和计数引入了一些奇怪的行为;例如如果可用范围使用 .group,则 Offering.available.count 将返回哈希而不是固定编号

    【讨论】:

      【解决方案2】:

      要实现可链接范围,您必须使用来自 ActiveRecord 查询 api 的方法。

      假设status 列类型是字符串,我认为您需要类似:

      scope :available, -> {
          where("offerings.approved_for_sale = ?", true).
          joins("INNER JOIN assets AS all_as ON all_as.offering_id = offerings.id
               LEFT JOIN assets AS ready_as ON ready_as.id = all_as.id AND ready_as.status = 'ready'").
          group("all_as.offering_id").
          having("COUNT(all_as.id) = COUNT(ready_as.id)")
      }
      

      它返回ActiveRecord::Relation而不是Array

      【讨论】:

      • 如果 any 资产的状态为:ready,而不是 all,这似乎返回了一个产品。否则,一个好的开始。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-23
      • 1970-01-01
      相关资源
      最近更新 更多