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}')")    

それをクリーンアップする方法はありますか?これは単純化された例であり、多くの場合、1つの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モデルに保存されているデータからレガシーを更新しているとき:

"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 に答える