【问题标题】:Batch search for named_scope批量搜索 named_scope
【发布时间】:2014-05-27 04:51:53
【问题描述】:

这是由其他人编写的现有代码,正在尝试对其进行增强。我是一名从事 Ruby on Rails 的 Java 开发人员,所以请体谅。

我有这样的实体

User 

交付实体,

Delivery 
belongs_to :user 

named_scope :for_abcs, :conditions => {'deliveries.xyz_type' => ['Xyz1', 'Xyz2']},

定义了许多这样的命名范围。

现在来取货,它是这样写的

 @deliveries = current_user.deliveries.send("for_abcs").with(:xyz, :sender, :receiver)
...
...
...
# few other  conditions added to @deliveries 

终于

@deliveries.sort(...)

这种排序会占用大量 sql 并产生性能问题。我想使用find_each,但find_each 仅适用于Ruby on Rails 中的活动实体,如何在不更改代码的情况下实现这一点(如果可能))

我以前也是这样的

Delevery.find_each 

无论在哪里

Delivery.find

现在我不能这样做,因为它是一个数组,在 Ruby on Rails 中执行此操作的解决方法或正确程序是什么。

编辑: 我尝试了什么:

deliveries_temp = []
@deliveries.find_each(:batch_size=>999) do |delivery_temp|
    deliveries_temp.push(delivery_temp)
end

这给了我错误

undefined method `find_each' for []:Array

type(@deliveries) 返回 ActiveRecord::NamedScope::Scope ,rails 版本 2.3.18

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-2


    【解决方案1】:

    find_each 应该适用于任何返回关系(包括范围)的东西。

    @deliveries = current_user.deliveries.for_abcs(:xyz, :sender, :receiver).find_each
    

    更新

    听起来您使用的是 Rails 2.3。 find_each 是 2.3 中的类方法,因此您需要一种方法从您的作用域中提取条件并将它们传递给 find_each。我找到了an article that looks promising,所以试试看:

    Delivery.find_each(current_user.deliveries.for_abcs.scope(:find))
    

    另外,我仍然不确定#with 在做什么。也许应该是#includes

    【讨论】:

    • 用我尝试过的内容和收到的错误编辑了我的评论。我在那里做错了吗?
    • 其实,重读你的代码就好了。 with 的定义是什么?这可能就是你需要修改的地方。
    • 对不起,我不知道它是什么,我搜索了很多以找到一个名为“with”的 Rails 术语,但我找不到。我只是忽略了它。完全不确定它是什么。 :(
    • 在您的项目(以及您正在使用的任何 gem)中搜索“def with”。
    • 不确定 with ,但我检查了@deliveries 的类型。它不是数组,它是 ActiveRecord::NamedScope::Scope 类型。这似乎是非常旧的 rails 版本。
    【解决方案2】:

    经过一周的大量研究并通过查看其源代码了解 named_scopes。我明白了问题所在。 @deliveriesActiveRecord::NamedScope::Scope 类的对象。这个类没有 find_each 方法。所以我在Delivery模型文件中写了一个新的named_scope用于限制和偏移:

    named_scope :limit_and_offset, lambda { |lim,off| { :limit => lim, :offset=>off } }
    

    在这之后,我在一个循环中调用它,传递 offset 和 limit ,例如。第一个循环有 offset=0, limit=999 ,第二个循环有 offset=999, limit=999 。我会将所有结果添加到一个空数组中。这个循环一直持续到结果大小小于限制值。这完全按照我想要的方式分批工作。

    set = 1
    total_deliveries = []
    set_limit=999
    original_condition = @deliveries
    loop do
        offset = (set-1) * set_limit
        temp_condition = original_condition.limit_and_offset(set_limit,offset)
        temp_deliveries = temp_condition.find(:all)
        total_deliveries+= temp_deliveries
        set += 1
        break if temp_deliveries.size < set_limit
    end
    @deliveries = total_deliveries.sort do |a, b|
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-06
      • 2021-01-29
      • 1970-01-01
      • 2022-06-16
      相关资源
      最近更新 更多