I have a system with a legacy database that I have to insert/update with manual SQL. Right now, I have something like this:
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}')")
Any ideas how to clean that up? It’s a simplified example, in many cases there are multiple attributes in the Legacy table updated with one SQL statement.
I could add a new accessor
Set Title = #{book.Title!)
or simply:
Set Title = #{book.Title.send('quoted')}
Any other ideas?
UPDATE: here is an actual example:
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;")
I sanitize like so:
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
called like this:
Insured.update_attributes(id,
{:Address1 => params[:submission][:address1],
:Address2 => params[:submission][:address2],
:City => params[:submission][:city],
:State => params[:submission][:state],
:Zip =>params[:submission][:zip]
})
I didn’t realize it when I first posted, but I’ve come to learn that my issue comes about when I insert/update data in the Legacy database from data stored in my regular Rails (MySQL) database. What I ended up doing was to put this method in all my Regular models:
def quoted_for_legacy(attribute)
Legacy.connection.quote(self[attribute])
end
So now, when I’m updating Legacy from data stored in regular Rails MySQL models:
"Set Foo = #{regmodel.quoted_for_legacy(:Foo)}"
I use the Rails built-in method to do this. This lets you use all the convenient substitution shortcuts you can with other SQL in Rails. Just write a wrapper around the ActiveRecord method:
Note: Looks like this method has been moved in the latest version. If you’re using that, you’ll want ActiveRecord::Sanitization::ClassMethods#sanitize_sql_array instead.
Then you can use the
sanitizefunction whenever you need to sub variables into the SQL, just like you would normally. Hope that helps!