From 0f1dab1ad1fd15611d8c9f0ebf6362b336bc5672 Mon Sep 17 00:00:00 2001 From: Ilya Konanykhin Date: Mon, 27 Mar 2017 10:59:07 +0600 Subject: [PATCH] BikeCsvImporter: add import of brands as a separate step --- app/models/bike_csv_importer.rb | 31 +++++++++++++++++++++- app/models/bike_csv_importer/bike_attrs.rb | 10 ++++--- app/models/bike_csv_importer/cache.rb | 7 +++-- lib/tasks/import.rake | 11 ++++++++ 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/app/models/bike_csv_importer.rb b/app/models/bike_csv_importer.rb index da51a49..5b7c157 100644 --- a/app/models/bike_csv_importer.rb +++ b/app/models/bike_csv_importer.rb @@ -26,8 +26,9 @@ class BikeCsvImporter puts "Performing a #{dry_run ? 'DRY RUN' : 'LIVE RUN'} of import" fetch do |bike_hash| - bike = new_bike bike_hash + bike = new_bike bike_hash check_method = dry_run ? :valid? : :save + if bike.try check_method puts "Imported #{bike.shop_id}: #{bike}".green @@ -76,6 +77,34 @@ class BikeCsvImporter end end + # Imports new brands from CSV file (field 'make'). Will print out progress to stdout + # + # @param [Boolean] dry_run If true, does not save data, only shows the progress of validation + def brands(dry_run) + created_count, skipped_count = 0, 0 + + puts "Performing a #{dry_run ? 'DRY RUN' : 'LIVE RUN'} of brands import" + + fetch do |bike_hash| + make = clean_value bike_hash['make'] + brand = bike_attr_bike_brand make, true + check_method = dry_run ? :valid? : :save + + if brand.try :persisted? + puts "Skipped already existing brand #{brand.brand}" + skipped_count +=1 + elsif brand.try check_method + puts "Created brand #{brand.brand}".green + created_count += 1 + else + puts "Skipped #{brand.try(:brand) || make}: #{brand.try(:errors).try(:full_messages).try(:join, '; ') || 'object not created'}".red + skipped_count += 1 + end + end + + puts "#{created_count} brand created, #{skipped_count} brand skipped, total of #{created_count + skipped_count} rows in the CSV" + end + private diff --git a/app/models/bike_csv_importer/bike_attrs.rb b/app/models/bike_csv_importer/bike_attrs.rb index 375d90c..a478406 100644 --- a/app/models/bike_csv_importer/bike_attrs.rb +++ b/app/models/bike_csv_importer/bike_attrs.rb @@ -20,7 +20,7 @@ class BikeCsvImporter def bike_attrs(bike_hash) bike_attr_fields.each_with_object({}) do |(model_field, csv_field), memo| - memo[model_field] = send :"bike_attr_#{ model_field }", clean_value(bike_hash[csv_field]) + memo[model_field] = send :"bike_attr_#{model_field}", clean_value(bike_hash[csv_field]) end end @@ -52,9 +52,13 @@ class BikeCsvImporter value.try(:gsub, /[$]/, '').try :to_i end + def bike_attr_bike_brand(value, new_if_empty = false) + value = 'Unknown' if !value || value =~ /\Aunknown/i + cached_bike_brand value, new_if_empty + end + def bike_attr_bike_brand_id(value) - return unless value - cached_bike_brand(value).try :id + bike_attr_bike_brand(value, false).try :id end def bike_attr_bike_model_id(value) diff --git a/app/models/bike_csv_importer/cache.rb b/app/models/bike_csv_importer/cache.rb index 33b36a6..6a0e3a7 100644 --- a/app/models/bike_csv_importer/cache.rb +++ b/app/models/bike_csv_importer/cache.rb @@ -6,12 +6,15 @@ class BikeCsvImporter @bike_purpose_cache[purpose] ||= BikePurpose.find_by_purpose purpose end - def cached_bike_brand(brand) + def cached_bike_brand(brand, new_if_empty = false) @bike_brand_cache ||= {} if @bike_brand_cache.has_key? brand @bike_brand_cache[brand] else - @bike_brand_cache[brand] = BikeBrand.where('lower(brand) = ?', brand.downcase).first + bike_brand = BikeBrand.where('lower(brand) = ?', brand.downcase).first + bike_brand ||= BikeBrand.new(brand: brand) if new_if_empty + + @bike_brand_cache[brand] = bike_brand end end diff --git a/lib/tasks/import.rake b/lib/tasks/import.rake index d9a3b55..43367f3 100644 --- a/lib/tasks/import.rake +++ b/lib/tasks/import.rake @@ -21,5 +21,16 @@ namespace :import do next puts "File #{file} does not exist or is unreachable" unless File.readable? file BikeCsvImporter.new(file).analyze field ? [field] : [] end + + # Imports new brands from CSV file + # + # rake import:bikes:brands_csv[import.csv,dry] # dry run + # rake import:bikes:brands_csv[import.csv] # live import + task :brands_csv, [:file, :dry_run] => :environment do |t, args| + file, dry_run = args.values_at :file, :dry_run + next puts "Usage: rake #{t.name}[$csv_file_path[,$dry_run=dry]]" unless file + next puts "File #{file} does not exist or is unreachable" unless File.readable? file + BikeCsvImporter.new(file).brands dry_run == 'dry' + end end end