【问题标题】:best way to concatenate scope results连接范围结果的最佳方法
【发布时间】:2018-05-20 16:05:31
【问题描述】:

我有两个范围。一个检查 db 列是否为空或空字符串,另一个检查相反(非空,非空字符串)

scope :has_something, where('something IS NOT NULL AND something != ""')
scope :has_no_something, where('something IS NULL OR something = ""')

我想最终将两个结果连接起来。即有东西的结果后面跟着没有东西的结果

我的第一次尝试是这样的:

def self.with_something_data_first
  has_something + has_no_something
end

这会导致:

NoMethodError: 未定义的方法 `order' 用于#

因为这个方法是和一个订单结合的

Model.with_something_data_first.order(:created_at).reverse_order.limit(20)

如果我可以在一个范围内执行此操作,它会返回所有包含数据的记录,然后是所有包含 null 或空字符串的记录。显然,您不能按 nil 订购,但也许您知道解决这个问题的棘手方法?

【问题讨论】:

  • 问题是当你连接“+”时,你得到一个数组,而不是一个 Active Record,所以你不能使用 order

标签: ruby-on-rails activerecord scope


【解决方案1】:

问题是当你连接两个作用域时,你得到一个数组,而不是一个 Active Record,所以你不能使用 order。不知道这是否是最好的方法,但您可以按照获得的顺序从 id 进行新查询。就像这样:

def self.with_something_data_first
  YourModel.find((has_something + has_no_something).map{|o| o.id})
end

像这样,您可以对其应用 order 方法,因为您将拥有一个 Active Record 关系,并且它尊重您之前建立的对象的顺序。希望这会有所帮助!

【讨论】:

  • 谢谢!我最终想出了一个更适合我需要的解决方案,但我可能会走这条路。
【解决方案2】:
scope :with_something_data_first, -> { order('something IS NULL OR something == ""') }

怎么做?

something IS NULL OR something == "" 在某些内容为 null 或空字符串时计算为 1,并且由于默认顺序为 ASC,因此所有这些条目将显示在 something IS NULL OR something == "" 导致为 0 的记录之后

【讨论】:

    【解决方案3】:

    我最终想出了一个更能满足我需求的解决方案。而不是检查数据库中的空字符串和空值。我将在空字符串输入时将它们转换为空值,并使用这样的顺序将空值放在结果集的末尾。

    scope :with_post_comments_first, order('-comment DESC')
    

    【讨论】:

      【解决方案4】:

      它非常简单直接。理想情况下,您应该能够得到同时应用这两个条件的结果吗?

      如果是,请执行以下操作,

      def self.with_something_data_first
        has_something.has_no_something
      end
      

      【讨论】:

      • 这将返回一个空数组
      猜你喜欢
      • 2014-07-21
      • 1970-01-01
      • 1970-01-01
      • 2013-03-12
      • 2012-12-15
      • 1970-01-01
      • 1970-01-01
      • 2014-01-24
      • 1970-01-01
      相关资源
      最近更新 更多