data_list_converter 0.3.9 → 0.4.3
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 +5 -5
- data/README.md +41 -39
- data/changelog.md +8 -0
- data/data_list_converter.gemspec +2 -0
- data/lib/data_list_converter/base.rb +11 -2
- data/lib/data_list_converter/filters/count.rb +1 -0
- data/lib/data_list_converter/helper.rb +38 -6
- data/lib/data_list_converter/types/csv_file.rb +4 -2
- data/lib/data_list_converter/types/marshal.rb +4 -2
- data/lib/data_list_converter/types/multi_sheet.rb +2 -1
- data/lib/data_list_converter/types/records.rb +13 -6
- data/lib/data_list_converter/types/xls_file.rb +11 -6
- data/lib/data_list_converter/types/xlsx_file.rb +10 -8
- data/lib/data_list_converter/version.rb +1 -1
- data/test/base_test.rb +6 -0
- data/test/filters_test.rb +19 -1
- data/test/helper_test.rb +17 -0
- data/test/types_test.rb +31 -0
- metadata +32 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ed694a5c72e52682133a22004d381f3968c3d28db54cbeba194eda7c793e70a9
|
4
|
+
data.tar.gz: 656daa9eb323ffa7b7bddb8e40df86606889f091f56c47069f39e37c9f434741
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad413ccb9e7f0552a39965c69f7924df825eda9933d9acfb83e20455ea03cdd25f34dd8275187190ca868b34fa490c4025c1024820ebf8627345b7e1d6a8d969
|
7
|
+
data.tar.gz: be36997b5d5b37af61e8c5281038ecb8187650ee3d8c506ea852fec5bba8c324a8434e53fe2e2ba729a86deb667376d331aed6194c9cd05286fd636cdbc48219
|
data/README.md
CHANGED
@@ -22,61 +22,73 @@ DataListConverter.convert(:xls_file, :multi_sheet_item_data, {filename: 'result.
|
|
22
22
|
You can also add filter to this process:
|
23
23
|
|
24
24
|
```ruby
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
{count: {size: 4}}],
|
33
|
-
]
|
34
|
-
filters.map do |filter|
|
35
|
-
data = [{name: "james"}] * 10
|
36
|
-
DataListConverter.convert(:item_data, :table_data, data, table_iterator: {filter: filter})
|
37
|
-
end
|
25
|
+
data = (1..20).map{|i| {name: "user-#{i}", age: i+20}}
|
26
|
+
# filter with default options (limit 10)
|
27
|
+
DataListConverter.convert(:item_data, :table_data, data, item_iterator: {filter: :limit})
|
28
|
+
# filter with options
|
29
|
+
DataListConverter.convert(:item_data, :table_data, data, item_iterator: {filter: {limit: {size: 2}}})
|
30
|
+
# multiple filters
|
31
|
+
DataListConverter.convert(:item_data, :table_data, data, item_iterator: {filter: [{limit: {size: 12}}, {count: {size: 4}}]})
|
38
32
|
```
|
39
33
|
|
40
|
-
Please read [the source code](https://github.com/halida/data_list_converter/blob/master/lib/data_list_converter/) for more information,
|
41
|
-
also you can check [test examples](https://github.com/halida/data_list_converter/blob/master/test/).
|
42
|
-
|
43
34
|
## Data Types
|
44
35
|
|
36
|
+
Default data types:
|
37
|
+
|
45
38
|
- **item_data** like: `[{name: 'James', age: '22'}, ...]`, keys should be symbol.
|
46
39
|
- **item_iterator** iterator for item_data, used like: iter.call{|item| out << item}
|
47
40
|
- **table_data** like: `[["name", "age"], ["James", "22"], ["Bob", "33"], ...]`
|
48
41
|
- **table_iterator** iterator for table_data
|
49
|
-
- **csv_file** file in csv format
|
50
|
-
- **xls_file** file in excel format, should install `spreadsheet` gem, and `require 'data_list_converter/types/xls_file'`
|
51
|
-
- **xlsx_file** file in excel xml format, should install `rubyXL` gem, and `require 'data_list_converter/types/xlsx_file'`
|
52
42
|
- **multi_sheet** Contains several data with sheets:
|
53
43
|
- **multi_sheet_table_iterator**: like: `{sheet1: table_iterator1, sheet2: table_iterator2}`
|
54
44
|
- **multi_sheet_table_data**: like: `{sheet1: [['name', 'age'], ...], sheet2: ...}`
|
55
45
|
- **multi_sheet_item_iterator**: like: `{sheet1: item_iterator1, sheet2: item_iterator2}`
|
56
46
|
- **multi_sheet_item_data**: like: `{sheet1: [{name: 'James', age: 32}], sheet2: ...}`
|
57
|
-
- **records** ActiveRecord records, usage: `DataListConverter.convert(:records, :item_data, Users.where(condition), item_iterator: {columns: [:name, :age]})`
|
58
47
|
|
48
|
+
Plugin data types, should required first by `require 'data_list_converter/types/#{type}'`
|
49
|
+
|
50
|
+
- **csv_file** file in csv format
|
51
|
+
- **xls_file** file in excel format, should install `spreadsheet` gem first
|
52
|
+
- **xlsx_file** file in excel xml format, should install `rubyXL` gem first
|
53
|
+
- **records** ActiveRecord records
|
54
|
+
|
55
|
+
Please check [test examples](https://github.com/halida/data_list_converter/blob/master/test/types_test.rb) to see how to use those types.
|
59
56
|
|
60
57
|
## Filters
|
61
58
|
|
62
|
-
**item_iterator/table_iterator limit**: limit item_iterator result counts, usage: `DataListConverter.convert(:item_data, :table_data, item_data, item_iterator: {filter: {limit: {size: 2}}})
|
59
|
+
**item_iterator/table_iterator limit**: limit item_iterator result counts, usage: `DataListConverter.convert(:item_data, :table_data, item_data, item_iterator: {filter: {limit: {size: 2}}})`, default limit size is 10.
|
63
60
|
|
64
|
-
**item_iterator count**: count item_iterator items, usage: `DataListConverter.convert(:xls_file, :item_data, {filename: 'result.xls'}, item_iterator: {filter: {count: {size: 10}}})`, it will print current item counts every `size
|
61
|
+
**item_iterator count**: count item_iterator items, usage: `DataListConverter.convert(:xls_file, :item_data, {filename: 'result.xls'}, item_iterator: {filter: {count: {size: 10}}})`, it will print current item counts every `size`, please [see here](https://github.com/halida/data_list_converter/blob/master/lib/data_list_converter/filters/count.rb) for more options.
|
65
62
|
|
66
|
-
Please
|
63
|
+
Please see [test examples](https://github.com/halida/data_list_converter/blob/master/test/filters_test.rb) to learn how to use filter.
|
64
|
+
|
65
|
+
## helpers
|
66
|
+
|
67
|
+
- **types**: Get current valid types.
|
68
|
+
- **routes**: Get current valid routes.
|
69
|
+
- **file_types**: Get current file types, which is the types has `_file` suffix.
|
70
|
+
- **get_file_format**: Get file type by filename, which compare file extension with `file_types`. `DataListConverter.get_file_format('xxx.xls') == :xls_file`
|
71
|
+
- **save_to_file**: Save data to file, it will use `get_file_format` to find proper file format. `DataListConverter.save_to_file(filename, data, data_format=:item_data)`
|
72
|
+
- **load_from_file**: Get data from file, it will use `get_file_format` to find proper file format. `DataListConverter.load_from_file(filename, data_format=:item_data)`
|
73
|
+
- **unify_item_data_keys**: Sometimes in the `item_data` list, each data keys don't exactly same, so use this function to fix it, example: `DataListConverter.unify_item_data_keys([{a: 12}, {b: 11}]) == [{a: 12, b: nil}, {a: nil, b: 11}]`.
|
74
|
+
- **flatten**: Flatten multi level item_data list into one level, example: `DataListConverter.flatten({a: {b: 12}, c: {d: {e: 11}}}) == {:"a:b"=>12, :"c:d:e"=>11}`, can change seperator: `DataListConverter.flatten(data, '_')`, set max level: `DataListConverter.flatten(data, '_', 2)`
|
67
75
|
|
68
76
|
## Extend
|
69
77
|
|
70
78
|
You can add your own data types and filters, example:
|
71
79
|
|
72
80
|
```ruby
|
73
|
-
DataListConverter.register_converter(:records, :item_iterator) do |
|
74
|
-
|
81
|
+
DataListConverter.register_converter(:records, :item_iterator) do |input, options|
|
82
|
+
query = self.parameter(input, :query, :input)
|
83
|
+
columns = self.parameter(input, :columns, :input)
|
84
|
+
display = input[:display] || columns
|
85
|
+
|
75
86
|
lambda { |&block|
|
76
|
-
|
77
|
-
item =
|
78
|
-
|
79
|
-
|
87
|
+
query.pluck(*columns).each do |data|
|
88
|
+
item = {}
|
89
|
+
data.each_with_index do |d, i|
|
90
|
+
item[display[i]] = d
|
91
|
+
end
|
80
92
|
block.call(item)
|
81
93
|
end
|
82
94
|
}
|
@@ -94,13 +106,3 @@ DataListConverter.register_filter(:item_iterator, :limit) do |proc, options|
|
|
94
106
|
}
|
95
107
|
end
|
96
108
|
```
|
97
|
-
|
98
|
-
|
99
|
-
## Todo
|
100
|
-
|
101
|
-
- check type exists
|
102
|
-
- register can bind method again
|
103
|
-
- better API
|
104
|
-
- better error message
|
105
|
-
- load file/save file with auto format by extname
|
106
|
-
- report error when cannot find type
|
data/changelog.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## 0.4
|
2
|
+
|
3
|
+
Add parameter check, type check, change record type API.
|
4
|
+
|
5
|
+
- 0.4.1 add max_level to flatten helper
|
6
|
+
- 0.4.2 fix value cannot save if value is symbol
|
7
|
+
|
1
8
|
## 0.3
|
2
9
|
|
3
10
|
Refactor.
|
@@ -8,6 +15,7 @@ Refactor.
|
|
8
15
|
- 0.3.7 add marshal_file type, and load_from_file, save_to_file helper
|
9
16
|
- 0.3.8 add raw type
|
10
17
|
- 0.3.9 add unify_item_data_keys helper
|
18
|
+
- 0.3.10 add flatten
|
11
19
|
|
12
20
|
## 0.2
|
13
21
|
|
data/data_list_converter.gemspec
CHANGED
@@ -17,6 +17,8 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.add_development_dependency 'spreadsheet', '~> 1.0'
|
18
18
|
s.add_development_dependency 'rubyXL', '~> 3.3'
|
19
19
|
s.add_development_dependency 'pry', '~> 0.10.1'
|
20
|
+
s.add_development_dependency 'sqlite3', '~> 1.3'
|
21
|
+
s.add_development_dependency 'activerecord', '~> 4.2'
|
20
22
|
|
21
23
|
s.files = `git ls-files`.split("\n")
|
22
24
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -21,6 +21,7 @@ class DataListConverter
|
|
21
21
|
puts "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}\t#{msg}"
|
22
22
|
end
|
23
23
|
|
24
|
+
# register_converter(:item_data, :item_iterator){ |data, options| ... }
|
24
25
|
def register_converter(from_type, to_type, &block)
|
25
26
|
@route_map = nil # clear cache
|
26
27
|
CONVERTERS[[from_type, to_type]] = block
|
@@ -44,7 +45,7 @@ class DataListConverter
|
|
44
45
|
def convert(from_type, to_type, from_value, options={})
|
45
46
|
methods = []
|
46
47
|
add_filter = lambda { |type|
|
47
|
-
filters = (options[type] || {})
|
48
|
+
filters = (options[type] || {})[:filter]
|
48
49
|
return unless filters
|
49
50
|
methods += normalize_filters(type, filters)
|
50
51
|
}
|
@@ -57,6 +58,7 @@ class DataListConverter
|
|
57
58
|
from_type, to_type = route[i], route[i+1]
|
58
59
|
method = CONVERTERS[[from_type, to_type]]
|
59
60
|
raise "cannot find converter #{from_type} -> #{to_type}" unless method
|
61
|
+
self.log "#{from_type} -> #{to_type} options: #{options[to_type]}"
|
60
62
|
methods.push([method, options[to_type] || {}])
|
61
63
|
add_filter.call(to_type)
|
62
64
|
end
|
@@ -91,7 +93,11 @@ class DataListConverter
|
|
91
93
|
# If we want to convert between types, like: convert item_data into csv_file,
|
92
94
|
# we need find all the intermidate data type, like: [:item_data, :item_iterator, :table_iterator, :csv_file]
|
93
95
|
def find_route(from_type, to_type)
|
96
|
+
[from_type, to_type].each do |type|
|
97
|
+
raise Exception, "cannot find type: #{type}" unless self.types.include?(type)
|
98
|
+
end
|
94
99
|
raise Exception, "from_type should not equal to to_type: #{from_type}" if from_type == to_type
|
100
|
+
|
95
101
|
# map wide search
|
96
102
|
checked = Set.new
|
97
103
|
checking = Set.new([from_type])
|
@@ -124,7 +130,10 @@ class DataListConverter
|
|
124
130
|
checking += Set.new(next_nodes) - checked
|
125
131
|
end
|
126
132
|
end
|
127
|
-
|
133
|
+
|
134
|
+
log = ["Route not found: #{from_type} -> #{to_type}", "Current routes:"]
|
135
|
+
log += self.routes.map{|from, to| "#{from} -> #{to}"}
|
136
|
+
raise Exception, log.join("\n")
|
128
137
|
end
|
129
138
|
|
130
139
|
# convert adjacency list into quick lookup hash
|
@@ -1,14 +1,14 @@
|
|
1
1
|
class DataListConverter
|
2
|
-
def self.save_to_file(filename, data, data_format=:item_data)
|
2
|
+
def self.save_to_file(filename, data, data_format=:item_data, options={})
|
3
3
|
file_format = self.get_file_format(filename)
|
4
|
-
|
5
|
-
|
4
|
+
options[file_format] = {filename: filename}
|
5
|
+
DataListConverter.convert(data_format, file_format, data, options)
|
6
6
|
end
|
7
7
|
|
8
|
-
def self.load_from_file(filename, data_format=:item_data)
|
8
|
+
def self.load_from_file(filename, data_format=:item_data, options={})
|
9
9
|
file_format = self.get_file_format(filename)
|
10
|
-
|
11
|
-
|
10
|
+
options[:filename] = filename
|
11
|
+
DataListConverter.convert(file_format, data_format, options)
|
12
12
|
end
|
13
13
|
|
14
14
|
def self.get_file_format(filename)
|
@@ -23,6 +23,10 @@ class DataListConverter
|
|
23
23
|
CONVERTERS.keys.flatten.uniq.sort
|
24
24
|
end
|
25
25
|
|
26
|
+
def self.routes
|
27
|
+
CONVERTERS.keys
|
28
|
+
end
|
29
|
+
|
26
30
|
def self.file_types
|
27
31
|
matcher = /(.*)_file$/
|
28
32
|
DataListConverter.types.select do |type|
|
@@ -46,4 +50,32 @@ class DataListConverter
|
|
46
50
|
end
|
47
51
|
end
|
48
52
|
end
|
53
|
+
|
54
|
+
# flatten multi level item data into one level, example:
|
55
|
+
# {a: {b: 12}, c: {d: {e: 11}}}
|
56
|
+
# =>
|
57
|
+
# {:"a:b"=>12, :"c:d:e"=>11}
|
58
|
+
def self.flatten(data, sep=':', max_level=nil)
|
59
|
+
out = {}
|
60
|
+
recursive_flatten(out, data, nil, sep, 1, max_level)
|
61
|
+
out
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.recursive_flatten(out, data, header, sep, level, max_level)
|
65
|
+
data.each do |k, v|
|
66
|
+
k = header ? :"#{header}#{sep}#{k}" : k
|
67
|
+
if v.kind_of?(Hash) and (!max_level or level <= max_level)
|
68
|
+
recursive_flatten(out, v, k, sep, level+1, max_level)
|
69
|
+
else
|
70
|
+
out[k] = v
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.parameter(data, key, type)
|
76
|
+
raise Exception, "`#{type}` should be hash, not `#{data.class}`: #{data}" unless data.kind_of?(Hash)
|
77
|
+
raise Exception, "Need `#{key}` for `#{type}`, current: #{data}" if not data.has_key?(key)
|
78
|
+
data.fetch(key)
|
79
|
+
end
|
80
|
+
|
49
81
|
end
|
@@ -3,7 +3,8 @@ require 'csv'
|
|
3
3
|
class DataListConverter
|
4
4
|
self.register_converter(:csv_file, :table_iterator) do |input, options|
|
5
5
|
lambda { |&block|
|
6
|
-
|
6
|
+
filename = self.parameter(input, :filename, :input)
|
7
|
+
CSV.open(filename) do |csv|
|
7
8
|
csv.each do |row|
|
8
9
|
block.call(row)
|
9
10
|
end
|
@@ -12,7 +13,8 @@ class DataListConverter
|
|
12
13
|
end
|
13
14
|
|
14
15
|
self.register_converter(:table_iterator, :csv_file) do |proc, options|
|
15
|
-
|
16
|
+
filename = self.parameter(options, :filename, :csv_file)
|
17
|
+
CSV.open(filename, 'wb', force_quotes: true) do |csv|
|
16
18
|
proc.call do |row|
|
17
19
|
csv << row
|
18
20
|
end
|
@@ -1,13 +1,15 @@
|
|
1
1
|
class DataListConverter
|
2
2
|
|
3
3
|
def self.marshal_file_to_data(input, options=nil)
|
4
|
-
|
4
|
+
filename = self.parameter(input, :filename, :input)
|
5
|
+
File.open(filename) do |f|
|
5
6
|
Marshal.load(f)
|
6
7
|
end
|
7
8
|
end
|
8
9
|
|
9
10
|
def self.marshal_data_to_file(data, options)
|
10
|
-
|
11
|
+
filename = self.parameter(options, :filename, :marshal)
|
12
|
+
File.open(filename, 'w+') do |f|
|
11
13
|
Marshal.dump(data, f)
|
12
14
|
end
|
13
15
|
options[:filename]
|
@@ -19,8 +19,9 @@ class DataListConverter
|
|
19
19
|
:"multi_sheet_#{from_type}",
|
20
20
|
:"multi_sheet_#{to_type}",
|
21
21
|
) do |data, options|
|
22
|
+
self.log("multi_sheet #{from_type} -> #{to_type} with options: #{options}")
|
22
23
|
data.map do |sheet, from_data|
|
23
|
-
to_data = self.convert(from_type, to_type, from_data)
|
24
|
+
to_data = self.convert(from_type, to_type, from_data, options)
|
24
25
|
[sheet, to_data]
|
25
26
|
end.to_h
|
26
27
|
end
|
@@ -1,13 +1,20 @@
|
|
1
1
|
# ActiveRecords
|
2
2
|
class DataListConverter
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
# columns = [:table_column1, :table_column2, ...]
|
5
|
+
# display = [:display_name1, :display_name2, ...]
|
6
|
+
# convert(:records, :item_data, query: query, columns: columns, display: display)
|
7
|
+
self.register_converter(:records, :item_iterator) do |input, options|
|
8
|
+
query = self.parameter(input, :query, :input)
|
9
|
+
columns = self.parameter(input, :columns, :input)
|
10
|
+
display = input[:display] || columns
|
11
|
+
|
6
12
|
lambda { |&block|
|
7
|
-
|
8
|
-
item =
|
9
|
-
|
10
|
-
|
13
|
+
query.pluck(*columns).each do |data|
|
14
|
+
item = {}
|
15
|
+
data.each_with_index do |d, i|
|
16
|
+
item[display[i]] = d
|
17
|
+
end
|
11
18
|
block.call(item)
|
12
19
|
end
|
13
20
|
}
|
@@ -5,7 +5,8 @@ class DataListConverter
|
|
5
5
|
|
6
6
|
self.register_converter(:xls_file, :table_iterator) do |input, options|
|
7
7
|
lambda { |&block|
|
8
|
-
|
8
|
+
filename = self.parameter(input, :filename, :input)
|
9
|
+
book = Spreadsheet.open(filename)
|
9
10
|
sheet = book.worksheet input[:sheet] || 0
|
10
11
|
sheet.each do |row|
|
11
12
|
block.call(row.to_a)
|
@@ -18,11 +19,13 @@ class DataListConverter
|
|
18
19
|
sheet = book.create_worksheet(name: (options[:sheet] || "Sheet1"))
|
19
20
|
i = 0
|
20
21
|
proc.call do |row|
|
22
|
+
row = row.map(&:to_s)
|
21
23
|
sheet.row(i).push *row
|
22
24
|
i += 1
|
23
25
|
end
|
24
|
-
|
25
|
-
|
26
|
+
filename = self.parameter(options, :filename, :xls_file)
|
27
|
+
book.write(filename)
|
28
|
+
filename
|
26
29
|
end
|
27
30
|
|
28
31
|
self.register_converter(:multi_sheet_table_iterator, :xls_file) do |data, options|
|
@@ -31,17 +34,19 @@ class DataListConverter
|
|
31
34
|
sheet = book.create_worksheet(name: name.to_s)
|
32
35
|
i = 0
|
33
36
|
table_iterator.call do |row|
|
37
|
+
row = row.map(&:to_s)
|
34
38
|
sheet.row(i).concat(row)
|
35
39
|
i += 1
|
36
40
|
end
|
37
41
|
end
|
38
|
-
filename = options
|
42
|
+
filename = self.parameter(options, :filename, :xls_file)
|
39
43
|
book.write(filename)
|
40
44
|
filename
|
41
45
|
end
|
42
46
|
|
43
|
-
self.register_converter(:xls_file, :multi_sheet_table_iterator) do |
|
44
|
-
|
47
|
+
self.register_converter(:xls_file, :multi_sheet_table_iterator) do |input, options|
|
48
|
+
filename = self.parameter(input, :filename, :input)
|
49
|
+
book = Spreadsheet.open(filename)
|
45
50
|
book.worksheets.map do |sheet|
|
46
51
|
iterator = lambda { |&block|
|
47
52
|
sheet.each do |row|
|
@@ -5,7 +5,8 @@ class DataListConverter
|
|
5
5
|
|
6
6
|
self.register_converter(:xlsx_file, :table_iterator) do |input, options|
|
7
7
|
lambda { |&block|
|
8
|
-
|
8
|
+
filename = self.parameter(input, :filename, :input)
|
9
|
+
book = RubyXL::Parser.parse(filename)
|
9
10
|
sheet = book.worksheets[input[:sheet] || 0]
|
10
11
|
sheet.each do |row|
|
11
12
|
next unless row
|
@@ -22,11 +23,11 @@ class DataListConverter
|
|
22
23
|
i = 0
|
23
24
|
proc.call do |row|
|
24
25
|
row.each_with_index do |v, j|
|
25
|
-
sheet.add_cell(i, j, v)
|
26
|
+
sheet.add_cell(i, j, v.to_s)
|
26
27
|
end
|
27
28
|
i += 1
|
28
29
|
end
|
29
|
-
filename = options
|
30
|
+
filename = self.parameter(options, :filename, :xlsx_file)
|
30
31
|
book.write(filename)
|
31
32
|
filename
|
32
33
|
end
|
@@ -41,27 +42,28 @@ class DataListConverter
|
|
41
42
|
row.each_with_index do |v, j|
|
42
43
|
if v.kind_of?(Hash)
|
43
44
|
# custom cell format
|
44
|
-
cell = sheet.add_cell(i, j, v[:text])
|
45
|
+
cell = sheet.add_cell(i, j, v[:text].to_s)
|
45
46
|
v.each do |k, v|
|
46
47
|
next if k == :text
|
47
48
|
cell.send(k, v)
|
48
49
|
end
|
49
50
|
cell.change_fill(v[:fill_color]) if v[:fill_color]
|
50
51
|
else
|
51
|
-
cell = sheet.add_cell(i, j, v)
|
52
|
+
cell = sheet.add_cell(i, j, v.to_s)
|
52
53
|
end
|
53
54
|
|
54
55
|
end
|
55
56
|
i += 1
|
56
57
|
end
|
57
58
|
end
|
58
|
-
filename = options
|
59
|
+
filename = self.parameter(options, :filename, :xlsx_file)
|
59
60
|
book.write(filename)
|
60
61
|
filename
|
61
62
|
end
|
62
63
|
|
63
|
-
self.register_converter(:xlsx_file, :multi_sheet_table_iterator) do |
|
64
|
-
|
64
|
+
self.register_converter(:xlsx_file, :multi_sheet_table_iterator) do |input, options|
|
65
|
+
filename = self.parameter(input, :filename, :input)
|
66
|
+
book = RubyXL::Parser.parse(filename)
|
65
67
|
book.worksheets.map do |sheet|
|
66
68
|
iterator = lambda { |&block|
|
67
69
|
sheet.each do |row|
|
data/test/base_test.rb
CHANGED
data/test/filters_test.rb
CHANGED
@@ -26,12 +26,30 @@ describe DataListConverter do
|
|
26
26
|
string = StringIO.new
|
27
27
|
filter = {count: {size: 4000,
|
28
28
|
out: string,
|
29
|
-
msg: "%{percent}
|
29
|
+
msg: "%{percent}%%"}}
|
30
30
|
result = DataListConverter.convert(
|
31
31
|
:item_iterator, :table_data, iter,
|
32
32
|
item_iterator: {filter: filter})
|
33
33
|
string.string.split("\n").must_equal ['total: 10000', '40.0%', '80.0%']
|
34
34
|
end
|
35
35
|
end
|
36
|
+
|
37
|
+
describe :remove_debug do
|
38
|
+
specify do
|
39
|
+
filter = {remove_debug: true}
|
40
|
+
item_data = [{name: "james", debug: "", a: 12}] * 2
|
41
|
+
result = DataListConverter.convert(
|
42
|
+
:item_data, :table_data, item_data,
|
43
|
+
table_iterator: {filter: filter})
|
44
|
+
result.must_equal [["name"], ["james"], ["james"]]
|
45
|
+
|
46
|
+
# check on multi_sheet
|
47
|
+
item_data = {a: [{name: "james", debug: "", a: 12}] * 2, b: [{name: 'cc', debug: "", b: 3}]*3}
|
48
|
+
result = DataListConverter.convert(
|
49
|
+
:multi_sheet_item_data, :multi_sheet_table_data, item_data,
|
50
|
+
multi_sheet_table_iterator: {table_iterator: {filter: {remove_debug: true}}})
|
51
|
+
result.must_equal(a: [["name"], ["james"], ["james"]], b: [["name"], ["cc"], ["cc"], ["cc"]])
|
52
|
+
end
|
53
|
+
end
|
36
54
|
|
37
55
|
end
|
data/test/helper_test.rb
CHANGED
@@ -70,4 +70,21 @@ describe DataListConverter do
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
+
|
74
|
+
describe :flatten do
|
75
|
+
specify do
|
76
|
+
data = {a: {b: 12}, c: {d: {e: 11}}}
|
77
|
+
@c.flatten(data).must_equal({:"a:b"=>12, :"c:d:e"=>11})
|
78
|
+
|
79
|
+
# change sep
|
80
|
+
data = {a: {b: 12}, c: {d: {e: 11}}}
|
81
|
+
@c.flatten(data, '_').must_equal({:"a_b"=>12, :"c_d_e"=>11})
|
82
|
+
|
83
|
+
# set max level
|
84
|
+
data = {a: {b: 12}, c: {d: {e: {f: 11}}}}
|
85
|
+
@c.flatten(data, ':', 1).must_equal({:"a:b"=>12, :"c:d"=>{e: {f: 11}}})
|
86
|
+
data = {a: {b: 12}, c: {d: {e: {f: 11}}}}
|
87
|
+
@c.flatten(data, ':', 2).must_equal({:"a:b"=>12, :"c:d:e"=>{f: 11}})
|
88
|
+
end
|
89
|
+
end
|
73
90
|
end
|
data/test/types_test.rb
CHANGED
@@ -99,5 +99,36 @@ describe DataListConverter do
|
|
99
99
|
end
|
100
100
|
end
|
101
101
|
end
|
102
|
+
|
103
|
+
describe :records do
|
104
|
+
specify do
|
105
|
+
require 'sqlite3'
|
106
|
+
require 'active_record'
|
107
|
+
|
108
|
+
ActiveRecord::Base.establish_connection(
|
109
|
+
adapter: 'sqlite3',
|
110
|
+
database: ':memory:'
|
111
|
+
)
|
112
|
+
|
113
|
+
ActiveRecord::Schema.define do
|
114
|
+
create_table :users, force: true do |t|
|
115
|
+
t.string :name
|
116
|
+
t.integer :age
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class User < ActiveRecord::Base; end
|
121
|
+
(1..10).each{ |i| User.create(name: "user-#{i}", age: i+20) }
|
122
|
+
|
123
|
+
query = User.where("age > 25 and age < 27")
|
124
|
+
columns = [:name, :age]
|
125
|
+
@c.convert(:records, :item_data, query: query, columns: columns).
|
126
|
+
must_equal([{name: "user-6", age: 26}])
|
127
|
+
|
128
|
+
display = [:n, :a]
|
129
|
+
@c.convert(:records, :item_data, query: query, columns: columns, display: display).
|
130
|
+
must_equal([{n: "user-6", a: 26}])
|
131
|
+
end
|
132
|
+
end
|
102
133
|
|
103
134
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: data_list_converter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- linjunhalida
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-08-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -80,6 +80,34 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 0.10.1
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: sqlite3
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.3'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: activerecord
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '4.2'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '4.2'
|
83
111
|
description: Data List Converter is a tool to convert data between different formats.
|
84
112
|
email:
|
85
113
|
- linjunhalida@gmail.com
|
@@ -132,14 +160,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
132
160
|
- !ruby/object:Gem::Version
|
133
161
|
version: '0'
|
134
162
|
requirements: []
|
135
|
-
|
136
|
-
rubygems_version: 2.4.8
|
163
|
+
rubygems_version: 3.0.6
|
137
164
|
signing_key:
|
138
165
|
specification_version: 4
|
139
166
|
summary: convert data between different formats
|
140
|
-
test_files:
|
141
|
-
- test/base_test.rb
|
142
|
-
- test/filters_test.rb
|
143
|
-
- test/helper_test.rb
|
144
|
-
- test/testdata.rb
|
145
|
-
- test/types_test.rb
|
167
|
+
test_files: []
|