Class: Effective::CSVImporter
- Inherits:
-
Object
- Object
- Effective::CSVImporter
- Defined in:
- app/models/effective/csv_importer.rb
Constant Summary collapse
- A =
0- B =
1- C =
2- D =
3- E =
4- F =
5- G =
6- H =
7- I =
8- J =
9- K =
10- L =
11- M =
12- N =
13- O =
14- P =
15- Q =
16- R =
17- S =
18- T =
19- U =
20- V =
21- W =
22- X =
23- Y =
24- Z =
25- AA =
26- AB =
27- AC =
28- AD =
29- AE =
30- AF =
31- AG =
32- AH =
33- AI =
34- AJ =
35- AK =
36- AL =
37- AM =
38- AN =
39- AO =
40- AP =
41- AQ =
42- AR =
43- AS =
44- AT =
45
Instance Attribute Summary collapse
-
#csv_file ⇒ Object
readonly
Returns the value of attribute csv_file.
-
#current_row ⇒ Object
readonly
Returns the value of attribute current_row.
-
#last_row ⇒ Object
readonly
Returns the value of attribute last_row.
Instance Method Summary collapse
- #after_import ⇒ Object
-
#assign_columns(obj, only: [], except: []) ⇒ Object
Takes an object and loops through all columns assigning the current row values.
-
#before_import ⇒ Object
Override me if you need some before/after hooks.
- #columns ⇒ Object
- #error(message) ⇒ Object
- #find(attributes) ⇒ Object
- #find!(attributes) ⇒ Object
-
#import! ⇒ Object
This runs through each row and calls process_row() on it.
-
#initialize(csv_file = default_csv_file(), header: true) ⇒ CSVImporter
constructor
A new instance of CSVImporter.
- #log(message) ⇒ Object
-
#normalize(column, value) ⇒ Object
Normalize the value based on column name.
- #process_row ⇒ Object
-
#rows ⇒ Object
Returns an Array of Arrays, with each row run through normalize.
- #warn(message) ⇒ Object
-
#where(attributes) ⇒ Object
UserStudentInfosImporter.new().where(id: 3, title: 'thing') Returns an Array of Hashes, representing any row that matches the selector.
- #where!(attributes) ⇒ Object
Constructor Details
#initialize(csv_file = default_csv_file(), header: true) ⇒ CSVImporter
Returns a new instance of CSVImporter.
12 13 14 15 16 17 |
# File 'app/models/effective/csv_importer.rb', line 12 def initialize(csv_file = default_csv_file(), header: true) @has_header_row = header @csv_file = csv_file raise "#{@csv_file} does not exist" unless File.exists?(@csv_file) end |
Instance Attribute Details
#csv_file ⇒ Object (readonly)
Returns the value of attribute csv_file.
5 6 7 |
# File 'app/models/effective/csv_importer.rb', line 5 def csv_file @csv_file end |
#current_row ⇒ Object (readonly)
Returns the value of attribute current_row.
5 6 7 |
# File 'app/models/effective/csv_importer.rb', line 5 def current_row @current_row end |
#last_row ⇒ Object (readonly)
Returns the value of attribute last_row.
5 6 7 |
# File 'app/models/effective/csv_importer.rb', line 5 def last_row @last_row end |
Instance Method Details
#after_import ⇒ Object
29 |
# File 'app/models/effective/csv_importer.rb', line 29 def after_import ; end |
#assign_columns(obj, only: [], except: []) ⇒ Object
Takes an object and loops through all columns assigning the current row values
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'app/models/effective/csv_importer.rb', line 111 def assign_columns(obj, only: [], except: []) assigns = ( if only.present? only = Array(only) columns.keep_if { |key, _| only.include?(key) } elsif except.present? except = Array(except) columns.delete_if { |key, _| except.include?(key) } end ) (assigns || columns).each do |column, _| obj.send("#{column}=", col(column)) if obj.respond_to?(column) end obj end |
#before_import ⇒ Object
Override me if you need some before/after hooks
28 |
# File 'app/models/effective/csv_importer.rb', line 28 def before_import ; end |
#columns ⇒ Object
19 20 21 |
# File 'app/models/effective/csv_importer.rb', line 19 def columns raise "Please define a method 'def columns' returning a Hash of {id: A, name: B}" end |
#error(message) ⇒ Object
133 134 135 136 |
# File 'app/models/effective/csv_importer.rb', line 133 def error() @errors_count += 1 puts "\n#{colorize('Error', :red)} (.csv line #{@current_row_number}) #{}" end |
#find(attributes) ⇒ Object
70 71 72 |
# File 'app/models/effective/csv_importer.rb', line 70 def find(attributes) where(attributes).first end |
#find!(attributes) ⇒ Object
74 75 76 |
# File 'app/models/effective/csv_importer.rb', line 74 def find!(attributes) find(attributes).presence || raise("csv row with #{attributes} not found") end |
#import! ⇒ Object
This runs through each row and calls process_row() on it
32 33 34 35 36 37 38 39 40 41 42 |
# File 'app/models/effective/csv_importer.rb', line 32 def import! log "Importing #{csv_file.split('/').last.sub('.csv', '')}" @errors_count = 0 before_import() with_each_row { process_row } after_import() log "Import complete (#{@errors_count} errors in #{@has_header_row ? @current_row_number-1 : @current_row_number} rows)" end |
#log(message) ⇒ Object
129 130 131 |
# File 'app/models/effective/csv_importer.rb', line 129 def log() puts "\n#{}"; end |
#normalize(column, value) ⇒ Object
Normalize the value based on column name
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'app/models/effective/csv_importer.rb', line 79 def normalize(column, value) column = column.to_s value = value.to_s if column.ends_with?('?') # Boolean ::ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(value) elsif column.ends_with?('_at') # DateTime parse_datetime(column, value) elsif column.ends_with?('_on') # Date parse_datetime(column, value).beginning_of_day elsif column.ends_with?('_to_i') value.to_i elsif column.ends_with?('_to_f') value.to_f elsif column.ends_with?('_to_s') value.to_s elsif column.ends_with?('_to_a') if ['[]', '{}'].include?(value) [] elsif value.starts_with?('{') && value.ends_with?('}') YAML::load(value).keys.select { |str| str.to_s.present? } else YAML::load(value).to_a.select { |str| str.to_s.present? } end elsif column == 'id' || column.ends_with?('_id') value.present? ? value.to_i : nil else value.presence end end |
#process_row ⇒ Object
23 24 25 |
# File 'app/models/effective/csv_importer.rb', line 23 def process_row raise "Please define a method 'def process_row' to process your row" end |
#rows ⇒ Object
Returns an Array of Arrays, with each row run through normalize
45 46 47 48 49 50 51 |
# File 'app/models/effective/csv_importer.rb', line 45 def rows @rows ||= [].tap do |rows| CSV.foreach(csv_file, headers: @has_header_row) do |row| rows << columns.map { |column, index| normalize(column, row[index].try(:strip).presence) } end end end |
#warn(message) ⇒ Object
138 139 140 |
# File 'app/models/effective/csv_importer.rb', line 138 def warn() puts "\n#{colorize('Warning', :yellow)} (.csv line #{@current_row_number}) #{}" end |
#where(attributes) ⇒ Object
UserStudentInfosImporter.new().where(id: 3, title: 'thing') Returns an Array of Hashes, representing any row that matches the selector
55 56 57 58 59 60 61 62 63 64 |
# File 'app/models/effective/csv_importer.rb', line 55 def where(attributes) raise 'expected a Hash of attributes' unless attributes.kind_of?(Hash) attributes.each { |column, _| raise "unknown column :#{column}" unless columns.key?(column) } rows.map do |row| if attributes.all? { |column, value| row[columns[column]] == value } columns.inject({}) { |retval, (column, index)| retval[column] = row[index]; retval } end end.compact end |
#where!(attributes) ⇒ Object
66 67 68 |
# File 'app/models/effective/csv_importer.rb', line 66 def where!(attributes) where(attributes).presence || raise("csv row with #{attributes} not found") end |