Created
March 23, 2012 16:32
-
-
Save betawaffle/2172507 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# in config/initializers | |
ActiveRecord::Relation.class_eval do | |
include EachRow | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module EachRow | |
def each_row &block | |
return to_enum(:each_row) unless block_given? | |
sql = to_sql | |
res = connection.execute(sql) | |
res.each do |row| | |
yield row | |
end | |
res.clear | |
nil | |
end | |
# WARNING: This is way too clever for anyone's good. | |
# Paramaters passed depend on the name you give them in the block. | |
# | |
# Example: | |
# lazy_map_rows do |id, updated_at| | |
# "#{self.class} with id #{id} was last updated at #{updated_at}" | |
# end | |
def lazy_map_rows mapper = nil, &block | |
return to_enum(:lazy_map_rows, block) unless mapper | |
return to_enum(:lazy_map_rows, mapper) unless block | |
table = arel_table | |
query = except(:select) | |
cols = mapper.parameters.map do |(_, col)| | |
query = query.select table[col] | |
col.to_s | |
end | |
proc = lambda do |row| | |
mapper.call *row.values_at(*cols) | |
end | |
sql = query.to_sql | |
res = connection.execute(sql) | |
res.each { |row| yield proc.call(row) } | |
res.clear | |
nil | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# NOTE: #each_row and #lazy_map_rows probably only work with Postgres. | |
# NOTE: #lazy_map_rows most likely only works on MRI 1.9.3 or later. | |
# Assume a model defined as so: | |
# Tag(id: integer, name: string, created_at: datetime, updated_at: datetime) | |
class Tag < ActiveRecord::Base | |
# EachRow methods can be called on any scope. | |
# Use .scoped or .unscoped if you don't use query methods first. | |
end | |
# And the associated table has the following data: | |
# [#<Tag id: 1, name: "socks", created_at: "2012-02-27 22:40:46", updated_at: "2012-02-27 22:40:46">, | |
# #<Tag id: 2, name: "hateful", created_at: "2012-02-27 22:40:46", updated_at: "2012-02-27 22:40:46">, | |
# #<Tag id: 3, name: "streamage", created_at: "2012-03-16 15:39:05", updated_at: "2012-03-16 15:39:05">, | |
# #<Tag id: 4, name: "empty", created_at: "2012-03-20 13:58:46", updated_at: "2012-03-20 13:58:46">] | |
# Each of the following examples will perform ONLY 1 iteration of the rows in the table. | |
tags = Tag.scoped.with_whatever.you_want | |
tags.lazy_map_rows { |id, name| "#{id} => #{name}" }.to_a | |
# => ["1 => socks", "2 => hateful", "3 => streamage", "4 => empty"] | |
tags.lazy_map_rows { |created_at, name| "#{name} was created at #{created_at}" }.to_a | |
# => ["socks was created at 2012-02-27 22:40:46.426997", | |
# "hateful was created at 2012-02-27 22:40:46.447398", | |
# "streamage was created at 2012-03-16 15:39:05.242834", | |
# "empty was created at 2012-03-20 13:58:46.88798"] | |
# Please Enjoy Responsibly! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment