原文首发:Ruby中文社区
社区地址:http://www.ruby-lang.org.cn/
转载请保留版权声明并以连接形式指向原文。这几天写个小东西,数据库是早就建立好的,没有办法更改,而且还有其它程序依赖于这个数据库,所以没有办法,只好在
Rails上动手脚了。
数据库结构大概如下:
1. 所有表名皆有统一前缀。
2. 所有字段名皆有前缀,大部分字段名的前缀与表名的单数形式一致,但有的为表名的简写。
想像一下,我们如果不做任何改变写出来的代码会是什么样子的。
CODE:
f = Forum.new
f.forum_name = 'My Forum'
f.forum_date_created = Time.now
f.forum_description = 'a simple forum'
u = User.new
u.user_name = 'skyover'
u.user_emoticion = '/face/1.gif'
u.save这样多烦啊,有没有什么好办法去改变得变得自然一些呢?
前面一个问题好解决,Rails本身就有支持:
1. 在environment.rb里加上这一句就行了。
CODE:
ActiveRecord::Base::table_name_prefix = 'bbs_'2. 不太好处理,Rails里本身没有提供这样的参数用来配置,只有以表名为前缀为字段前缀的才可以处理。没有办法只好自己动手了。
写一个module.
my_base.rb
CODE:
module MyBase
def method_missing(method_id, *arguments)
@prefix ||= self.class.table_name.split(/_/)[1].singularize + '_'
method_name = method_id.to_s
method_name = @prefix + method_name unless method_name.include?(@prefix)
#puts method_name
return super(method_name.to_sym, *arguments) if self.respond_to?(method_name.to_sym)
raise NoMethodError
end
end这个module重载了method_missing的方法,在发现方法不存在的时候就尝试使用表名去掉前缀后的单数形式加上原有的方法名称去匹配,如果还是没有找到,则返回一个没有找到方法的错误信息。
有了这个module,我们就比较好办了,分两种情况处理:
a. 字段名前缀与表名有共通之处的。
CODE:
class Forum < ActiveRecord::Base
include MyBase
has_many :topics
def self.primary_key
"forum_id"
end
end首先,我们include了MyBase这个module,这样这个method_missing方法将mixin到类里。注意primary_key这个方法,因为rails默认的主銉是id,所以我们必须要覆盖这个方法来返回正确的主键名称。
b. 字段名前缀与表名不直接对应的,例如表名叫bbs_categories,字段名为cat_name.
CODE:
class Category < ActiveRecord::Base
include MyBase
has_many :forums, :foreign_key => :cat_id
def method_missing(method_id, *arguments)
@prefix = 'cat_'
super
end
def self.primary_key
"cat_id"
end
end我们在这里再次重写父module里的metod_missing方法,手工将@prefix实例变量设置好,这样就处理清楚了。
综上所述,动动脑筋,还是有很多办法还实现自己的想法的。
一点点编写代码过程中的小tips,谨与大家共享。