我需要使用自己的约定连接到旧版SQL Server 2000数据库,特别是CamelCase列和表。
对于表格似乎很好,Rails用小写字母询问它,数据库很好地找到它。问题在于列,因为Rails使用SQL获取它们的名称,从而得到它们名称的任何情况。
我正在处理 500 + 表,其中每个表都有几十列,而且几个遗留应用程序在它们之上运行,因此重命名列是没有解决方案的。 使用alias_attribute也是一种太多的工作解决方案。
我不希望在我的代码中有一些奇怪的情况,就像client.AccountId(看起来像Java代码)。
所以我的最后一个问题是:有没有办法让Rails处理小写的方法和符号,然后在处理SQL时数据库使用的情况下使用它们? 我正在寻找任何现有的解决方案,甚至是ActiveRecord敏感区域的方向,所有这些机制都已完成(我一直在搜索,但源代码很大......)
答案 0 :(得分:0)
好的,在发布问题后的一段时间我有一个想法,alias_attribute实际上是解决方案,但只是需要一点魔力。 这是我自己问题的解决方案:
module LegacyDatabase
module ClassMethods
def aliased_attributes
@aliased_attributes ||= {}
end
def alias_attribute(new_name, old_name)
self.aliased_attributes[new_name.to_sym] = old_name.to_sym
super(new_name, old_name)
end
end
module InstanceMethods
private
def read_attribute(attr_name)
attr_name = self.class.aliased_attributes[attr_name.to_sym] if self.class.aliased_attributes.has_key?(attr_name.to_sym)
super(attr_name)
end
def write_attribute(attr_name, value)
attr_name = self.class.aliased_attributes[attr_name.to_sym] if self.class.aliased_attributes.has_key?(attr_name.to_sym)
super(attr_name, value)
end
end
def self.included(base)
base.instance_eval do
extend(ClassMethods)
include(InstanceMethods)
end
base.columns.each do |column|
legacy_name = column.name
rails_name = column.name.underscore
if legacy_name != rails_name
base.alias_attribute rails_name, legacy_name
end
end
end
end
我认为这是可以避免弄乱所有ActiveRecord代码的最小代码修改。如果你看到我要击中的墙,我不喜欢你的意见和你的意见!
为了描述解决方案,我使用ActiveRecord的columns方法为每列生成snake_case查找别名。我也给alias_column一个别名的内存,这样读取和写入属性方法就知道它们何时处理别名。
由于在我的遗留数据库中,ID或表Table的约定是TableID,我的解决方案将使用“table_name_with_underscore”约定创建ActiveRecord找到的table_id别名,因此id方法按预期工作。
我认为它不适用于所有的SQL提取,即使有Squeel的东西,但我认为没有任何简单的解决方案。