Iterating over all Models in Rails

Posted by Matt on May 16, 2008

Neat little snippet of code in those odd times you need to loop over every model in your application programmatically.

This exact snippet loops over every model, and converts each timestamp (created_at, updated_at) to UTC. It can be quite helpful if you’re adding Time Zone support to your Rails 2.1 application and you have existing non-UTC timestamps.


Object.constants.each do |o|
  klass = eval(o, TOPLEVEL_BINDING)
  if klass.is_a?(Class) && klass.superclass == ActiveRecord::Base
    puts "\n\nUpdating #{klass} timestamps to UTC"
    klass.all.each do |obj|
      offset_hours = (Time.zone.utc_offset / 1.hour) * -1
      obj.created_at = obj.created_at + (obj.created_at.dst? ? offset_hours - 1 : offset_hours).hours
      obj.updated_at = obj.updated_at + (obj.updated_at.dst? ? offset_hours - 1 : offset_hours).hours
      obj.save
      print '.'
    end
  end
end

*Please note: I haven’t tested this very thoroughly, but it does seem to do the trick. As we know, Dates and Times can be total PITAs!

I Love Ruby

Posted by Matt on May 16, 2008

In the application I’m currently developing a User has_many Jobs, and each Job has a bunch of nested resources. The application calls for a Dashboard, filled with the latest changes to any Job the currently logged-in user is assigned to.

Sounds difficult huh?


def self.get_latest_items_for(current_user)
  assigned_job_ids = current_user.jobs.collect(&:id)
  find(:all, :conditions => ["job_id in (?)", assigned_job_ids])
end

In order to get the currently logged-in user’s list I just do:


RecentItem.get_latest_items_for(current_user)

Simple, elegant, understandable, and concise.