Created
August 18, 2009 16:17
-
-
Save brandon-beacher/169807 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
| 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 |
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
| 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 |
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
| 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