[Ruby on Rails (RoR)] Rails 7 adds change tracking methods for belongs_to associations

Rails 7 adds change tracking methods for belongs_to associations

Sometimes minor updates add the most joy to users! A recent Rails update introduced the ability to monitor for changes in belongs_to associations. This brings in a welcome change for developers who like to conform to “the Rails way”.

Before

Now, let’s try to do the same thing when a posts’ category changes.

1
2
3
4
5
6
7
8
9
10
11
12
class Post
belongs_to :category

before_update :record_activity

private
def record_activity
if self.category_id_changed?
# record an activity
end
end
end

This is an eyesore! We have an association called category, but we can’t monitor for its change. Rather, we have to resort to a rather crude way of monitoring for category_id changes. This isn’t very “the Rails way”.

After

Fortunately, Rails 7 now introduces a way to do this. With this PR, we can now do this.

1
2
3
4
5
6
7
8
9
10
11
12
class Post
belongs_to :category

before_update :record_activity

private
def record_activity
if self.category_changed?
# record an activity
end
end
end

The association_changed? method (assuming an association named :association) returns true if a different associated object has been assigned and, the foreign key will be updated in the next save!

We also get access to this method, association_previously_changed? which returns true if the previous save updated the association to reference a different associated object.

1
2
3
4
5
6
7
post.category # => #<Post category_id: 123, title: "Welcome to Rails!">
post.category_previously_changed? # => false

post.category = Category.second # => #<Post category_id: 456, title: "Welcome to Rails!">
post.save!

post.category_previously_changed? # => true

References

[1] Rails 7 adds change tracking methods for belongs_to associations | Saeloun Blog - https://blog.saeloun.com/2021/07/27/rails-7-belongs-to-change-tracking.html

[2] Add change tracking methods for belongs_to associations by georgeclaghorn · Pull Request #42751 · rails/rails - https://github.com/rails/rails/pull/42751

[3] https://github.com/rails/rails/blob/main/activerecord/CHANGELOG.md - https://github.com/rails/rails/blob/main/activerecord/CHANGELOG.md