00:00:24.690
Alright, so I'm Jacob Swanner, and I'm here to talk about Active Record scopes and Arel. Before we get started with where we are now with scopes, I think it's important to know where we came from, how Rails has evolved over time, and hopefully gain a better understanding of why things are the way they are. We can also discuss where things might be going in the future. So, let's take a look back at how Rails was before version 2.1.
00:01:04.899
Previously, with Active Record, you had find methods where you would provide a hash of options, but there were no built-in means of reusing those options. If you needed to use the same conditions multiple times, there was nothing built in to help with reusability. You could write a method to return that options hash, and that was about the best you could do. For example, the find method has different modes of operation; you could give it a number to look for a record with that ID, but I'm not referring to that here—it's mostly about how we would query records out of the database.
00:01:46.839
In the past, if you wanted to find the first author where the name is 'Bob', you would specify that in the options hash. This would replace the conditions with the value that follows it, in this case 'Bob'. For another example, if you wanted to find all the books where the title contains 'foo', you would need to specify that in the options as well. But, again, there was no way of reusing any of these conditions or ordering.
00:02:53.310
With the release of Rails 2.1, some changes were introduced. The first was the introduction of named scopes, which rolled in Nick Kallen's has finder plugin directly into Rails. This feature allows you to reuse query options and enables the composition or chaining of scopes. This means that if you create granular scopes, you can build them up to retrieve the records you want using multiple scopes. For example, you can define a scope called 'published' based on the condition that an author has more than zero books. Here, you might say that an author is published if their books count is greater than zero.
00:04:02.790
Another example is a scope by first name that accepts an argument using a lambda function. This approach allows you to specify where the first name matches a given value. In this way, you could find all published authors whose first name is 'Bob'. This was a significant improvement back when Rails 2.1 was released.
00:05:32.240
Then Rails 3 came along and made further changes to how you query the database. The named scope became simply 'scope', retaining its functionality but becoming slightly shorter. Additionally, Rails 3 introduced a variety of query methods to Active Record, extracting options from the hash into separate methods like 'where' and 'order'. The ability to chain these methods together enhanced composability, allowing you to query more dynamically. For instance, you could say 'where author: Bob' and also chain conditions like 'where city: Orlando', effectively making complex queries much simpler.
00:07:04.320
As an illustration, we can find all authors whose first name is Bob, now using the updated methods available in Rails 3. Notably, the way you use the scopes has not changed—only their definitions have, making transitions between versions smooth for developers. This flexibility allows developers to continue using their previously defined scopes without needing to change the corresponding code.
00:08:58.440
Now, let's take a look at Arel, which is a relational algebra library used internally by Active Record. Arel simplifies the process of generating SQL queries while abstracting the complexity involved. For example, you define the table you want to query by specifying the authors table. Then you'd designate the specific column (like 'name') you want to operate on and establish the operator you wish to use, which can further assist in crafting dynamic SQL.
00:10:53.640
When querying for records, Arel provides predicates that allow for easy query creation. If you're looking for authors whose name equals 'Amy', you can construct this query using Arel. Moreover, Arel also allows for matches across different conditions in a flexible manner, making it easier to deal with complex queries from various tables.
00:12:11.020
However, it's important to address some potential issues as you might run into problems of case sensitivity based on the database you're using. If you're writing on Postgres and your development environment is SQLite, queries may behave differently, leading to discrepancies in results. For instance, while SQLite may treat 'LIKE' queries case-insensitively, Postgres does not. One workaround is to use 'ILIKE' for case-insensitive searches; however, it's not available in all databases.
00:13:09.600
So, if you want a more environment-agnostic solution, consider using Arel for creating more dynamic queries that don’t rely on specific SQL syntax tied to a certain database system. For example, instead of using 'LIKE', you could still create relevant matching conditions that are compatible across platforms. Using Arel in this way allows you to create versatile, reusable code.
00:14:52.960
Notably, Arel provides predicates that allow you to express queries like 'greater than' or 'less than', further extending your querying capabilities beyond simple comparisons. You can generate SQL conditions dynamically and utilize features from various databases without being restricted to a single SQL dialect.
00:16:07.880
Furthermore, Rails supports traditional methods of querying as well. For instance, while it’s intuitive to use SQL fragments to get results, it would be beneficial to leverage Arel or even Active Record's query interface for clearer intent and better clarity, especially when constructing more complex queries.
00:17:15.390
An example would be making dynamic queries with an ActiveRecord 'where' clause. Writing clearer query conditions using Arel's approach can help mitigate ambiguities in your logic or when querying across multiple models. Unlike combining string queries, which can lead to confusion, using Arel keeps everything neat and organized.
00:18:45.200
As we conclude this talk, I want to emphasize that traditional scopes can sometimes lead to complexity when used in larger applications. In many cases, utilizing class methods instead of lambdas can simplify your code and improve readability. Rails has shown substantial evolution, and I encourage everyone to experiment with these approaches to see which best fits their coding style.
00:19:55.620
Let me wrap up by mentioning that Arel has a range of predicates you can use—like equivalence, not equal, greater than, and less-than—making it a powerful tool for constructing advanced database queries. The library called Squeel also complements Arel, providing a more concise syntax while still exposing a lot of functionalities available in Arel. Together, they form a solid foundation for building reusable query logic.
00:26:04.710
Thank you all for attending! I'm Jacob Swanner; feel free to reach out to me on Twitter. I work at MV Labs, the company behind Code School, as well as other projects like Try Ruby and Rails for Zombies. If you have any questions now, I'm all ears.