rails-importer 0.0.9 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +59 -5
- data/config/locales/importers.en.yml +4 -1
- data/lib/rails_importer/base.rb +47 -20
- data/lib/rails_importer/version.rb +1 -1
- metadata +3 -4
- data/lib/rails_importer/_importer.rb +0 -138
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bea8cb112642a3e3695ba97fefcbe5637e685f6
|
4
|
+
data.tar.gz: d1df31e5b7cef7266dafc0c0d556ab135349bb9e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de85def8d858626a261969cb6b62a53353ac8e1fbd7d5c6ec06b306c3a97509adab58f2bac405e354e5ed208a6f8c32170748c4c22b5e77aa21dd04d42db01a2
|
7
|
+
data.tar.gz: 1f87419a56c6b27b455181e5f294a92e855ad64bf2ca00ddddc0cfcd652346e97fa31ce3377f9f0282220831ea6925db2bc4450f42363caaee9968ec5375c979
|
data/README.md
CHANGED
@@ -53,14 +53,68 @@ end
|
|
53
53
|
### How to use
|
54
54
|
|
55
55
|
You can call `import` from **Importers** objects:
|
56
|
-
|
56
|
+
**file param** must be an object that responds to `.path` method
|
57
|
+
```ruby
|
57
58
|
file = params[:import][:file]
|
58
|
-
records = ExampleImporter.import(file
|
59
|
+
records = ExampleImporter.import(file)
|
59
60
|
```
|
60
61
|
|
61
62
|
Or with context:
|
63
|
+
```ruby
|
64
|
+
file = params[:import][:file]
|
65
|
+
records = ExampleImporter.import(file, context: :simple)
|
66
|
+
```
|
67
|
+
|
68
|
+
Overwrite default fields (called in the block `importer do`):
|
69
|
+
```ruby
|
70
|
+
file = params[:import][:file]
|
71
|
+
records = ExampleImporter.import(file, fields: [:name, :email, :age])
|
72
|
+
```
|
62
73
|
|
63
|
-
|
74
|
+
With extra params:
|
75
|
+
```ruby
|
64
76
|
file = params[:import][:file]
|
65
|
-
records = ExampleImporter.import(file,
|
66
|
-
```
|
77
|
+
records = ExampleImporter.import(file, {user: 'john@mail.com'})
|
78
|
+
```
|
79
|
+
Then inside each record you can get params:
|
80
|
+
```ruby
|
81
|
+
class ExampleImporter < RailsImporter::Base
|
82
|
+
importer do
|
83
|
+
# ...
|
84
|
+
each_record do |record, params|
|
85
|
+
# ...
|
86
|
+
params[:user]
|
87
|
+
# ...
|
88
|
+
end
|
89
|
+
# ...
|
90
|
+
end
|
91
|
+
end
|
92
|
+
```
|
93
|
+
|
94
|
+
With full options:
|
95
|
+
```ruby
|
96
|
+
file = params[:import][:file]
|
97
|
+
records = ExampleImporter.import(file,
|
98
|
+
context: :simple,
|
99
|
+
fields: [:name, :email, :age],
|
100
|
+
{user: 'john@mail.com', account: '1'})
|
101
|
+
```
|
102
|
+
|
103
|
+
To return imported values, you need to return values inside of `each_record`:
|
104
|
+
```ruby
|
105
|
+
class ExampleImporter < RailsImporter::Base
|
106
|
+
importer do
|
107
|
+
# ...
|
108
|
+
each_record do |record, params|
|
109
|
+
# ...
|
110
|
+
u = Model.new(record)
|
111
|
+
u.created_by = params[:user]
|
112
|
+
ok = !!u.save
|
113
|
+
return {record: u, success: ok}
|
114
|
+
end
|
115
|
+
# ...
|
116
|
+
end
|
117
|
+
end
|
118
|
+
records = ExampleImporter.import(file, {user: 'john@mail.com'})
|
119
|
+
# [{record: ..., success: true}, {record: ..., success: false}]
|
120
|
+
```
|
data/lib/rails_importer/base.rb
CHANGED
@@ -8,18 +8,23 @@ module RailsImporter
|
|
8
8
|
class << self
|
9
9
|
def import(file, *args)
|
10
10
|
context = args.try(:context) || :default
|
11
|
+
custom_fields = args.try(:fields) || nil
|
11
12
|
result = []
|
12
13
|
begin
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
if file.respond_to?(:path)
|
15
|
+
ext = (File.extname(file.path)[1..-1] rescue '')
|
16
|
+
if self.file_types.include?(ext.to_sym)
|
17
|
+
rows = self.send('import_from_%s' % ext, file, context, custom_fields)
|
18
|
+
if rows.present? && rows.is_a?(Array)
|
19
|
+
result = rows.map do |record|
|
20
|
+
self.importers[context][:each_record].call(record, *args) if self.importers[context][:each_record].is_a?(Proc)
|
21
|
+
end.compact
|
22
|
+
end
|
23
|
+
else
|
24
|
+
result = I18n.t(:invalid_file_type, file_types: self.file_types.join(', '), scope: [:importer, :error])
|
20
25
|
end
|
21
26
|
else
|
22
|
-
I18n.t(:
|
27
|
+
result = I18n.t(:invalid_file, scope: [:importer, :error])
|
23
28
|
end
|
24
29
|
rescue Exception => e
|
25
30
|
result = e.message
|
@@ -57,19 +62,19 @@ module RailsImporter
|
|
57
62
|
end
|
58
63
|
|
59
64
|
private
|
60
|
-
def import_from_csv(file, context = :default)
|
65
|
+
def import_from_csv(file, context = :default, custom_fields = :nil)
|
61
66
|
records = []
|
62
67
|
line = 0
|
63
68
|
CSV.foreach(file.path, {:headers => false, :col_sep => ';', :force_quotes => true}) do |row|
|
64
69
|
if line > 0
|
65
|
-
records << object_values(row, context) unless array_blank?(row)
|
70
|
+
records << object_values(row, context, custom_fields) unless array_blank?(row)
|
66
71
|
end
|
67
72
|
line += 1
|
68
73
|
end
|
69
74
|
records
|
70
75
|
end
|
71
76
|
|
72
|
-
def import_from_xml(file, context = :default)
|
77
|
+
def import_from_xml(file, context = :default, custom_fields = :nil)
|
73
78
|
records = []
|
74
79
|
xml_structure = self.importers[context][:xml_structure]
|
75
80
|
xml = Hash.from_xml(file.read)
|
@@ -77,33 +82,33 @@ module RailsImporter
|
|
77
82
|
xml = xml[node.to_s]
|
78
83
|
end
|
79
84
|
xml.each do |elem|
|
80
|
-
records << object_values(elem.values, context) unless array_blank?(elem.values)
|
85
|
+
records << object_values(elem.values, context, custom_fields) unless array_blank?(elem.values)
|
81
86
|
end
|
82
87
|
records
|
83
88
|
end
|
84
89
|
|
85
|
-
def import_from_xls(file, context = :default)
|
90
|
+
def import_from_xls(file, context = :default, custom_fields = :nil)
|
86
91
|
records = []
|
87
92
|
Spreadsheet.client_encoding = 'UTF-8'
|
88
93
|
document = Spreadsheet.open(file.path)
|
89
94
|
spreadsheet = document.worksheet 0
|
90
95
|
spreadsheet.each_with_index do |row, i|
|
91
96
|
next if i.zero?
|
92
|
-
records << object_values(row, context) unless array_blank?(row)
|
97
|
+
records << object_values(row, context, custom_fields) unless array_blank?(row)
|
93
98
|
end
|
94
99
|
records
|
95
100
|
end
|
96
101
|
|
97
|
-
def object_values(array, context = :default)
|
98
|
-
attributes = self.importers[context][:fields]
|
102
|
+
def object_values(array, context = :default, custom_fields = nil)
|
103
|
+
attributes = custom_fields || self.importers[context][:fields]
|
99
104
|
attributes = attributes.keys if attributes.is_a?(Hash)
|
100
|
-
|
101
|
-
hash_values = Hash[attributes.zip(
|
105
|
+
values = equalize_columns_of_values(attributes, array)
|
106
|
+
hash_values = Hash[attributes.zip(values)]
|
102
107
|
attributes.each do |attr|
|
103
108
|
if hash_values[attr].present?
|
104
109
|
if hash_values[attr].is_a?(Numeric)
|
105
110
|
hash_values[attr] = hash_values[attr].to_i if hash_values[attr].modulo(1).zero?
|
106
|
-
hash_values[attr] = (hash_values[attr].to_s.strip rescue
|
111
|
+
hash_values[attr] = (hash_values[attr].to_s.strip rescue I18n.t(:convert_number_to_text, scope: [:importer, :error]))
|
107
112
|
elsif hash_values[attr].is_a?(Date)
|
108
113
|
hash_values[attr] = (I18n.l(hash_values[attr], format: '%d/%m/%Y') rescue hash_values[attr]).to_s
|
109
114
|
elsif hash_values[attr].is_a?(DateTime)
|
@@ -126,7 +131,7 @@ module RailsImporter
|
|
126
131
|
def importer_value(key, attributes)
|
127
132
|
if attributes.present?
|
128
133
|
if key == :fields
|
129
|
-
self.importers[@importer_name][key] = (attributes
|
134
|
+
self.importers[@importer_name][key] = normalize_fields(attributes)
|
130
135
|
else
|
131
136
|
self.importers[@importer_name][key] = attributes
|
132
137
|
end
|
@@ -134,6 +139,28 @@ module RailsImporter
|
|
134
139
|
self.importers[@importer_name][key]
|
135
140
|
end
|
136
141
|
end
|
142
|
+
|
143
|
+
def normalize_fields(attributes)
|
144
|
+
if attributes.first.is_a?(Hash)
|
145
|
+
attributes.inject(:merge)
|
146
|
+
elsif attributes.first.is_a?(Array)
|
147
|
+
attributes.flatten
|
148
|
+
else
|
149
|
+
attributes
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def equalize_columns_of_values(attributes, values=[])
|
154
|
+
if attributes.size > values.size
|
155
|
+
diff_size = (attributes.size - values.size).abs
|
156
|
+
values + Array.new(diff_size, nil)
|
157
|
+
elsif attributes.size < values.size
|
158
|
+
values[0...attributes.size]
|
159
|
+
else
|
160
|
+
values
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
137
164
|
end
|
138
165
|
|
139
166
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-importer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bruno Porto
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-03-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -67,7 +67,6 @@ files:
|
|
67
67
|
- lib/generators/templates/generic_importer.erb
|
68
68
|
- lib/rails-importer.rb
|
69
69
|
- lib/rails_importer.rb
|
70
|
-
- lib/rails_importer/_importer.rb
|
71
70
|
- lib/rails_importer/base.rb
|
72
71
|
- lib/rails_importer/engine.rb
|
73
72
|
- lib/rails_importer/version.rb
|
@@ -91,7 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
90
|
version: '0'
|
92
91
|
requirements: []
|
93
92
|
rubyforge_project:
|
94
|
-
rubygems_version: 2.6.
|
93
|
+
rubygems_version: 2.6.14
|
95
94
|
signing_key:
|
96
95
|
specification_version: 4
|
97
96
|
summary: Rails Importer
|
@@ -1,138 +0,0 @@
|
|
1
|
-
require 'ostruct'
|
2
|
-
|
3
|
-
module RailsImporter
|
4
|
-
|
5
|
-
def self.included(base)
|
6
|
-
base.extend ClassMethods
|
7
|
-
|
8
|
-
base.define_singleton_method 'colunas' do |*args|
|
9
|
-
@importacao_colunas = nil unless @importacao_colunas.present?
|
10
|
-
if args.present?
|
11
|
-
@importacao_colunas = (args.first.is_a?(Hash) ? args.inject(:merge) : args)
|
12
|
-
else
|
13
|
-
@importacao_colunas
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
base.define_singleton_method 'estrutura_xml' do |*args|
|
18
|
-
@importacao_estrutura_xml = nil unless @importacao_estrutura_xml.present?
|
19
|
-
if args.present?
|
20
|
-
@importacao_estrutura_xml = args
|
21
|
-
else
|
22
|
-
@importacao_estrutura_xml
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
base.define_singleton_method 'para_cada_linha' do |&block|
|
27
|
-
define_singleton_method('importar_registro') do |registro, *args|
|
28
|
-
block.call(registro, *args)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.tipos_de_arquivos
|
35
|
-
[:csv, :xls, :xml]
|
36
|
-
end
|
37
|
-
|
38
|
-
module ClassMethods
|
39
|
-
|
40
|
-
def importacao(&block)
|
41
|
-
block.call if block_given?
|
42
|
-
self.class.class_eval do
|
43
|
-
define_method :importar do |arquivo, *args|
|
44
|
-
retorno = []
|
45
|
-
begin
|
46
|
-
ext = (File.extname(arquivo.path)[1..-1] rescue nil)
|
47
|
-
if arquivo.respond_to?(:path) and RailsImporter.tipos_de_arquivos.include?(ext.to_sym)
|
48
|
-
registros = self.send("#{ext}_para_array", arquivo)
|
49
|
-
if registros.present? and registros.is_a?(Array)
|
50
|
-
retorno = registros.map do |registro|
|
51
|
-
importar_registro(registro, *args)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
else
|
55
|
-
raise "Tipo de arquivo inválido. Arquivos permitidos: #{RailsImporter.tipos_de_arquivos.join(', ')}"
|
56
|
-
end
|
57
|
-
rescue Exception => e
|
58
|
-
retorno = e.message
|
59
|
-
end
|
60
|
-
retorno
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
private
|
66
|
-
def csv_para_array(arquivo)
|
67
|
-
registros = []
|
68
|
-
linha=0
|
69
|
-
CSV.foreach(arquivo.path, {:headers => false, :col_sep => ';', :force_quotes => true}) do |row|
|
70
|
-
if linha>0
|
71
|
-
registros << object_values(row) unless array_blank?(row)
|
72
|
-
end
|
73
|
-
linha+=1
|
74
|
-
end
|
75
|
-
registros
|
76
|
-
end
|
77
|
-
|
78
|
-
def xml_para_array(arquivo)
|
79
|
-
registros = []
|
80
|
-
estrutura_xml = self.send(:estrutura_xml)
|
81
|
-
if estrutura_xml.present? and estrutura_xml.is_a?(Array) and estrutura_xml.count > 0
|
82
|
-
xml = Hash.from_xml(arquivo.read)
|
83
|
-
estrutura_xml.each do |node|
|
84
|
-
xml = xml[node.to_s]
|
85
|
-
end
|
86
|
-
xml.each do |elem|
|
87
|
-
registros << object_values(elem.values) unless array_blank?(elem.values)
|
88
|
-
end
|
89
|
-
else
|
90
|
-
raise 'Você precisa informar a estrutura_xml no seu Model'
|
91
|
-
end
|
92
|
-
registros
|
93
|
-
end
|
94
|
-
|
95
|
-
def xls_para_array(arquivo)
|
96
|
-
registros = []
|
97
|
-
Spreadsheet.client_encoding = 'UTF-8'
|
98
|
-
documento = Spreadsheet.open(arquivo.path)
|
99
|
-
planilha = documento.worksheet 0
|
100
|
-
planilha.each_with_index do |row, i|
|
101
|
-
next unless i>0
|
102
|
-
registros << object_values(row) unless array_blank?(row)
|
103
|
-
end
|
104
|
-
registros
|
105
|
-
end
|
106
|
-
|
107
|
-
def object_values(array)
|
108
|
-
atributos = self.send(:colunas)
|
109
|
-
atributos = atributos.keys if atributos.is_a?(Hash)
|
110
|
-
args = array[0...atributos.size]
|
111
|
-
hValores = Hash[atributos.zip(args)]
|
112
|
-
#Ajustando valores inválidos
|
113
|
-
atributos.each do |atributo|
|
114
|
-
if hValores[atributo].present?
|
115
|
-
if hValores[atributo].is_a?(Numeric)
|
116
|
-
hValores[atributo] = hValores[atributo].to_i if hValores[atributo].modulo(1).zero?
|
117
|
-
hValores[atributo] = (hValores[atributo].to_s.strip rescue '#ERRO AO CONVERTER NUMERO PARA TEXTO')
|
118
|
-
elsif hValores[atributo].is_a?(Date)
|
119
|
-
hValores[atributo] = (I18n.l(hValores[atributo], format: '%d/%m/%Y') rescue hValores[atributo]).to_s
|
120
|
-
elsif hValores[atributo].is_a?(DateTime)
|
121
|
-
hValores[atributo] = (I18n.l(hValores[atributo], format: '%d/%m/%Y %H:%i:%s') rescue hValores[atributo]).to_s
|
122
|
-
else
|
123
|
-
#PARA QUALQUER OUTRO VALOR, FORÇA CONVERTER PARA STRING
|
124
|
-
hValores[atributo] = (hValores[atributo].to_s.strip rescue '')
|
125
|
-
end
|
126
|
-
else
|
127
|
-
hValores[atributo] = ''
|
128
|
-
end
|
129
|
-
end
|
130
|
-
OpenStruct.new(hValores)
|
131
|
-
end
|
132
|
-
|
133
|
-
def array_blank?(array)
|
134
|
-
array.all? {|i|i.nil? or i==''}
|
135
|
-
end
|
136
|
-
|
137
|
-
end
|
138
|
-
end
|