我有一个带有本地rails数据库和旧数据库的rails应用程序。
我很好地查询这些遗留表,但我也必须在其中插入记录。
但Legacy表不符合rails约定WRT的关键。 Legacy Key不是自动递增的整数,而是一个字符串(总是数字字符0-9,但仍然是DB中的字符串属性)。 Legacy数据库有一个存储当前索引值的表,插入操作需要从'current_index'表中读取当前索引值,将其递增1,然后将值保存回'index_table',然后返回新的value,用于新键值的insert语句中。
现在我需要手工制作的SQL来插入分散在各种控制器中的记录。我想把它清理干净,然后把它移到模型中。
目前我这样做:
legacy_table.db:
class LegacyTable < Ldb
self.table_name = "legacyTableName"
self.primary_key "legacyKeyName"
end
控制器中的:
def insert_legacy_record(attrs)
result = Ldb.connection.exec_query("
DECLARE @key int;
EXEC dbo.getKeyField @key OUTPUT, 'RecordKey';
SELECT @key as ref_key;
")
newkey = result.first['ref_key']
result = Ldb.connection.exec_query("
INSERT INTO legacyTableName
(legacyKeyName,foo,...)
VALUES
('#{newkey}','#{attrs[:foo]}',...)
")
end
这很痛苦,因为我必须手动维护表属性列表及其输入的相应值作为attrs。
我可以覆盖activeRecord的索引生成部分吗?这样我就可以做到这一点:
OPTION1
@item = LegacyTable.new
@item.attributes(data)
@item.save <=== somehow override new index value generation
或者我应该覆盖新方法,让它返回它生成的新键值?
OPTION2
newkey = LegacyTable.new(data)
@new = LegacyTable.find(newkey)
我知道怎么做OPTION2,OPTION1可能吗?
答案 0 :(得分:1)
如何覆盖create
模型中的LegacyTable
方法,如下所示:
def create
# new_id = The code you use to get/set a new id for insertion
self.id = new_id
super # continue as normal
end
答案 1 :(得分:1)
您可以创建初始值设定项:
module Extensions
module LegacyModelId
extend ActiveSupport::Concern
included do
before_create :generate_legacy_id
def generate_legacy_id
result = Ldb.connection.exec_query("
DECLARE @key int;
EXEC dbo.getKeyField @key OUTPUT, 'RecordKey';
SELECT @key as ref_key;
")
self.id = result.first['ref_key']
end
end
end
end
在每个传统模型中:
class LegacyModelFoo < ActiveRecord::Base
include Extensions::LegacyModelId
...
end
这将在您包含扩展名的每个模型上添加before_create
回调,使其进行查找并分配新ID。