【问题标题】:after_find callback broken after upgrade to rails3升级到 rails3 后 after_find 回调中断
【发布时间】:2010-09-07 18:09:14
【问题描述】:

您好!

在 Rails 2.3.8 中完美运行的应用程序中,我有以下类方法:

def self.encode(*attr_names)
  encoder = Encoder.new(attr_names)
  before_save encoder
  after_save encoder            
  after_find encoder
  define_method(:after_find) { } # defining here, since there's only alias in the Encoder class itself            
end

此方法引用编码器类。就是这样:

class Encoder
  include Encodings 

  def initialize(attrs_to_manage) # We're passed a list of attributes that should be stored encoded in the database
    @attrs_to_manage = attrs_to_manage
  end

  def before_save(model) # Before saving or updating, encode the attributes to their original encoding
    @attrs_to_manage.each do |field|
      model[field] = to_orig_encod(model[field])
    end
  end

  def after_save(model) # After saving, encode them back to utf8
    @attrs_to_manage.each do |field|
      model[field] = to_utf8(model[field])
    end
  end

  alias_method :after_find, :after_save # Do the same after finding an existing record
end

在升级到 rails3 之前,所有回调(before_save、after_save、after_find)都运行良好。升级后 before_saveafter_save 仍然有效,但 after_find 无效,并且我在日志中收到以下弃用警告:

DEPRECATION WARNING: Base#after_find has been deprecated, please use Base.after_find :method instead

我不确定如何更改我的代码以重新启用 after_find 回调的功能。我尝试了一些简单的替代方法,但没有成功,而且有关此回调的 rails API 文档非常有限,并且没有实现示例。

任何帮助表示赞赏,在此先感谢!

编辑:

解决办法如下:

好的,所以问题似乎比最初出现的更微妙。经过额外的测试,我发现事实上,正如 Jeppe 指出的那样,无论弃用警告如何,after_find 回调都在工作,“to_utf8”方法实际上已成功调用并在模型属性上执行。结果与预期不符的原因是“to_utf8”方法本身。它的作用是使用 ruby​​ 模块 Iconv 将字符串从非 utf8 编码(例如 cp1251)转换为 utf。这是针对使用 Active Record 从具有非 utf 编码的远程旧数据库中获取的模型的属性完成的。然而,事实证明,与以前版本的 rails 不同,rails 3 中的 AR 自动并静默处理所有对象到 ut8 的转换,即使是从非 unicode 的数据库中获取的对象。所以基本上在升级之后,我的代码最终重新转换为 utf8 字符串,这些字符串已经被 AR 转换为 utf8,结果是一堆乱码。该问题已通过完全删除 after_find 和 after_save 回调得到解决,因为在这种情况下不再需要它们:)

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3


    【解决方案1】:

    我已尝试重现您的问题,但我只能重现弃用警告,您可以通过删除您的来摆脱

    define_method(:after_find) { }
    

    声明。

    除此之外,无论有无 define_method 语句,一切似乎都按预期工作。

    我的代码:

    class Testmodel < ActiveRecord::Base
    
      def self.encode(*attr_names)
        encoder = Encoder.new(attr_names)
        before_save encoder
        after_save encoder            
        after_find encoder
      end
    end
    
    class Encoder
      def initialize(attrs_to_manage) # We're passed a list of attributes that should be stored encoded in the database
        @attrs_to_manage = attrs_to_manage
      end
    
      def before_save(model) # Before saving or updating, encode the attributes to their original encoding
        @attrs_to_manage.each do |field|
          model[field] = to_orig_encod(model[field])
        end
      end
    
      def after_save(model) # After saving, encode them back to utf8
        @attrs_to_manage.each do |field|
          model[field] = to_utf8(model[field])
        end
      end
    
      alias_method :after_find, :after_save # Do the same after finding an existing record
    
      private
      def to_orig_encod(var)
        "foo"
      end
    
      def to_utf8(var)
        "bar"
      end
    end
    

    控制台测试:

    ruby-1.9.2-p0 > Testmodel.create
     => #<Testmodel id: 3, name: nil, created_at: "2010-09-08 14:02:06", updated_at: "2010-09-08 14:02:06"> 
    ruby-1.9.2-p0 > Testmodel.last
     => #<Testmodel id: 3, name: nil, created_at: "2010-09-08 14:02:06", updated_at: "2010-09-08 14:02:06"> 
    ruby-1.9.2-p0 > Testmodel.encode('name')
     => [Testmodel(id: integer, name: string, created_at: datetime, updated_at: datetime)] 
    ruby-1.9.2-p0 > Testmodel.last
     => #<Testmodel id: 3, name: "bar", created_at: "2010-09-08 14:02:06", updated_at: "2010-09-08 14:02:06"> 
    

    我一直在查阅 http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html 的文档以了解您的问题 :-)

    【讨论】:

    • 您付出了很多努力,非常感谢您复制代码,我将使用您和我的代码玩一会儿,以弄清楚为什么您的代码可以正常工作而我的代码似乎可以不是,我很快就会得出结论!再次感谢您花时间和精力深入研究这个问题!
    • 好的,所以我想出了问题所在。我将其全部解释为对问题的编辑,因为没有足够的空间将其全部放在评论中。再次感谢 Jeppe,您仔细检查了代码并为我指明了正确的方向!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多