Occasionally I need to iterate over the results of a query, and perform some operation on each item. Until recently, I was only aware of option 1 and option 2 below.
Option 1: Define a block for the iterator
class User
def anonymise
Users.find_each do |user|
user.update_columns email: "#{user.id}@devnullmail.com"
end
end
end
Option 2: Define a method on the User object, and then pass it to the find_each method
class AnonymiseUsers
include UseCasePattern
def perform
User.find_each &:anonymise
end
end
class User
def anonymise
update_columns email: "#{user.id}@devnullmail.com"
end
end
Option 3: Define a method, and then pass it to the find_each method
class AnonymiseUsers
include UseCasePattern
def perform
User.find_each &method(:anonymise)
end
private
def anonymise(user)
user.update_columns email: "#{user.id}@devnullmail.com"
end
end
This third option is useful. It allows me to keep the anonymise code out of the User class. Usually it’s best to keep related code together, and the code within AnonymiseUsers is not expected to be required elsewhere in the code base.
It also has the advantage of keeping the User class, which can often become a “God Class”, as slim as possible.