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

この優れたリファクタはありがとうございます。私はこのエラーがあります: irb(main):001:0> Person.import_data NameError:未初期化定数Person :: Version from /home/ludy/inch-test/app/models/person.rb:12:in import_data。 良いVersionはテーブルです... – Orsay

+0

Orsay、Version.lastをコンソールから試すことはできますか? またバージョン名を変更してみてください:: Version.where ... –

+0

これは 'PaperTrail :: Version.where ... 'を呼び出さなければならないからです。これで修正されました。他のエラーが発生しました...: PaperTrail :: Version Load(0.4ms)SELECT item_id、object FROM "versions" WHERE "versions"。 "item_type" =? [["item_type"、 "Person"]] Person Load(0.4ms)SELECT "people"。* "FROM" people "WHERE" people "。" firstname "=? AND "people"。 "lastname" =? AND "人" "アドレス" =? LIMIT 1 [["firstname"、 "Henri"]、["lastname"、 "Dupont"]、["address"、 "10 Rue Labruyère"] NoMethodError:未定義メソッド '+ 'for nil:NilClass – Orsay

関連する問題