00:00:09.960
My name is Mario Alberto Chavez, and I work for a development company. Today, I'm going to talk about rediscovering Active Record.
00:00:15.000
We are all familiar with Active Record. When I came to Rails years ago, the first thing I heard from people was that it was magic.
00:00:21.560
So let's get started. We just create or define a class, which is basically what we needed in order to work with a database.
00:00:29.920
However, over time, I found that there is no magic in Active Record. Active Record does some pretty cool things for us, hiding a lot of the complexity that comes from having a model connected to a table in the database. But in the end, there is no magic at all. What I want to do here is to explore the main actions that Active Record performs to transform a query into an object.
00:00:57.960
Let's start with a function that I'm sure we are all familiar with. You can think of it like a Russian doll. We are basically just using a generator. What we are going to end up with is something like this. I started with building gems, accessed autoloading magic, and opened up the console. I can run a query asking Active Record to access the database and pull a record with a specific ID. What we see below is the actual response.
00:01:39.560
In this case, I have an ID, name, and email address. Obviously, we will also have standard CRUD operations. But how can Active Record come from this to being able to execute? What is doing all the magic?
00:02:08.479
The first thing we need to understand is that Active Record needs to perform some kind of introspection. With this introspection, the first task that Active Record will perform is to ask the database what the schema is. Once we have this table schema, we can do a lot of things.
00:02:45.800
The first time we load JavaScript or CSS in our application and we attempt to execute any kind of operation like a query, the first action that will happen is that Active Record will try to load the necessary schema for that model. Basically, what it's doing is calling a method. If we fire up the console and use a model to call this attribute types method, we will find out that this method triggers something inside the Active Record code called 'load schema.' This method delegates the call to the actual database connection to ask for the schema relevant to that model.
00:03:21.959
So, every time—or at least the first time—we try to use a model, Active Record will go in, pull the table schema, make a copy of it, and cache it, making it ready for the next calls to these models. This means that only the first time for each model, we will perform this operation, effectively caching the schema so that subsequent calls don’t need to go to the database for it.
00:04:05.200
For example, if we call the schema cache column hash for the users table, we will retrieve a specific hash. The keys will be the columns of the table, and the values will be objects carrying a lot of information. Some important pieces of data we receive here include the attribute type. We can see that the database might be an integer type, but there will also be default values and other important metadata that we can use within Active Record.
00:05:16.120
Now that we see this cache schema method, it also needs to give us some extra information. Basically, what we need is a cast type. A cast type allows us to convert whatever the database tells us about the data type we are storing into how it should be represented on the Ruby side.
00:06:06.400
In the case of integers, for example, the transformation is straightforward—when we have an integer in the database, it practically remains an integer in Ruby. However, for complex data types like timestamps, we require a system to manage that casting.
00:06:39.840
Inside Active Record, it implements a base class to manage type casting. It typically has types such as active model type integer, string, date, among others, that help facilitate this process. Implemented in Rails 5, we can also create our own custom types. For instance, if we have a field in the database storing complex data, we might want to translate that into an object in our application. This custom data type does not necessarily have to be an Active Record model; it could be a struct or any type compatible with Rails.
00:07:21.680
In order to define our own data types in Rails, we need to implement at least three methods: serialize, cast, and the third is up to us. The serialize method specifies how we convert data from the database into a Ruby object. The cast method is used for user input to convert it from whatever format the user provides into the type stored in the database. Finally, we have the cast method, which defines how we convert Ruby types back into the database's data type.
00:08:00.760
Active Record has a way to pull the database schema. Now I just want to show one more thing, which is how Active Record provides this lazy loading mechanism. When we invoke something like attribute types, we are basically asking to see the response for what’s available in our model.
00:08:59.000
Inside this, we can still understand the schema, but we cannot actually run the query just yet. The actual query that needs to be performed requires us to create it. Active Record is smart enough to allow the creation of query objects for us.
00:09:21.360
When we execute a query, for example using the find method, it tries to see if that previous statement was executed before. If it has, it pulls that query without executing it again. If not, the find method converts the request into a new environment—everything gets wrapped inside a block.
00:11:05.000
In this block, we define the query, and Active Record works under the hood to convert that into SQL. When we want to retrieve, Active Record constructs the appropriate SQL statement for us.
00:11:49.600
The statement will then have placeholders, which means that when we execute our SQL queries, Rails takes care to bind values to these parameters. This method performs essential steps where the SQL gets prepared and executed without needing to define everything at once. It ensures that we efficiently retrieve only what we need and allows us to map results back into our Active Record objects.
00:12:57.360
Finalizing execution involves calling the execute method, which pulls the required ID for the record we want from the database. This will return a result set, which consists of rows and columns arranged in a structured manner.
00:14:05.559
Active Record then transforms this result set into instances of our models, effectively creating the objects that represent our data in a way that feels intuitive to work with.
00:15:16.839
From here, it has to allocate model objects and initialize attributes—making sure that for each record queried, the appropriate accessors are defined. When initializing attributes, Active Record checks if the attributes have already been set and will create the necessary methods on the fly.
00:16:10.759
This process is foundational to how we interact with our models, and it engages a whole series of internal processes that handle caching and efficient data retrieval.
00:16:57.680
Through all these unique steps, what we can see ultimately is that while Active Record does seem magical, it is simply performing a series of well-structured tasks that efficiently interacts with our database.
00:18:12.920
The key takeaway here is that understanding how Active Record works underneath the surface can enhance our effectiveness as developers. Curious exploration into the Rails framework can yield improvement in our development process.
00:19:33.400
As I was diving into this code, I discovered the intricate workings of Active Record, prompting me to share my insights. If you're interested in how Active Record operates, it’s worth taking the time to explore.
00:20:00.799
I encourage you to think of your tools with curiosity and dive deeper into their contexts. Whether through documentation, GitHub repositories, or simply testing out queries in a console, the experience can often be quite rewarding.
00:21:35.740
Thank you for being here today, and I hope you can take these insights back into your work with Rails. If there are any questions about Rails engines, feel free to ask.