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.
- #assign_valid_email(user, at: 'example.com') ⇒ Object
-
#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_files(), 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_files(), 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_files(), header: true) @has_header_row = header @csv_file = Array(csv_file).find { |csv_file| File.exist?(csv_file) } raise "#{csv_file} does not exist" unless @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 |
#assign_valid_email(user, at: 'example.com') ⇒ Object
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'app/models/effective/csv_importer.rb', line 129 def assign_valid_email(user, at: 'example.com') raise 'expected an object that responds to email=' unless user.respond_to?('email=') # Normalize email user.email = user.email.to_s.strip.downcase.gsub(' ', '').presence user.email = nil unless user.email.to_s.count('@') == 1 # Assign if empty if user.email.blank? if user.respond_to?(:first_name) && user.respond_to?(:last_name) user.email ||= [user.first_name.to_s.parameterize.presence, user.last_name.to_s.parameterize.presence].compact.join('.').presence end if user.respond_to?(:full_name) user.email ||= user.full_name.to_s.parameterize.presence end if user.respond_to?(:name) user.email ||= user.name.to_s.parameterize.presence end user.email ||= user.object_id user.email = "#{user.email}@#{at.sub('@', '')}" end # Check for uniqueness unique = 0 email = user.email while user.class.where(email: email).where.not(id: user.id).present? pieces = user.email.split('@') email = pieces.first + "+#{(unique += 1)}@" + pieces.last end user.email = email user 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
173 174 175 176 |
# File 'app/models/effective/csv_importer.rb', line 173 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
169 170 171 |
# File 'app/models/effective/csv_importer.rb', line 169 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 truthy?(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
178 179 180 |
# File 'app/models/effective/csv_importer.rb', line 178 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 |