模型中的单引号处理

时间:2012-09-01 18:22:28

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

我有一个带有遗留数据库的系统,我必须使用手动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}')")    

任何想法如何清理它?这是一个简化的示例,在许多情况下,Legacy表中有多个属性使用一个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)数据库中的数据中插入/更新Legacy数据库中的数据时,我才知道我的问题出现了。我最终做的是将这个方法放在我的所有常规模型中:

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

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

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

1 个答案:

答案 0 :(得分:1)

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

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

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

然后,只要您需要将变量子变量放入SQL,就可以使用sanitize函数,就像通常一样。希望有所帮助!