0

我有一个带有旧数据库的系统,我必须使用手动 SQL 插入/更新。现在,我有这样的事情:

class Legacy  < ActiveRecord::Base
  establish_connection("legacy#{Rails.env}")
end

class Book < Legacy
end

book = Book.find(params[:isbn])
# CLEAN UP BELOW
Legacy.connection.exec_query("
          UPDATE dbo.Book Set Title = #{Legacy.connection.quote(book.Title)}
          WHERE dbo.Book.ISBN = '#{book.ISNB}')")    

任何想法如何清理它?这是一个简化的示例,在许多情况下,旧表中的多个属性使用一条 SQL 语句进行更新。

我可以添加一个新的访问器

Set Title = #{book.Title!)

或者简单地说:

Set Title = #{book.Title.send('quoted')}

还有其他想法吗?

更新:这是一个实际的例子:

result = Aim.connection.exec_query("
DECLARE @InsuredKey_PK int;
DECLARE @ResultVal varchar(125);
EXEC dbo.spAIMImportInsured #{tmpname}
, @InsuredKey_PK OUTPUT, @ResultVal OUTPUT, NULL, 'B', '#{submission.dba}', 
#{tmpaddr1}, #{tmpaddr2}, #{tmpcity}, '#{submission.state}', '#{submission.zip}' ,
#{tmpaddr1}, #{tmpaddr2}, #{tmpcity}, '#{submission.state}', '#{submission.zip}' 
, NULL, NULL, NULL, '#{submission.ProducerID}', 
'#{Employee.find(submission.acct_exec).first_name.downcase}',
'#{aim_name.Name}','#{aim_name.NameKeyPK}';
SELECT @InsuredKey_PK as insured_aim_key, @ResultVal as result;")

我是这样消毒的:

class Insured < Legacy
  def self.update_attributes(id,update_hash)
    set_sql = ActiveRecord::Sanitization::ClassMethods.send(
      :sanitize_sql_for_assignment,update_hash
    )
    connection.exec_query("UPDATE dbo.Insured Set " + set_sql + 
      "WHERE dbo.Insured.InsuredID = #{id}"
    )
  end
end

像这样调用:

Insured.update_attributes(id,
  {:Address1 => params[:submission][:address1],
  :Address2 => params[:submission][:address2],
  :City => params[:submission][:city],
  :State => params[:submission][:state],
  :Zip =>params[:submission][:zip]
  })

我第一次发帖时并没有意识到这一点,但我了解到我的问题是当我从存储在常规 Rails (MySQL) 数据库中的数据中插入/更新旧数据库中的数据时出现的。我最终做的是把这个方法放在我所有的常规模型中:

def quoted_for_legacy(attribute)
  Legacy.connection.quote(self[attribute])
end

所以现在,当我从存储在常规 Rails MySQL 模型中的数据更新 Legacy 时:

"Set Foo = #{regmodel.quoted_for_legacy(:Foo)}"
4

1 回答 1

1

我使用 Rails 内置方法来执行此操作。这让您可以在 Rails 中使用所有方便的替换快捷方式来处理其他 SQL。只需围绕ActiveRecord 方法编写一个包装器:

def sanitize(*array)
    return ActiveRecord::Base.send(:sanitize_sql_array, array)
end

注意: 看起来此方法已在最新版本中移动。如果您正在使用它,您将需要ActiveRecord::Sanitization::ClassMethods#sanitize_sql_array

然后,您可以sanitize像往常一样在需要将变量子变量放入 SQL 时使用该函数。希望有帮助!

于 2012-09-01T18:51:56.680 回答