1

アクティブな管理者を使用していて、CSVファイルからデータベースにレコードをアップロードしています。ただし、ここでは2つの問題が発生します。提出された書類が欠落していて、2回目の実行が非常に週になるとコードが破損します。バッチ処理では実行できません。それは重要であり、私は多くの開発者がそのような問題の良い解決策を考えていると信じています。RailsでのCSVアップロードでのバッチ処理とエラー処理

require 'CSV' 
class CsvDb 
    class << self 
    def convert_save(model_name, csv_data, field_name=nil) 
     target_model = model_name.classify.constantize 
     csv_file = csv_data.read 
     row_headers={} 
     counter=0; 
     #Thread.new do 
       CSV.parse(csv_file) do |row| 
        if counter==0 
         temp=row 
         row_headers = Hash[temp.map.with_index.to_a] 
         counter +=1 
         next 
        end 
        unless row[row_headers["name"]].nil? 
         temp={} 
         business_type = row[row_headers["business_type_id"]] 
         business_type_id = business_type=='Online' ? 1: business_type=='Local' ? 2: 3 
         temp[:business_type_id]   = business_type_id 
         temp[:user_id]     = row[row_headers["user_id"]] 
         temp[:name]      = row[row_headers["name"]] 
         temp[:country_id]    = row[row_headers["country_id"]] 
         temp[:homepage]     = row[row_headers["homepage"]] ||="" 
         temp[:telephone]    = row[row_headers["telephone"]] ||="" 
         temp[:email]     = row[row_headers["email"]] ||="" 
         temp[:address]     = row[row_headers["address"]] ||="" 
         temp[:latitude]     = row[row_headers["latitude"]] 
         temp[:longitude]    = row[row_headers["longitude"]] 
         temp[:facebook]     = row[row_headers["facebook"]] ||="" 
         temp[:twitter]     = row[row_headers["twitter"]] ||="" 
         temp[:google]     = row[row_headers["google"]] ||="" 
         temp[:instagram]    = row[row_headers["instagram"]] ||="" 
         temp[:pinterest]    = row[row_headers["pinterest"]] ||="" 
         temp[:free_shipping]   = row[row_headers["free_shipping"]] 
         temp[:ship_details]    = row[row_headers["ship_details"]] ||="" 
         temp[:category_ids]    = [row[row_headers["category_ids"]]] 
         temp[:style_ids]    = [row[row_headers["style_ids"]]] 
         temp[:shipping_country_ids]  = [row[row_headers["shipping_country_ids"]]] 
         temp[:filter_ids]    = [row[row_headers["filter_ids"]]] 
         business = target_model.new(temp) 
         business.save 
        end 
       end 
       ActiveRecord::Base.connection.close 
     end 
    #end 
    end 
end 
+0

任意の提案やトリックをhhighly理解されるであろう。 –

答えて

0

ここでは、CSVの行をオブジェクトに変換することに焦点を当てます。身体以外の部分には多くの繰り返しがあります。これらの行はすべて一度言及してから、このようなハードコーディングではなくループで処理する必要があります。例えば。

unless row[row_headers["name"]].nil? 
    temp={} 
    business_type = row[row_headers["business_type_id"]] 
    business_type_id = business_type == "Online" ? 1: business_type == "Local" ? 2 : 3 
    temp[:business_type_id] = business_type_id 
    for name in [:user_id, :name, :country_id, :latitude, :longitude, :free_shipping, :category_ids, :style_ids, :shipping_country_ids] 
     temp[name] = row[row_headers[name.to_s]] 
    end 
    for name in [:homepage, :telephone, :email, :address, :facebook, :twitter, :google, :instagram, :pinterest, :ship_details] 
     temp[name] = row[row_headers[name.to_s]] ||= "" 
    end 
    business = target_model.new(temp) 
    business.save 
end 

代替ソリューションは、コードレビューサイトから受け取っ:

CSV.parse(csv_file, {headers: true, header_converters: :symbol}) do |row| 
    business_type_id = case row[:business_type_id] 
         when 'Online' then 1 
         when 'Local' then 2 
         else 3 
         end 

    target_model.new({business_type_id: business_type_id} + extract_required_fields(row) + extract_optionals_fiels(row)) 
       .save() 

end 

def extract_required_fields(row) 
    [:user_id, :name, :country_id, :free_shipping, :category_ids, :style_ids, :shipping_country_ids] 
    .reduce({}) do |carry, item| 
     carry[item] = row[item] 
    end 
end 

def extract_optionals_fiels(row) 
    [:homepage, :telephone, :email, :address, :facebook, :twitter, :google, :instagram, :pinterest, :ship_details] 
    .reduce({}) do |carry, item| 
     carry[item] = row[item] ||= '' 
    end 
end