Hanami Repository Bulk Update Update multiple database records at once
Hanami Repository Bulk Update
Imagine that your team is tasked to implement a feature that enables a human to
review and publish a list of books. Most of the work has already been done, what
remains is to update the
published_at attribute of the subset of books that
were reviewed. To that end you’ll implement a
publish method on the
BookRepository that takes the list of reviewed books and updates them.
# lib/bookshelf/repositories/book_repository.rb # frozen_string_literal: true class BookRepository < Hanami::Repository def publish(reviewed_books) books .where(id: reviewed_books.map(&:id)) .update(published_at: Time.now) end end
The feature is a success and your users are happy. It turns out that there are a lot more bulk operations that users would like to be able to do. For now we want to enable users to set discounts for books in bulk. Again the UI is already updated and all we have left to do is implement this in our repository.
# lib/bookshelf/repositories/book_repository.rb # frozen_string_literal: true class BookRepository < Hanami::Repository def publish(reviewed_books) update_all(reviewed_books, published_at: Time.now) end def discount(books_on_sale, reduction_rate) # we validate the reduction rate at the controller level, it may even be a # value object update_all(books_on_sale, discount: reduction_rate.to_f) end private def update_all(books_to_update, **attribute_value_pairs) books .where(id: books_to_update.map(&:id)) .update(**attribute_value_pairs) end end
While it is tempting to just implement the generic
update_all method publicly
and use it outside of the repository this flexibility would come at a cost. The
knowledge of what publishing books or granting discounts means would potentially
be spread across our code base.
Instead we define less flexible but intention revealing methods that naturally attract behaviour pertaining to their responsibility.Twitter Facebook