2012-09-01 29 views
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}')")  

任何想法如何清理呢?这是一个简化的例子,在很多情况下,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)数据库。我落得这样做是为了把这个方法在我所有的普通机型:

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

所以现在,当我从存储在日常的Rails MySQL的模型数据更新的遗产:

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

回答

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

然后,您可以使用sanitize函数,无论何时您需要将变量分到SQL中,就像您通常那样。希望有所帮助!

+0

对我而言,谢谢 – RadBrad

+0

Ugg,我刚刚更新了我的问题,构建sql_array来清理会很痛苦。以tmp开头的变量是唯一必须被清理的变量(来自表单)。任何其他想法? – RadBrad

+0

@RadBrad - 我不确定我是否知道你的意思。你当然可以像现在这样使用字符串插值将“安全”变量抛出,然后使用清理来逃避其余部分,但总体替换次数很多,以至于没有什么事情会变得很漂亮......你能给出一个使用清洁时你的代码是什么样子的例子? –