3

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

对于表,它似乎很好,Rails 用小写询问它,数据库很好地找到它。问题在于列,因为 Rails 使用 SQL 获取它们的名称,因此无论它们的名称是什么大小写。

我正在处理500多个表,每个表中都有几十列,并且在它们上面运行了几个在生产中运行的遗留应用程序,因此重命名这些列不是解决方案。使用 alias_attribute 也是一种工作量太大的解决方案。

我不想在我的代码中出现一些奇怪的情况,比如 client.AccountId (就像 Java 代码一样)。

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

4

1 回答 1

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 代码的最小代码修改。如果您看到我要撞墙而我没有撞墙,我想听听您对此的意见和评论!

To describe the solution, I'm using the columns method of ActiveRecord to generate snake_case looking aliases for each column. I'm also giving alias_column a memory of the aliases, that way read and write attribute methods know when they are dealing with alias names.

Since in my legacy database the convention for the ID or the table Table is TableID, my solution will create a table_id alias found by ActiveRecord using the "table_name_with_underscore" convention, so the id method is working as expected.

I presume it's not going to work with all the SQL fetches, even with Squeel of something but I don't think there is any simple solution for this.

于 2012-12-13T13:50:18.650 回答