众所周知 alias_method_chain 是用来继承方法的
class Apple
def eat
puts "eat"
end
def eat_with_duck
puts "eat with duck"
eat_without_duck
end
alias_method_chain :eat, :duck
def buy
puts "buy"
end
end
我们平常打补丁 可以这样写。
Apple.class_eval <<-EOF
def buy_with_me
puts "buy with me"
buy_without_me
end
alias_method_chain :buy, :me
EOF
最近改造一个数据库在 SQL Server 上的项目,用 1.9.3-p327, Rails3.2.9.rc3 因为 SQL Server2008 不能自动识别 date 类型还是 datetime。自己想利用 alias_method_chain 方法做自动转换日期类型。
class CustomModel < ActiveRecord::Base
self.abstract_class = true
##此处省略一些代码
def self.correct_sqlserver_date(*names)
names.each do |column_name|
self.class_eval <<-EOF
pp self
def #{column_name}_with_format_date
self.#{column_name}_without_format_date && self.class.correct_date(self.#{column_name}_without_format_date)
end
alias_method_chain "#{column_name}", :format_date
def #{column_name}_with_format_date=(val)
self.#{column_name}_without_format_date = case val
when String
Time.zone.parse(val)
when Date
val.to_time_in_current_zone
else
val
end
end
alias_method_chain :"#{column_name}=".to_sym, :format_date
EOF
end
end
end
使用方法
class Car < CustomModel
correct_sqlserver_date "InactivationDate"
end
在 console 里执行的时候,奇迹般的出错了。提示 undefined method 'InactivationDate' for
Car' `。Car 对象表里肯定是有 InactivationDate 这个字段的,这是为什么呢?
这个问题查了一天,曾怀疑自己的经验,甚至怀疑 ruby1.9.3-p327 改了 alias_method_chain 用法。
最后发现一个事实:alias_method_chain 原方法名是 active_record 字段的时候,必须是规范的小写字母开头属性。
悲剧的是 SQL Server 的数据库字段 都是大写的,例如 InactivationDate, ExpirationDate. 目前用 super 解决了。希望大家遇到类似情况 能分享下自己调试分析的过程。