Talks
Active Record vs. Ecto: A Tale of Two ORMs

Active Record vs. Ecto: A Tale of Two ORMs

by Brad Urani

This video, titled "Active Record vs. Ecto: A Tale of Two ORMs," presented by Brad Urani at RailsConf 2016, explores the differences between two popular object-relational mappers (ORMs): Active Record and Ecto. Both ORMs serve as bridges between applications and databases but take different approaches that yield varied implications for developers.

Key Points Discussed:

  • Introduction to ORMs: The speaker introduces ORMs, specifically focusing on Active Record from Ruby on Rails and Ecto from the Phoenix framework built with Elixir.
  • Overview of Elixir and Phoenix: Elixir, a functional programming language, was created for high concurrency and is designed to run on the Erlang VM, which excels in real-time systems. Phoenix is an MVC framework promoting productivity and speed.
  • Previous Experiences: Brad shares his background using various ORMs, which leads into a direct comparison of Active Record and Ecto.
  • Architecture Comparison: While Active Record is simpler and focuses on developer convenience with readable syntax, it can lead to performance pitfalls, such as the N+1 query problem. In contrast, Ecto leans towards explicitness, with a strong emphasis on defining schemas and relationships clearly, improving maintainability and performance.
  • Immutable Structures in Ecto: Ecto utilizes immutable structures, meaning once created, data cannot be modified. This design philosophy encourages clearer and more structured code, avoiding the complexities found in Active Record.
  • Querying Differences: In Ecto, queries closely resemble SQL syntax, allowing for explicit field selection and reducing the confusion often caused by implicit query generation in Active Record.
  • Concurrency and Performance: Brad highlights how Ecto leverages the concurrency capabilities of the Erlang VM, enhancing performance during testing. This makes it particularly suitable for applications requiring real-time updates, like video games and communication tools.
  • Wrap-Up Comparisons: The video concludes that both ORMs cater to different needs within development projects. Active Record favors convenience, while Ecto prioritizes explicitness and performance.

Conclusions:

  • Developers should weigh the trade-offs between convenience and explicitness when choosing an ORM, considering their specific project needs. Both Active Record and Ecto provide unique advantages, and understanding their designs will help developers select the right one for upcoming projects.
  • Brad encourages further learning on these topics, suggesting resources such as the Bike Shed Podcast and exploring opportunities at Procore.
00:00:09.650 My name is Brad Urani, and I work at Procore. This talk is about object-relational mappers (ORMs), specifically comparing and contrasting Ecto and Active Record. Ecto is an ORM for Phoenix.
00:00:16.230 Phoenix is a web framework for Elixir, which is a relatively new programming language created by José Valim. José was a long-time core member of Rails, and he split off to start his own programming language.
00:00:24.269 Elixir is an interesting language; it's very fast, functional, and it has Ruby-like syntax. It's designed for very high concurrency and does that exceptionally well.
00:00:30.570 Elixir compiles to Erlang bytecode. Erlang was originally developed for massively scalable soft real-time systems, which require high availability.
00:00:36.570 Erlang was created by Joe Armstrong back in the '80s for telephone systems while he was working at Ericsson. He wrote software for a telephone switch that ran a million landlines with 99.9999999% availability.
00:00:42.750 This technology was used to design systems that could serve the entire continent of Europe. Although it was groundbreaking, it fell out of popularity when the Internet emerged in the '90s.
00:00:54.449 During this time, languages like Perl and Java became the de facto languages of the Internet, and Erlang was somewhat forgotten.
00:01:00.660 However, it's made a comeback recently as people realize there are still use cases for high-concurrency real-time systems on the Internet.
00:01:06.720 One of the neat things about Elixir and Erlang is that you can run thousands of processes concurrently, allowing for remarkable inter-process communication.
00:01:13.530 Imagine a telecom technology that routes thousands of phone calls in real time with servers that automatically cluster to create real-time distributed systems.
00:01:19.439 Erlang is like an ugly Ferrari—it's incredibly fast but has a somewhat difficult syntax that isn't very user-friendly.
00:01:25.890 José Valim came along and created Elixir, which runs on Erlang but has a more aesthetically pleasing Ruby-like syntax.
00:01:31.049 Although the similarity to Ruby is somewhat superficial, Elixir is a functional language, and how you use it differs significantly.
00:01:36.299 Now, it's sort of like a pretty Ferrari, combining amazing speed with a visually appealing interface.
00:01:42.830 Phoenix, built with Elixir, is an MVC framework that emphasizes productivity without sacrificing speed or maintainability.
00:01:48.000 Developed by Chris McCord, it shares many similarities with Rails. Phoenix has its own MVC architecture, routing, and generators.
00:01:54.449 It employs a package manager called Hex, which takes the best aspects of both Ruby's Gem and Bundler. Additionally, it features Mix, akin to Ruby's Rake.
00:02:03.899 Today, I will be discussing Ecto, the ORM that shares a feature set with Active Record, including queries, migrations, and validations.
00:02:10.229 Many people say that Phoenix represents the next evolution of Rails, which we will explore.
00:02:17.060 Phoenix is also many times faster than Ruby on Rails, which can sometimes make Rails feel slow.
00:02:22.430 Elixir and Phoenix can be particularly advantageous for real-time communication systems.
00:02:28.190 For instance, when sending messages from one phone to another in a mobile app built with Elixir, the message goes directly between servers without going through Redis.
00:02:35.540 In contrast, Rails 5's Action Cable requires messages to go through Redis. Ecto's architecture allows for more efficient real-time message transfer between servers.
00:02:42.830 This difference in architecture signifies a fundamentally faster model.
00:02:48.000 Using this technology, applications such as video conferencing systems and MMORPGs can be built more seamlessly.
00:02:54.780 An example is League of Legends, a popular game whose backend was built using Erlang.
00:03:01.010 Ecto, as an ORM, operates within an MVC framework built on telecommunications technology, somewhat like Rails but with additional capabilities.
00:03:07.170 Today, however, my focus is specifically on ORMs and how the designs of Ecto and Active Record contrast.
00:03:13.520 Throughout my experience, I've worked with various ORMs, primarily in Java and C#. I recently transitioned to working with Active Record and Ecto.
00:03:22.120 When I look at this list of ORMs, Active Record stands out due to its unique design.
00:03:28.190 Before diving deeper into ORMs, I want to touch upon functional programming.
00:03:36.930 Elixir is characterized as a functional language, which emphasizes avoiding state and mutable data.
00:03:41.430 This might not seem intuitive right away, so I'll explain that Elixir does not have traditional objects like Ruby. Instead, it has modules.
00:03:48.270 This means that there are no instance methods; it uses functions instead of methods and data.
00:03:54.170 It also does not allow mutations. For instance, if you modify a struct, you receive a new struct, leaving the old one unchanged.
00:04:00.650 This use of immutable persistent data structures causes a fundamental shift in how the language operates.
00:04:08.210 With that in mind, allow me to begin discussing Active Record.
00:04:14.080 You may have encountered Active Record before, so I'll provide an overview and set a foundation for our discussion on Ecto.
00:04:20.370 It's essential to understand what drives the design philosophies of Active Record and Ecto.
00:04:25.620 I created a demo app called Hallway Track, which I'll reference throughout this talk.
00:04:32.050 The premise revolves around attendees at conferences and the informal chats people have in the hallways.
00:04:37.560 So, how do we define the relationships here? A conference has many parties, and each party has several users.
00:04:42.590 Now, let's set up Active Record. We have our Party class, which includes scopes for conference dates.
00:04:49.710 Scopes are reusable query fragments, allowing us to create reusable bits of queries.
00:04:55.960 We can combine these scopes for specific queries. For example, we create a scope for conferences that started after a specific date.
00:05:02.200 With Active Record, the syntax is very readable, making it easy to understand at a glance.
00:05:09.610 As we go further into the code, we see our controllers and views all integrating smoothly.
00:05:16.790 However, a common issue that can arise is the N+1 query problem.
00:05:20.289 This happens when queries aren't preloaded, leading to additional database hits, which can degrade performance.
00:05:27.980 To address this, you'd add a preload method to your queries, but it complicates the initially readable syntax.
00:05:34.590 The result is that the elegant and simple Active Record syntax gets cluttered.
00:05:40.900 This leakiness often requires developers to remember implicit database interactions while using Active Record.
00:05:47.700 This can lead to confusion as developers try to abstract away the database details.
00:05:54.560 As I mentioned earlier, our frameworks can lead to complex debugging processes when it comes to understanding SQL queries.
00:06:01.820 In Active Record, the abstraction can limit your understanding of what's happening under the hood.
00:06:08.060 From my experiences, the SQL often becomes a background consideration rather than a primary focus.
00:06:14.230 Joe Armstrong once stated that, regarding objects, you may want a banana, but you'll get a gorilla holding it.
00:06:20.490 In this case, the active record model serves as the gorilla, complicating matters.
00:06:27.770 You've lost track of where the queries are scattered in the codebase.
00:06:34.420 The design allows for convenience but often sacrifices explicitness, which can impact performance.
00:06:39.360 Active Record does favor English-like syntax for the sake of readability.
00:06:45.380 While this may expedite developer productivity, it can lead to performance pitfalls.
00:06:51.890 As I mentioned earlier, convenience may often come at the cost of explicitness in these cases.
00:06:57.140 Now, let’s transition to Ecto to explore its approach.
00:07:03.230 Phoenix and Rails have a lot in common, particularly for CRUD applications, but Ecto delivers real-time communication capabilities that set it apart.
00:07:11.680 Ecto is not just a simple model. It's more comprehensive, comprising a repo, schema, changeset, and query.
00:07:17.420 First, we need to define the schema in the model file. In Active Record, fields are dynamic, but Ecto requires them to be explicitly defined.
00:07:23.440 In Ecto, this explicitness aids in clarity, ensuring we define relationships clearly between models.
00:07:29.270 Once the schema is defined, we can proceed to the controller, which maintains its own structure.
00:07:36.960 For instance, in the index action, we retrieve the request and response and handle them without relying on global state.
00:07:42.590 The repo module represents our database, and we access queries through it.
00:07:48.090 This structure separates responsibilities, allowing us to have both repo and query parts in our design.
00:07:55.140 The repository pattern separates the concerns defined in Martin Fowler's design patterns.
00:08:01.650 Active Record merges several models, leading to a somewhat confusing amalgamation of patterns.
00:08:07.290 What’s interesting is that Ecto has no save method, which deviates from the Active Record pattern.
00:08:14.420 In Ecto, you can't just modify and save an object directly. Instead, data is returned without methods.
00:08:19.540 Structs in Ecto are immutable, meaning that once a struct is created, it cannot be altered.
00:08:25.090 This absence of mutability fosters a different design philosophy compared to Active Record.
00:08:30.220 When we create queries in Ecto, we define them clearly, allowing for greater control and visibility.
00:08:38.370 The queries resemble SQL syntax, which enhances readability and manages interactions with the database.
00:08:45.860 We can also define our queries in a way that includes specific fields while avoiding the sometimes chaotic select star problem.
00:08:54.090 When we need to jump into complex queries or groupings, Ecto retains structured reasoning in defining relationships.
00:09:01.230 This clearer structure allows for tracking queries easier within the codebase without losing track.
00:09:08.510 If we examine the test performance of Ecto, we notice that tests are concurrent, running multiple at once.
00:09:15.780 This is due in part to how the Erlang VM manages concurrent processes, enhancing the overall performance during testing.
00:09:23.170 The use of Ecto also aligns with contemporary tools such as PostgreSQL, allowing the implementation of JSON types.
00:09:30.650 Adapting Ecto for nontraditional databases adds flexibility, making it possible to interact with different data sources.
00:09:38.920 As we explore these tools, it’s clear that Ecto and Active Record illustrate different paths through similar challenges.
00:09:45.420 In summary, there are trade-offs associated with each ORM. One is not necessarily superior, but they cater to various needs.
00:09:51.460 Ecto encourages explicitness in its structure, while Active Record focuses more on developer convenience.
00:09:57.470 Finally, I’d like to discuss considerations for choosing the ORM that suits your project best.
00:10:02.240 Resources such as the Bike Shed Podcast explore these topics in-depth. For anyone interested in immutability, I gave a talk at RubyConf titled "Change the Unchangeable."
00:10:08.020 If you’re curious about the distinctions between Ecto and Active Record, or interested in relating back to service architectures, there are exploration opportunities available.
00:10:16.470 Moreover, Procore is actively seeking developers and architects, so if interested, be sure to connect!