升级到rails3后,after_find回调中断

素不相识的!

在一个在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 

此方法引用Encoder类。 就这个:

 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回调的function。 我尝试了一些简单的替换但没有成功,这个回调的rails API文档非常有限,没有实现的例子。

任何帮助表示感谢,提前感谢!

编辑:

这是解决方案:

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

我试图重现你的问题,但我只能重现弃用警告,你可以通过删除你的

 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 => # ruby-1.9.2-p0 > Testmodel.last => # 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 => # 

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