active_report 5.2.1 → 5.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.reek +3 -0
- data/.rubocop.yml +2 -0
- data/lib/active_report/array.rb +20 -32
- data/lib/active_report/base.rb +52 -33
- data/lib/active_report/configuration.rb +1 -1
- data/lib/active_report/hash.rb +25 -41
- data/lib/active_report/record.rb +41 -47
- data/lib/active_report/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f93cb814920fb21c597c30929a0aeaa42b12e8d55bf8d6cd279fc19feeb70d5a
|
4
|
+
data.tar.gz: cfaf4b8f1766e6d0d3e29322758f45228c60593acce062197b56e4aa5e15b456
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d084d1a9d69806666acb79ce1346f6136684da0bb70bf23e2cf092dc3fe354acf78736073fbfcc009aabed24696a23ed597849b7f4e7443195a67f0c56b19fb
|
7
|
+
data.tar.gz: e99b0c98944ec3d34aa2c040483e943306b1ef9b227ed5c73773c6cfd3d3f6617ca0366e82cd067df5ee0c96926292f76c190fda39cef9dc6420247a6a1b1c07
|
data/.reek
CHANGED
data/.rubocop.yml
CHANGED
data/lib/active_report/array.rb
CHANGED
@@ -2,43 +2,17 @@
|
|
2
2
|
|
3
3
|
class ActiveReport::Array < ActiveReport::Base
|
4
4
|
|
5
|
-
def initialize(datum, headers: nil, options: {}, stream: false)
|
6
|
-
@datum = datum
|
7
|
-
@headers = headers
|
8
|
-
@options = csv_options.merge(options)
|
9
|
-
@stream = stream
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.export(datum, headers: nil, options: {}, stream: false)
|
13
|
-
klass = new(datum, headers: headers, options: options, stream: stream)
|
14
|
-
klass.export
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.import(datum, headers: nil, options: {})
|
18
|
-
klass = new(datum, headers: headers, options: options)
|
19
|
-
klass.import
|
20
|
-
end
|
21
|
-
|
22
5
|
def export
|
23
|
-
@
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
csv << CSV.generate_line(@headers) unless @headers.nil?
|
28
|
-
@datum.each { |row| csv << CSV.generate_line(row) }
|
29
|
-
end
|
30
|
-
else
|
31
|
-
CSV.generate(@options) do |csv|
|
32
|
-
csv << @headers unless @headers.nil?
|
33
|
-
@datum.each { |row| csv << row }
|
34
|
-
end
|
35
|
-
end
|
6
|
+
@data = munge_first(@data)
|
7
|
+
@data = @data.unshift(@opts[:headers]) unless @opts[:headers].nil?
|
8
|
+
|
9
|
+
@opts[:stream] ? export_stream : export_csv
|
36
10
|
end
|
37
11
|
|
38
12
|
def import
|
39
|
-
array = merge(@headers)
|
13
|
+
array = merge(@opts[:headers])
|
40
14
|
|
41
|
-
CSV.foreach(@
|
15
|
+
CSV.foreach(@data, @opts[:options]) do |row|
|
42
16
|
row = encode_to_utf8(row) if csv_force_encoding?
|
43
17
|
array.push(row)
|
44
18
|
end
|
@@ -47,4 +21,18 @@ class ActiveReport::Array < ActiveReport::Base
|
|
47
21
|
metatransform(array)
|
48
22
|
end
|
49
23
|
|
24
|
+
private
|
25
|
+
|
26
|
+
def export_csv
|
27
|
+
CSV.generate(@opts[:options]) do |csv|
|
28
|
+
@data.each { |row| csv << row }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def export_stream
|
33
|
+
Enumerator.new do |csv|
|
34
|
+
@data.each { |row| csv << CSV.generate_line(row) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
50
38
|
end
|
data/lib/active_report/base.rb
CHANGED
@@ -4,6 +4,14 @@ class ActiveReport::Base
|
|
4
4
|
|
5
5
|
@@evaluate = false
|
6
6
|
|
7
|
+
def initialize(data, opts = {})
|
8
|
+
@data = data
|
9
|
+
@opts = opts
|
10
|
+
|
11
|
+
%i[except only].each { |key| @opts[key] = munge(@opts[key]) }
|
12
|
+
@opts[:options] ||= csv_options
|
13
|
+
end
|
14
|
+
|
7
15
|
def csv_options
|
8
16
|
ActiveReport.configuration.csv_options
|
9
17
|
end
|
@@ -25,6 +33,16 @@ class ActiveReport::Base
|
|
25
33
|
self
|
26
34
|
end
|
27
35
|
|
36
|
+
def self.export(data, opts = {})
|
37
|
+
klass = new(data, opts)
|
38
|
+
klass.export
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.import(data, opts = {})
|
42
|
+
klass = new(data, opts)
|
43
|
+
klass.import
|
44
|
+
end
|
45
|
+
|
28
46
|
private
|
29
47
|
|
30
48
|
def encode_to_utf8(line)
|
@@ -43,11 +61,12 @@ class ActiveReport::Base
|
|
43
61
|
end
|
44
62
|
|
45
63
|
def filter(object)
|
46
|
-
if @only.empty?
|
47
|
-
return if @except.empty?
|
48
|
-
|
64
|
+
if @opts[:only].empty?
|
65
|
+
return object if @opts[:except].empty?
|
66
|
+
|
67
|
+
object.delete_if { |key, _| @opts[:except].include?(key) }
|
49
68
|
else
|
50
|
-
object.keep_if { |key, _| @only.include?(key) }
|
69
|
+
object.keep_if { |key, _| @opts[:only].include?(key) }
|
51
70
|
end
|
52
71
|
end
|
53
72
|
|
@@ -55,6 +74,10 @@ class ActiveReport::Base
|
|
55
74
|
object.to_s.tr('_', ' ').capitalize
|
56
75
|
end
|
57
76
|
|
77
|
+
def humanize_values(data)
|
78
|
+
data.map { |col| humanize(col) }
|
79
|
+
end
|
80
|
+
|
58
81
|
def merge(object)
|
59
82
|
[object].compact
|
60
83
|
end
|
@@ -67,53 +90,49 @@ class ActiveReport::Base
|
|
67
90
|
end
|
68
91
|
# rubocop:enable Security/Eval, Lint/RescueException
|
69
92
|
|
70
|
-
def metaform_array(
|
71
|
-
|
93
|
+
def metaform_array(data)
|
94
|
+
data.map { |val| metaform(val) }
|
72
95
|
end
|
73
96
|
|
74
|
-
def metaform_hash(
|
75
|
-
|
97
|
+
def metaform_hash(data)
|
98
|
+
data.each { |key, val| data[key] = metaform(val) }
|
76
99
|
end
|
77
100
|
|
78
|
-
def metamorph_array(
|
79
|
-
case
|
80
|
-
when 'Array' then
|
81
|
-
when 'Hash' then
|
82
|
-
else metaform_array(
|
101
|
+
def metamorph_array(data)
|
102
|
+
case data.first.class.name
|
103
|
+
when 'Array' then data.map { |arr| metaform_array(arr) }
|
104
|
+
when 'Hash' then data.map { |hsh| metaform_hash(hsh) }
|
105
|
+
else metaform_array(data)
|
83
106
|
end
|
84
107
|
end
|
85
108
|
|
86
|
-
def metamorph(
|
87
|
-
case
|
88
|
-
when 'Array' then metamorph_array(
|
89
|
-
when 'Hash' then metaform_hash(
|
90
|
-
else metaform(
|
109
|
+
def metamorph(data)
|
110
|
+
case data.class.name
|
111
|
+
when 'Array' then metamorph_array(data)
|
112
|
+
when 'Hash' then metaform_hash(data)
|
113
|
+
else metaform(data)
|
91
114
|
end
|
92
115
|
end
|
93
116
|
|
94
|
-
def metatransform(
|
95
|
-
return if
|
96
|
-
evaluate? ? metamorph(
|
117
|
+
def metatransform(data)
|
118
|
+
return if data.empty?
|
119
|
+
evaluate? ? metamorph(data) : data
|
97
120
|
end
|
98
121
|
|
99
|
-
def munge(
|
100
|
-
|
122
|
+
def munge(data)
|
123
|
+
data.is_a?(Array) ? data : merge(data)
|
101
124
|
end
|
102
125
|
|
103
|
-
def munge_first(
|
104
|
-
|
126
|
+
def munge_first(data)
|
127
|
+
data.first.is_a?(Array) ? data : merge(data)
|
105
128
|
end
|
106
129
|
|
107
|
-
def filter_values(
|
108
|
-
|
109
|
-
(filter(datum) || datum).each_value { |val| array << val }
|
110
|
-
array
|
130
|
+
def filter_values(data)
|
131
|
+
filter(data).values
|
111
132
|
end
|
112
133
|
|
113
|
-
def filter_humanize_keys(
|
114
|
-
|
115
|
-
(filter(datum.first) || datum.first).each_key { |key| array << humanize(key) }
|
116
|
-
array
|
134
|
+
def filter_humanize_keys(data)
|
135
|
+
filter(data.first).collect { |key, _| humanize(key) }
|
117
136
|
end
|
118
137
|
|
119
138
|
end
|
@@ -8,7 +8,7 @@ module ActiveReport
|
|
8
8
|
def initialize
|
9
9
|
@csv_force_encoding = true
|
10
10
|
@csv_options = { encoding: 'UTF-8' }
|
11
|
-
@import_adapter = '
|
11
|
+
@import_adapter = 'sqlite3_adapter'
|
12
12
|
@import_options = { validate: false, on_duplicate_key_ignore: true }
|
13
13
|
end
|
14
14
|
|
data/lib/active_report/hash.rb
CHANGED
@@ -2,65 +2,49 @@
|
|
2
2
|
|
3
3
|
class ActiveReport::Hash < ActiveReport::Base
|
4
4
|
|
5
|
-
def initialize(datum, only: nil, except: nil, headers: nil, options: {}, stream: false)
|
6
|
-
@datum = datum
|
7
|
-
@only = munge(only)
|
8
|
-
@except = munge(except)
|
9
|
-
@headers = headers
|
10
|
-
@options = csv_options.merge(options)
|
11
|
-
@stream = stream
|
12
|
-
end
|
13
|
-
|
14
|
-
# rubocop:disable Metrics/LineLength
|
15
|
-
def self.export(datum, only: nil, except: nil, headers: nil, options: {}, stream: false)
|
16
|
-
klass = new(datum, only: only, except: except, headers: headers, options: options, stream: stream)
|
17
|
-
klass.export
|
18
|
-
end
|
19
|
-
# rubocop:enable Metrics/LineLength
|
20
|
-
|
21
|
-
def self.import(datum, only: nil, except: nil, headers: nil, options: {})
|
22
|
-
klass = new(datum, only: only, except: except, headers: headers, options: options)
|
23
|
-
klass.import
|
24
|
-
end
|
25
|
-
|
26
5
|
def export
|
27
|
-
@
|
28
|
-
@headers = (@headers || filter_humanize_keys(@
|
6
|
+
@data = munge(@data)
|
7
|
+
@opts[:headers] = (@opts[:headers] || filter_humanize_keys(@data))
|
29
8
|
|
30
|
-
|
31
|
-
Enumerator.new do |csv|
|
32
|
-
csv << CSV.generate_line(@headers)
|
33
|
-
@data.each { |row| csv << CSV.generate_line(filter_values(row)) }
|
34
|
-
end
|
35
|
-
else
|
36
|
-
CSV.generate(@options) do |csv|
|
37
|
-
csv << @headers
|
38
|
-
@datum.each { |row| csv << filter_values(row) }
|
39
|
-
end
|
40
|
-
end
|
9
|
+
@opts[:stream] ? export_stream : export_csv
|
41
10
|
end
|
42
11
|
|
43
12
|
def import
|
44
13
|
array = []
|
45
|
-
line = 0
|
46
14
|
|
47
|
-
CSV.foreach(@
|
15
|
+
CSV.foreach(@data, @opts[:options]).with_index do |data, i|
|
48
16
|
data = encode_to_utf8(data) if csv_force_encoding?
|
49
17
|
|
50
|
-
if @headers.nil? &&
|
51
|
-
@headers = data
|
18
|
+
if @opts[:headers].nil? && i.zero?
|
19
|
+
@opts[:headers] = data
|
52
20
|
else
|
53
21
|
subdata = {}
|
54
|
-
@headers.each_with_index { |header, idx| subdata[header.to_s] = data[idx] }
|
22
|
+
@opts[:headers].each_with_index { |header, idx| subdata[header.to_s] = data[idx] }
|
55
23
|
filter(subdata)
|
56
24
|
array.push(subdata)
|
57
25
|
end
|
58
|
-
|
59
|
-
line += 1
|
60
26
|
end
|
61
27
|
|
62
28
|
array = array.first if array.size == 1
|
63
29
|
metatransform(array)
|
64
30
|
end
|
65
31
|
|
32
|
+
private
|
33
|
+
|
34
|
+
def export_csv
|
35
|
+
CSV.generate(@opts[:options]) do |csv|
|
36
|
+
csv << @opts[:headers]
|
37
|
+
|
38
|
+
@data.each { |row| csv << filter_values(row) }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def export_stream
|
43
|
+
Enumerator.new do |csv|
|
44
|
+
csv << CSV.generate_line(@opts[:headers])
|
45
|
+
|
46
|
+
@data.each { |row| csv << CSV.generate_line(filter_values(row)) }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
66
50
|
end
|
data/lib/active_report/record.rb
CHANGED
@@ -7,65 +7,37 @@ require 'json'
|
|
7
7
|
|
8
8
|
class ActiveReport::Record < ActiveReport::Base
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def initialize(datum, model: nil, only: nil, except: nil, headers: nil, options: {}, stream: false)
|
14
|
-
@datum = datum
|
15
|
-
@model = model
|
16
|
-
@only = munge(only)
|
17
|
-
@except = munge(except)
|
18
|
-
@headers = headers
|
19
|
-
@options = csv_options.merge(options)
|
20
|
-
@stream = stream
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.export(datum, only: nil, except: nil, headers: nil, options: {}, stream: false)
|
24
|
-
klass = new(datum, only: only, except: except, headers: headers, options: options, stream: stream)
|
25
|
-
klass.export
|
26
|
-
end
|
27
|
-
# rubocop:enable Metrics/LineLength
|
10
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
11
|
+
def export
|
12
|
+
%i[except only].each { |key| @opts[key] = @opts[key].map(&:to_s) }
|
28
13
|
|
29
|
-
|
30
|
-
|
31
|
-
klass.import
|
32
|
-
end
|
14
|
+
if !@data.is_a?(ActiveRecord::Relation) && @data.try(:superclass) == ActiveRecord::Base
|
15
|
+
@opts[:headers] = (@opts[:headers] || humanize_values(@data.column_names))
|
33
16
|
|
34
|
-
|
35
|
-
@datum = if @datum.is_a?(ActiveRecord::Relation)
|
36
|
-
JSON.parse(@datum.to_json).flatten
|
37
|
-
else
|
38
|
-
merge(@datum.attributes)
|
39
|
-
end
|
40
|
-
|
41
|
-
@only.map!(&:to_s)
|
42
|
-
@except.map!(&:to_s)
|
43
|
-
@headers = (@headers || filter_humanize_keys(@datum))
|
44
|
-
|
45
|
-
if @stream == true
|
46
|
-
Enumerator.new do |csv|
|
47
|
-
csv << CSV.generate_line(@headers)
|
48
|
-
@data.each { |row| csv << CSV.generate_line(filter_values(row)) }
|
49
|
-
end
|
17
|
+
@opts[:stream] ? export_stream : export_csv
|
50
18
|
else
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
19
|
+
@data = if @data.is_a?(ActiveRecord::Relation)
|
20
|
+
JSON.parse(@data.to_json).flatten
|
21
|
+
else
|
22
|
+
merge(@data.attributes)
|
23
|
+
end
|
24
|
+
|
25
|
+
ActiveReport::Hash.export(@data, @opts)
|
55
26
|
end
|
56
27
|
end
|
28
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
57
29
|
|
58
30
|
def import
|
59
|
-
if @model.nil? || (@model.superclass != ActiveRecord::Base)
|
31
|
+
if @opts[:model].nil? || (@opts[:model].superclass != ActiveRecord::Base)
|
60
32
|
raise ArgumentError,
|
61
33
|
'Model must be an ActiveRecord::Base object.'
|
62
34
|
end
|
63
35
|
|
64
|
-
@
|
65
|
-
@
|
36
|
+
@data = ActiveReport::Hash.import(@data, headers: @opts[:headers], options: @opts[:options])
|
37
|
+
@data = munge(@data)
|
66
38
|
|
67
39
|
records = []
|
68
|
-
@
|
40
|
+
@data.each do |data|
|
69
41
|
params = {}
|
70
42
|
|
71
43
|
data.each do |key, value|
|
@@ -78,7 +50,29 @@ class ActiveReport::Record < ActiveReport::Base
|
|
78
50
|
records << params
|
79
51
|
end
|
80
52
|
|
81
|
-
@model.import(records, import_options)
|
53
|
+
@opts[:model].import(records, import_options)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def export_csv
|
59
|
+
CSV.generate(@opts[:options]) do |csv|
|
60
|
+
csv << @opts[:headers]
|
61
|
+
|
62
|
+
@data.find_each do |row|
|
63
|
+
csv << filter_values(row.attributes)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def export_stream
|
69
|
+
Enumerator.new do |csv|
|
70
|
+
csv << CSV.generate_line(@opts[:headers])
|
71
|
+
|
72
|
+
@data.find_each do |row|
|
73
|
+
csv << CSV.generate_line(filter_values(row.attributes))
|
74
|
+
end
|
75
|
+
end
|
82
76
|
end
|
83
77
|
|
84
78
|
end
|