Tips for writing efficient code in Ruby

Suleyman Musayev
4 min readDec 1, 2023

--

In the realm of Ruby programming, efficiency is not just a virtue but a necessity, especially when dealing with data manipulation through ActiveRecord in a Rails application. Crafting code that not only accomplishes tasks but does so swiftly and resourcefully can significantly impact the overall performance of your application.

Over the course of my work experience I have built a habit of following simple rules that allow me to write more efficient code.

Choose Wisely

In Ruby, various array methods exist for data manipulation, while these methods provide perfect and convenient tools for handling arrays, they might not be equally efficient when dealing with ActiveRecord and database operations. For instance:

select vs. where

While select is used to extract specific elements from an array in Ruby, where in ActiveRecord performs a similar operation for database queries.

pluck vs. map

When retrieving specific columns from a database, pluck is more efficient than map. While map retrieves all records, and then extracts the specified attribute, pluck directly fetches only the needed data, reducing memory usage and potentially improving speed.

present? vs. exists?

These methods help in checking the presence or absence of data. present? checks if the object is not blank, exists? checks the existence of records in the database based on provided conditions. When validating the existence of records in the database, prefer exists? over present? as it directly generates an SQL query to check for records, enhancing performance.

find_by vs. find

When searching for a single record, find_by is preferable over find as it allows specifying conditions directly in the method call. This way, the database fetches only the first matching record, enhancing efficiency.

any?

To check if any element meets certain criteria in an array, consider using exists? or where in ActiveRecord for database-related operations. For non-database scenarios, utilizing methods like include?, find, or custom enumerable methods might be more suitable based on the specific condition.

flatten

In Ruby arrays this method is used to collapse nested arrays into a single array. For database operations, when dealing with nested associations or multiple table joins, utilizing includes or joins with appropriate conditions can fetch related data efficiently without needing to flatten arrays.

There are also many other array methods that can be optimized, for example, instead of chaining uniq you can structure your query to use distinct or instead of using compact your query can make use of where.not(column_name: nil).

Performing operations in the database will filter out unnecessary data, fetching only the essential information. This practice reduces the data packet size transmitted from the database to the application’s memory, consequently improving page load speeds for web applications and overall user experience.

ActiveRecord Optimization Techniques

When working with ActiveRecord and database operations, some queries or operations can be expensive and impact performance significantly. Here are the most common scenarios and their alternatives for better efficiency:

Avoiding N+1 queries

Utilize eager loading using includes, joins, or preload to fetch associated data upfront, reducing the number of queries executed and enhancing performance. But be cautious about loading only the necessary data.

Batching Updates

When performing bulk updates or inserts, using methods like update_all or insert_all can significantly enhance performance by reducing the number of individual queries sent to the database. Keep in mind that some of these methods, e.g. insert and insert_all, generate direct call to the database bypassing validations specified within Rails framework.

Careful Use of Callbacks and N+1 Issues

Be cautious with callbacks in ActiveRecord as they might trigger additional queries. Assess whether callbacks are necessary and optimize accordingly.

Expensive operations like left joins and wildcard lookups using ilike %% in SQL queries can be optimized using alternative techniques:

Left joins can be resource-intensive, especially when dealing with large datasets. Consider using eager loading with includes or joins along with careful use of associations and indexing to optimize queries. Utilizing preload or eager_load helps fetch associated data efficiently without causing performance bottlenecks.

Instead of using ilike %% for wildcard searches, consider utilizing database-specific features. For instance, in PostgreSQL you can use the built in full text search feature by implementing ts_vector columns combined with functionalities like tsearch, trigram, or dmetaphone can significantly enhance text search performance. These features leverage indexing and specialized search algorithms, providing faster and more efficient wildcard search capabilities.

Sometimes, ActiveRecord abstractions might not be the most efficient way to interact with the database. In such cases, employing raw SQL or leveraging ActiveRecord’s find_by_sql method might offer performance gains.

Benchmarking and Testing

Always measure and benchmark the performance of your code changes. Tools like benchmark-ips and built-in Rails performance testing tools can help identify bottlenecks and improvements.

Conclusion

Efficient Ruby code isn’t just about achieving the desired outcome; it’s about achieving it optimally. By following the mentioned tips for choosing the right methods, optimizing ActiveRecord queries, considering SQL alternatives when necessary you can improve efficiency of your code and improve performance of your Ruby applications.

And prioritizing efficiency in coding practices not only enhances the user experience but also contributes to a scalable and robust application architecture.

If you have any similar advise please feel free to share them in the comments.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

No responses yet

Write a response