0
\$\begingroup\$

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
\$\endgroup\$
2
  • \$\begingroup\$ 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? \$\endgroup\$ Jan 18, 2019 at 16:21
  • \$\begingroup\$ The aim is updating the library active attribute based on the associated books. \$\endgroup\$ Jan 19, 2019 at 0:50

1 Answer 1

1
\$\begingroup\$

A couple of things:

  • 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.

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.