从文件中评估字符串的更简单方法?

时间:2009-12-23 17:57:38

标签: ruby

我想将mySQL查询存储在一个文件中。我打算用我的程序中的变量来替换它的部分字符串。

我在红宝石中使用'eval'方法,但是它有效,但感觉有点笨拙。

使用irb我做了以下事情。

>> val = 7
=> 7
>> myQuery = "select * from t where t.val = \#{val}" #escaped hash simulates reading it from file
=> "select * from t where t.val = \#{val}"
>> myQuery = eval "\"#{myQuery}\""
=> "select * from t where t.val = 7"

正如你所看到的那样有效!但为了使它工作,我必须将'myQuery'变量包装在转义引号中,整个事情看起来有点混乱。

有更简单的方法吗?

4 个答案:

答案 0 :(得分:1)

通常,您不应使用字符串插值来构建SQL查询。这样做会让您受到SQL injection攻击,其中有人提供具有结束引号字符的输入,然后是另一个查询。例如,使用您的示例:

>> val = '7; DROP TABLE users;'
=> "7; DROP TABLE users;"
>> myQuery = "select * from t where t.val = \#{val}"
=> "select * from t where t.val = \#{val}"
>> eval "\"#{myQuery}\""
=> "select * from t where t.val = 7; DROP TABLE users;"

即使没有恶意输入,您也可能只是意外地执行您不想要的代码,例如,如果有人在其输入中包含引号。

除非绝对必要,否则避免使用eval通常也是个好主意;它使得如果你的程序中有错误,有人可以通过将它传递给eval来执行任意代码,并且它使代码的可维护性降低,因为你的一些源代码将从你以外的地方加载常规源树。

那么,你怎么做呢?数据库API通常包含prepare命令,可以准备执行SQL语句。在该语句中,您可以包含?个字符,这些字符表示可在该语句中替换的参数。然后,您可以在语句上调用execute,传入这些参数的值,并且它们将被安全地执行,而无法让某人执行任意SQL。

以下是它在您的示例中的工作原理。假设您使用的是this MySQL/Ruby module;如果您使用的是另一个,它可能会有类似的界面,但可能不完全相同。

>> val = 7
>> db = Mysql.new(hostname, username, password, databasename)
>> query = db.prepare("select * from t where t.val = ?")
>> query.execute(val)

答案 1 :(得分:0)

您可以使用ERB模板 - 从文件中读取它们并插入变量(将<%= something%>标记转换为实际值)。

Here's the official doc,它非常完整和直截了当。

答案 2 :(得分:0)

您可以使用类似printf的语法进行字符串替换

"123 %s 456" % 23 # => "123 23 456"

这仅适用于您的程序事先知道要使用哪些变量。

答案 3 :(得分:0)

你能使用参数化查询吗?

我不知道如何在ruby中这样做,但基本上它涉及使用SQL识别的命令标记您的SQL语句,而不是使用除语句之外发送的参数。

此链接可能有所帮助:http://sqlite-ruby.rubyforge.org/sqlite3/faq.html#538670816