Nigel Ramsay

Wellington, New Zealand

Using any method with Ruby iterators

07 March 2017

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.