具有带有大小写混合的列名称的小写方法名称

时间:2012-12-13 09:59:58

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

我需要使用自己的约定连接到旧版SQL Server 2000数据库,特别是CamelCase列和表。

对于表格似乎很好,Rails用小写字母询问它,数据库很好地找到它。问题在于列,因为Rails使用SQL获取它们的名称,从而得到它们名称的任何情况。

我正在处理 500 + 表,其中每个表都有几十列,而且几个遗留应用程序在它们之上运行,因此重命名列是没有解决方案的。 使用alias_attribute也是一种太多的工作解决方案。

我不希望在我的代码中有一些奇怪的情况,就像client.AccountId(看起来像Java代码)。

所以我的最后一个问题是:有没有办法让Rails处理小写的方法和符号,然后在处理SQL时数据库使用的情况下使用它们? 我正在寻找任何现有的解决方案,甚至是ActiveRecord敏感区域的方向,所有这些机制都已完成(我一直在搜索,但源代码很大......)

1 个答案:

答案 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的东西,但我认为没有任何简单的解决方案。