1

任何想法重構方法self.import_data的代碼?這是一種允許應用程序在數據庫中保存CSV文件的方法(對用戶電子郵件有一些限制)。它應該每天中午運行,所以它必須快速。 當我有一個很大的CSV文件時,它的運行時間很長。我想知道是否有辦法讓代碼更有效率並贏得一些時間(或避免循環或減少請求...)。我真的不知道究竟是什麼讓這個過程變得如此漫長,以及如何糾正它。如何在模型中製作更高效的代碼?

這裏是我的模型:

class Person < ActiveRecord::Base 
    has_paper_trail 
    validates :email, uniqueness: true 
    require 'csv' 

    def is_former_email?(update_email) 
    self.versions.each do |version| 
     next if version.object.nil? 
     return true if version.object.include?(update_email) 
    end 
    end 

def self.import_data 
    filename = File.join Rails.root, '/vendor/people.csv' 

    CSV.foreach(filename, headers: true, col_sep: ',') do |row| 
    firstname, lastname, home_phone_number, mobile_phone_number, email, address = row 

    person = Person.find_or_create_by(firstname: row["firstname"], lastname: row['lastname'], address: row['address']) 
    if person.is_former_email?(row['email']) == true 
     puts "not allowed" 
    else 
     person.update_attributes({firstname: row['firstname'], lastname: row['lastname'], home_phone_number: row['home_phone_number'], mobile_phone_number: row['mobile_phone_number'], address: row['address'], email: row['email']}) 
    end 
    end 
    end 
end 

回答

2

我是一個小重構你的代碼,但對於更有效地我推薦使用寶石activerecord-import和優化版本,型號爲搜索之前的電子郵件。

class Person < ActiveRecord::Base 
    require 'csv' 

    FILE_NAME = File.join Rails.root, '/vendor/people.csv' 

    validates :email, uniqueness: true 

    has_paper_trail 

    def self.import_data 
    people = CSV.new(File.new(FILE_NAME), headers: true, header_converters: :symbol, converters: :all).to_a.map(&:to_hash) 
    versions_by_item_id = Version.where(item_type: 'Person').select('item_id, object').group_by(&:item_id) 

    people.each do |person_params| 
     person = Person.find_or_create_by(person_params.slice(:firstname, :lastname, :address)) 
     if versions_by_item_id[person.id] && versions_by_item_id[person.id].sum { |v| v.object.to_s }.include?(person_params[:email]) 
     puts 'not allowed' 
     else 
     person.update_attributes(person_params.slice(:home_phone_number, :mobile_phone_number, :email)) 
     end 
    end 
    end 
end 
+0

謝謝Daniil對這個很好的事實。我只是有這個錯誤: IRB(主要):001:0> Person.import_data NameError:未初始化的常量人::版本從/home/ludy/inch-test/app/models/person.rb:12:in import_data。 但是好'Version'是一個表... – Orsay

+0

奧賽,你可以從控制檯嘗試Version.last? 也可以嘗試在:: Version.where重命名版本... –

+0

好吧這是因爲我要調用'PaperTrail :: Version.where ...'。所以,現在它的固定,我得到一個其它的錯誤...: PaperTrail ::版本的Load(0.4ms)選擇ITEM_ID,對象從「版本」 WHERE「版本」,「ITEM_TYPE」 =? [ 「ITEM_TYPE」, 「人」]] 人負荷(0.4ms)選擇 「人」。* FROM 「人」 WHERE 「人」。 「名字」=? AND「people」。「lastname」=?和「people」。「address」=? LIMIT 1 [[ 「姓名」, 「亨利」],[ 「姓氏」, 「杜邦」],[ 「地址」, 「10街拉布呂耶爾」]] NoMethodError:未定義的方法'+」爲零:NilClass – Orsay