# Updating one model field based on the associated model's field

I'm wondering if there is any way we can optimize the following code. Scenario is Library's active field should be true if it has any available book.

class Book < ApplicationRecord
belongs_to :library
scope :available, -> { where.not(deleted: true) }

after_commit :update_library_active, on: [:update, :create]

def update_library_active
self.library.update_active_status
end

end

class Library < ApplicationRecord
has_many :books

def update_active_status
self.update(active: books.available.present?)
end

end

• Is the aim here to be able to list all of the libraries that are active, or for an individual library to be able to state whether it is active or not? – David Aldridge Jan 18 '19 at 16:21
• The aim is updating the library active attribute based on the associated books. – Bibek Sharma Jan 19 '19 at 0:50

• I wouldn't do this in the after_commit handler. If you do it before the commit then an error here would cause the whole transaction to fail whereas doing it after committing could potentially result in an inconsistent database.
• You also want to update the library when a destroy happens which you currently doing. Even though it looks like you are using soft deletion I would consider it a good idea to cover all your bases.
• books.available.exists? usually performs a little better than books.available.present? in this situation. (Because I can almost guarantee from experience that you are going to completely destroy bad data manually for some reason)
• If you are need to optimize for performance you might want to check if destroyed? || deleted_changed? before running the query.
• Additionally you could be more intelligent and factor in the value of the deleted flag on the current record. i.e. if it is false then you can make the library active without running a second query.