active_report 5.2.1 → 5.2.2
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/.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
|