Article | Using any method with Ruby iterators

Using any method with Ruby iterators

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.

Message sent
Message could not be sent
|