I have the following variables:
query = "(first_name = ?) AND (country = ?)" # string
values = ['Bob', 'USA'] # array
I need the following result:
result = "(first_name = Bob) AND (country = USA)" # string
The number of substitutions varies (1..20).
What is the best way to do it in Ruby?
If you don't mind destroying the array:
query.gsub('?') { values.shift }
Otherwise just copy the array and then do the replacements.
Edited: Used gsub('?') instead of a regex.
If you can control the query
string, the String#% operator is what you need:
query = "(first_name = %s) AND (country = %s)" # string
values = ['Bob', 'USA'] # array
result = query % values
#=> "(first_name = Bob) AND (country = USA)"
You have to replace ?
with %s
in your query
string.
query = "(first_name = ?) AND (country = ?)"
values = ['Bob', 'USA']
result = query.dup
values.each{|s| result.sub!("?",s) }
p query
# >> "(first_name = Bob) AND (country = USA)"
values.inject(query){|s1, s2| s1.sub("?", s2)}
Since this question is tagged ruby-on-rails , you could (should) use ActiveRecord::QueryMethods#where
with Array Conditions .
This will raise ActiveRecord::PreparedStatementInvalid
if you provide the wrong number of bind variables in values
, which saves you from checking this yourself.
Not only is this elegant because Rails performs the substitutions for you, it will also help guard you against SQL injection attacks by sanitising your SQL in the process.
Assuming your model is called User
and query
and value
are as in your question, this:
User.where(query, *values)
...would generate SQL like:
SELECT * FROM users WHERE first_name = 'Bob' AND country = 'USA';
The example above will execute the query. To display the generated SQL without execution, simply invoke ActiveRecord::Relation#to_sql
:
User.where(query, *values).to_sql
If you're using Rails (or at least ActiveRecord), I'd recommend using
ActiveRecord::Base.sanitize_sql_for_conditions(['(first_name = ?) AND (country = ?)', 'Bob', 'USA'])
Unless it's just for a regular where
condition, in which case it will ActiveRecord will just do this for you in User.where('(first_name =?) AND (country =?)', 'Bob', 'USA')
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.