1

I have a set-up with multiple contests and objects. They are tied together with a has_many :through arrangement with contest_objs. contest_objs also has votes so I can have several contests including several objects. I have a complex SQL setup to calculate the current ranking. However, I need to specify the contest in the SQL select statement for the ranking. I am having difficulty doing this. This is what I got so far:

@objects = @contest.objects.select('"contest_objs"."votes" AS v, name, "objects"."id" AS id, 
                                   (SELECT COUNT(DISTINCT "oi"."object_id")
                                           FROM  contest_objs oi
                                           WHERE ("oi"."votes") > ("contest_objs"."votes"))+1 AS vrank')

Is there any way in the selection of vrank to specify that WHERE also includes "oi"."contest_id" = @contest.id ?

3 Answers 3

3

Use sanitize_sql_array:

sanitize_sql_array('select ? from foo', 'bar')

If you're outside a model, because the method is protected you have to do this:

ActiveRecord::Base.send(:sanitize_sql_array, ['select ? from foo', 'bar'])

http://apidock.com/rails/ActiveRecord/Sanitization/ClassMethods/sanitize_sql_array

Sign up to request clarification or add additional context in comments.

Comments

2

Since @contest.id is an integer and does not present any risk of an SQL Injection, you could do the following using string interpolation :

Model.select("..... WHERE id = #{@contest.id}")

Another possible solution would be to build your subquery using ActiveRecord, and then call .to_sql in order to get the generated SQL, and insert it in your main query.

5 Comments

I had tried that and it gives me this error 'ActiveRecord::StatementInvalid (SQLite3::SQLException: unrecognized token: "#"'
Are you SURE you're using double quotes ? String interpolation does not work with single quotes.
Huh. It worked. I always thought single and double quotes were interchangeable. It works!
@Marc only "" are evaluated. '' is a string literal.
Don't do this. ActiveRecord prepared statement cache will leak memory.
-1

You can insert variables into sql commands like this:

Model.select("...... WHERE id = ?", @contest.id)

Rails will escape the values for you.

Edit:

This does not work as stated by Intrepidd in the comments, use string interpolation like he suggested in his answer. That is safe for integer parameters.

If you find yourself inserting several strings in a query, you could consider using find_by_sql, which gives you the above mentioned ? replacement, but you can't use it with chaining, so rewriting the whole query would be needed.

3 Comments

False. select only accepts one parameter and does not escape parameters. It will work with where but not select. You'll get the following error : ArgumentError: wrong number of arguments (2 for 1)
thanks for the clarification, but he could use find_by_sql, right?
Indeed, but he'll have to write the entire SQL query then.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.