【问题标题】:ActiveRecord find_each and PostgresActiveRecord find_each 和 Postgres
【发布时间】:2012-05-31 13:15:34
【问题描述】:

我收到以下错误:

PGError: ERROR:  operator does not exist: character varying >= integer
LINE 1: ...CT  "games".* FROM "games"  WHERE ("games"."uuid" >= 0) ORDE...
                                                             ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
: SELECT  "games".* FROM "games"  WHERE ("games"."uuid" >= 0) ORDER BY "games"."uuid" ASC LIMIT 1000

当我尝试这样做时:

Game.find_each do |game|
  # ...
end

我的模型有一个字符串 (UUID) 主键:

class Game < ActiveRecord::Base
  self.primary_key = 'uuid'

  before_create do |game|
    game.uuid = UUIDTools::UUID.timestamp_create().to_s if game.uuid.blank?
  end
end

我不知道 ActiveRecord 为什么要放入 WHERE 子句,但这是完全没有必要的,也是类型错误的原因(因为它是字符串列,而不是整数列)。

那么,我该如何避免这种情况呢?我应该在我的模型定义中添加一些东西吗?或者我应该避免find_each 并使用不同的方法?这是一个 rake 任务,它只是遍历所有条目并查找一些附加信息......

【问题讨论】:

    标签: ruby-on-rails ruby postgresql activerecord


    【解决方案1】:

    似乎find_each 存在非数字主键的错误:

    https://groups.google.com/group/compositekeys/browse_frm/month/2011-06

    【讨论】:

      【解决方案2】:

      我认为不带任何参数的 find_each 将导致 find_by_id 其中 id >= 0。即使 ActiveRecord 使用正确的列,在您的情况下,它似乎并不知道该列是 varchar 类型,而是整数。

      您可以尝试使用另一种查找方法,或者尝试在 find_each 中添加一些条件。

      这可能与使用字符串作为主键的问题有关:http://railsforum.com/viewtopic.php?id=11110

      干杯

      【讨论】:

        【解决方案3】:

        blog post 已修复您的错误:

        在 lib/clean_find_in_batches.rb 中

        module CleanFindInBatches
        
          def self.included(base)
            base.class_eval do
              alias :old_find_in_batches :find_in_batches
              alias :find_in_batches :replacement_find_in_batches
            end
          end
        
          # Override due to implementation of regular find_in_batches
          # conflicting using UUIDs
          def replacement_find_in_batches(options = {}, &block)
            relation = self
            return old_find_in_batches(options, &block) if relation.primary_key.is_a?(Arel::Attributes::Integer)
            # Throw errors like the real thing
            if (finder_options = options.except(:batch_size)).present?
              raise "You can't specify an order, it's forced to be #{batch_order}" if options[:order].present?
              raise "You can't specify a limit, it's forced to be the batch_size" if options[:limit].present?
              raise 'You can\'t specify start, it\'s forced to be 0 because the ID is a string' if options.delete(:start)
              relation = apply_finder_options(finder_options)
            end
            # Compute the batch size
            batch_size = options.delete(:batch_size) || 1000
            offset = 0
            # Get the relation and keep going over it until there's nothing left
            relation = relation.except(:order).order(batch_order).limit(batch_size)
            while (results = relation.offset(offset).limit(batch_size).all).any?
              block.call results
              offset += batch_size
            end
            nil
          end
        
        end
        

        在 config/initializers/clean_find_in_batches.rb 中

        ActiveRecord::Batches.send(:include, CleanFindInBatches)
        

        【讨论】:

        猜你喜欢
        • 2015-05-16
        • 1970-01-01
        • 1970-01-01
        • 2013-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-18
        • 1970-01-01
        相关资源
        最近更新 更多