Explain Codes LogoExplain Codes Logo

Rails 3 Execute Custom SQL Query Without a Model

sql
raw-sql
active-record
sql-injection
Nikita BarsukovbyNikita Barsukov·Aug 4, 2024
TLDR

To execute raw SQL in Rails 3, use the ActiveRecord::Base.connection.execute method:

# Let's get this party started! 🎉 results = ActiveRecord::Base.connection.execute("SELECT * FROM your_table WHERE column = value")

The results obtained are database-specific: use methods such as each or map to process them. Always handle exceptions to avoid any unpleasant SQL errors.

In cases where swift execution is vital and a Model isn't necessary, laying out a custom SQL query is a viable approach for rapid data retrieval.

Establishing the Connection

Before executing your SQL query, you should first make sure you have a database connection set up properly. By using ActiveRecord::Base.establish_connection, you ensure efficient retrieval of data with minimal overhead.

If you wish to be hands-on with your connection pool settings, ActiveRecord::Base.connection_pool.spec might catch your attention. Adjusting such settings can improve your raw SQL performance and optimize resource utilization.

Fetching Your Data

Now, it's time to fetch your data. From Rails 3.1 onwards, ActiveRecord::Result simplifies this process. Methods such as rows, columns, and to_hash provide a comfortable interface to your query results. These allow you to focus on the data itself, rather than the technicalities of data structures.

One Method Does Not Fit All

Executing a raw SQL query might be a different experience depending on your Rails version, and you may encounter a version-specific error. You can circumvent this by using ActiveRecord::Base.connection.execute if an 'undefined method' error is raised.

The execution method differs based on your queries and their complexity. For more structured results, use exec_query, but for a wider range of data, execute becomes your best bet.

Dealing With Complex Associations

Sometimes, you will face more challenging scenarios where complex associations and subqueries may be part of your SQL statements. In such cases, calling upon find_by_sql acts as an excellent parachute:

# Durability test - because we love to stress-test our queries! 🛠️ complex_results = Post.find_by_sql("SELECT * FROM posts INNER JOIN comments ON comments.post_id = posts.id")

For those unversed in the arcane nature of find_by_sql, refer to apidock.com where you can find all its mysteries unraveled.

Precautionary Measures

Operating with raw SQL also means living on the edge when it comes to SQL injection. You are no longer under the protective umbrella of ActiveRecord’s sanitation methods. Guarding against this by sanitizing your parameters becomes paramount.

Furthermore, if you are in the SQL Server realm, consider installing the TinyTds gem. It allows executing raw SQL queries while offering robust connection management functionality.