Whenever an object is updated, ActiveRecord allows belongs_to associations to automatically call the touch method on their parent object.
- [Instructor] In this movie, we will learn how to tell Active Record to automatically Touch Associated Records whenever a record is updated. We've already learned about touch in a previous chapter. It's an active record method that we can call on a single object. So for example, we can find a category in the database and then we can call touch on it. And what it does is it updates that object's updated at or updated on timestamp to be the current time. We can do the same thing in our associations. An Active Record will automatically touch that associated object whenever this object is saved.
So in this case, if we had a product object that had a category object associated to it, whenever we save, update, or destroy the product object, Active Record will automatically touch the related category object. That is, it'll set its updated at or updated on timestamp to the current time. Note that this only works on belongs to associations. If you wanted to use it on another kind of association, you would have to write custom code that would do that. We'll learn about callbacks a bit later.
Callbacks are the way that you would do that. So this is only on belongs to associations. You could use touch whenever an update to a child record should also be considered as an update to the parent record. It's also worth noting that when that associated object is being touched, none of its validations are actually going to be run. It's just simply going to update that timestamp. Most of the time, you're going to call touch with a value true. However, you could also specify another timestamp that you'd like it to update.
So here, for example, there's another column on categories which is called products_updated_at and I'm asking the association to update that timestamp on the category. Note that it also does this in addition to updating the updated at, updated on timestamp. This is just an additional column that we're updating. So it's still going to touch the updated at timestamp, we're just telling it to also update another one. Let's try this out in our demo project. So inside our project, let's go to our product model.
Remember, this only works with the belongs to associations. So that's where we want to put our touch, is on belongs to. So belongs_to category and then we'll just add an option to that. Touch, true, that's it, that's all we have to do. Now whenever we have our product and we make a change to it, create, update, or delete it, its parent category will also get touched automatically. Let's save that file and let's try it out. Let's go to our console rails c, inside the root of our project and let's start by finding a product.
I'm going to find product and I'm going to find a product but I also am going to go ahead and use includes to get its category. We know that we're going to want the category. So we know how to do includes now. Then I'm going to find the product with ID 4. That's going to be my sofa. So product ID 4 is a Sofa and let's look at its category. Product.category.name, it's Furniture. And let's also look at the price of this product. It has no price set.
Okay, so what I'm going to do is I'm going to set a price for it. And when I do, when I update the price on the product, it should touch the category at the same time. I'm going to clear my screen. And let's start by reviewing our starting values of updated at. So product.updated_at to string, that's my starting value. If you've been working along with me, you almost certainly have something different than me, that's fine. Click the up arrow and now let's ask the product category for its updated at. Okay, so those are my two starting values.
That's the values that I have to begin with. Those values ought to change when I update the price. So, let's do that. Let's do product.update_attributes and use price with 300. Alright, I'm going to hit return and notice the SQL that it created. Notice that it updates products and it sets the price. It set the products updated_at at the same time. That's a normal Active Record behavior. It always magically updates that updated at column whenever we make changes to these attributes.
Notice also though that it made another update to the categories. And it set its updated_at value to the same thing. Let's go back and let's check our values. I'm going to hit the up arrow. Product.updated_at, of course, got updated. And product.category.updated_at also got updated. Okay, let's try another one. Let's do product.touch. Let's just touch our product. Touching the product should update its updated_at. Will it then also update the category? Yes, it does.
You can see that it updated the product with something that's one minute later and it did the same thing for categories. Okay, let's try another one. Now let's try product.increment the inventory. I'm going to use exclamation point so that it will save when it increments automatically. Inventory, here we go. Hit return. Now notice it only fired off one SQL statement. It did not update the category. It only made an update to our products table.
And if you look carefully at what it did to the products table, you'll see that it didn't even update the updated at on the products table. That's the way increment works. Increment bypasses the callbacks. It skips all the callbacks and that includes the automatic callback that we've put here by adding touch true. So you want to use caution whenever you're using methods which skip callbacks. But most of the time, adding touch as an option to your association will update the parent record automatically for you in the background.
- Migrating databases
- Creating, updating, and deleting records
- Tracking changes to objects and attributes
- Writing queries
- Delegating attributes
- Working with associations