Skip to content

Instantly share code, notes, and snippets.

@brandon-beacher
Created August 18, 2009 16:17
Show Gist options
  • Select an option

  • Save brandon-beacher/169807 to your computer and use it in GitHub Desktop.

Select an option

Save brandon-beacher/169807 to your computer and use it in GitHub Desktop.
class CreateJobs < ActiveRecord::Migration
def self.up
create_table :jobs, :force => true do |table|
table.timestamps
table.string :type, :null => false
table.integer :person_id, :null => false
table.boolean :running, :null => false, :default => true
table.text :exception, :default => nil
table.text :data
end
end
def self.down
drop_table :jobs
end
end
class Job < ActiveRecord::Base
def self.spawn(person_id, data)
job = create!(:person_id => person_id, :data => data)
job.spawn do
begin
job.run
rescue Exception => exception
job.update_attribute(:exception, :class => exception.class.to_s, :message => exception.message, :backtrace => exception.backtrace.join("\n"))
ensure
job.update_attribute(:running, false)
end
end
job
end
private
def update_data(hash)
update_attribute(:data, data.merge(hash))
end
end
class PeopleExportJob < Job
def run
update_data(:status => "preparing")
finder = Person.finder(data[:params])
filename = "#{Customer.current.layout}_people_#{Time.now.to_s(:filename_date_and_time)}.csv"
FasterCSV.open("tmp/#{filename}", "w", :force_quotes => true) do |csv|
csv << headers
page = 1
while true
people = finder.paginate(:page => page, :per_page => 200)
update_data(:status => "exporting", :offset => people.offset, :length => people.length, :total_entries => people.total_entries)
people.each do |person|
row = []
row << person.created_at
row << person.id
row << person.original_id
row << person.last_name
row << person.first_name
row << person.honorific
row << person.gender
row << person.listed
1.upto(maximum_memberships) do |sequence|
membership = person.memberships.primary_first[sequence - 1] || empty_membership
row << membership.primary
row << membership.kind
row << membership.parish.to_s
end
1.upto(maximum_emails) do |sequence|
email = person.emails.primary_first[sequence - 1] || empty_email
row << email.primary
row << email.kind
row << email.address
end
1.upto(maximum_phones) do |sequence|
phone = person.phones.primary_first[sequence - 1] || empty_phone
row << phone.primary
row << phone.kind
row << phone.number
row << phone.extension
end
1.upto(maximum_addresses) do |sequence|
address = person.addresses.primary_first[sequence - 1] || empty_address
row << address.primary
row << address.kind
row << address.street
row << address.city
row << address.state
row << address.zip
row << address.country_code
end
property_ids.each do |property_id|
value = person.values.detect { |value| value.property_id == property_id } || empty_value
row << value.value
end
csv << row
end
page += 1
break unless people.next_page
end
end
update_data(:status => "uploading")
AWS::S3::S3Object.store(filename, open("tmp/#{filename}"), "dfc_exports", :content_type => "text/csv")
url = AWS::S3::S3Object.url_for(filename, "dfc_exports", :expires_in => 24.hours)
update_data(:status => "complete", :url => url)
end
def empty_address
OpenStruct.new( "primary" => nil, "kind" => nil, "street" => nil, "city" => nil, "state" => nil, "zip" => nil, "country_code" => nil )
end
def empty_email
OpenStruct.new( "primary" => nil, "kind" => nil, "address" => nil )
end
def empty_membership
OpenStruct.new( "primary" => nil, "kind" => nil, "parish" => nil )
end
def empty_phone
OpenStruct.new( "primary" => nil, "kind" => nil, "number" => nil, "extension" => nil )
end
def empty_value
OpenStruct.new( "value" => nil )
end
def headers
person_headers + membership_headers + email_headers + phone_headers + address_headers + property_headers
end
def person_headers
["Created At", "ID", "Original ID", "Last Name", "First Name", "Honorific", "Gender", "Public profile?"]
end
def property_headers
Property.find(property_ids).collect { |property| property.pretty_name }
end
def address_headers
headers = []
1.upto(maximum_addresses) do |sequence|
headers << "Address #{sequence} Primary?"
headers << "Address #{sequence} Type"
headers << "Address #{sequence} Street"
headers << "Address #{sequence} City"
headers << "Address #{sequence} State/Province/Region"
headers << "Address #{sequence} Zip/Postal Code"
headers << "Address #{sequence} Country"
end
headers
end
def email_headers
headers = []
1.upto(maximum_emails) do |sequence|
headers << "Email #{sequence} Primary?"
headers << "Email #{sequence} Type"
headers << "Email #{sequence} Address"
end
headers
end
def membership_headers
headers = []
1.upto(maximum_memberships) do |sequence|
headers << "Membership #{sequence} Primary?"
headers << "Membership #{sequence} Type"
headers << "Membership #{sequence} #{Parish.human_name}"
end
headers
end
def phone_headers
headers = []
1.upto(maximum_phones) do |sequence|
headers << "Phone #{sequence} Primary?"
headers << "Phone #{sequence} Type"
headers << "Phone #{sequence} Number"
headers << "Phone #{sequence} Extension"
end
headers
end
def maximum_addresses
@maximum_addresses ||= Integer(Customer.connection.select_value(maximum_addresses_query))
end
def maximum_emails
@maximum_emails ||= Integer(Customer.connection.select_value(maximum_emails_query))
end
def maximum_memberships
@maximum_memberships ||= Integer(Customer.connection.select_value(maximum_memberships_query))
end
def maximum_phones
@maximum_phones ||= Integer(Customer.connection.select_value(maximum_phones_query))
end
def property_ids
@property_ids ||= Property.for_propertyable_type(Person).collect { |property| property.id }
end
def maximum_addresses_query
%{ select max(address_count) as maximum
from (
select addressable_id, count(*) as address_count
from addresses
where addressable_type = 'Person'
group by addressable_id ) as address_counts }
end
def maximum_emails_query
%{ select max(email_count) as maximum_emails
from (
select emailable_id, count(*) as email_count
from emails
where emailable_type = 'Person'
group by emailable_id ) as email_counts }
end
def maximum_memberships_query
%{ select max(membership_count) as maximum_memberships
from (
select person_id, count(*) as membership_count
from memberships
group by person_id ) as membership_counts }
end
def maximum_phones_query
%{ select max(phone_count) as maximum_phones
from (
select phoneable_id, count(*) as phone_count
from phones
where phoneable_type = 'Person'
group by phoneable_id ) as phone_counts }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment