lite-report 1.0.0
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 +7 -0
- data/.DS_Store +0 -0
- data/.fasterer.yml +19 -0
- data/.gitignore +11 -0
- data/.rspec +4 -0
- data/.rubocop.yml +28 -0
- data/.travis.yml +24 -0
- data/CHANGELOG.md +10 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +155 -0
- data/LICENSE.txt +21 -0
- data/README.md +202 -0
- data/Rakefile +8 -0
- data/_config.yml +1 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/generators/lite/report/install_generator.rb +17 -0
- data/lib/generators/lite/report/templates/install.rb +7 -0
- data/lib/lite/report.rb +14 -0
- data/lib/lite/report/array.rb +17 -0
- data/lib/lite/report/base.rb +56 -0
- data/lib/lite/report/configuration.rb +31 -0
- data/lib/lite/report/hash.rb +28 -0
- data/lib/lite/report/helpers/converters.rb +28 -0
- data/lib/lite/report/helpers/encoders.rb +42 -0
- data/lib/lite/report/helpers/filters.rb +56 -0
- data/lib/lite/report/helpers/headers.rb +37 -0
- data/lib/lite/report/helpers/processors.rb +26 -0
- data/lib/lite/report/helpers/records.rb +29 -0
- data/lib/lite/report/helpers/transporters.rb +44 -0
- data/lib/lite/report/record.rb +58 -0
- data/lib/lite/report/version.rb +9 -0
- data/lite-report.gemspec +56 -0
- metadata +286 -0
data/Rakefile
ADDED
data/_config.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
theme: jekyll-theme-leap-day
|
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'lite/report'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators'
|
4
|
+
|
5
|
+
module Lite
|
6
|
+
module Report
|
7
|
+
class InstallGenerator < Rails::Generators::Base
|
8
|
+
|
9
|
+
source_root File.expand_path('../templates', __FILE__)
|
10
|
+
|
11
|
+
def copy_initializer_file
|
12
|
+
copy_file('install.rb', 'config/initializers/lite-report.rb')
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/lite/report.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'csv'
|
4
|
+
require 'lite/report/version'
|
5
|
+
|
6
|
+
%w[converters encoders filters headers processors records transporters].each do |file_name|
|
7
|
+
require "lite/report/helpers/#{file_name}"
|
8
|
+
end
|
9
|
+
|
10
|
+
%w[configuration base array hash record].each do |file_name|
|
11
|
+
require "lite/report/#{file_name}"
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'generators/lite/report/install_generator'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Lite::Report::Array < Lite::Report::Base
|
4
|
+
|
5
|
+
def export
|
6
|
+
generate_or_stream_export!
|
7
|
+
end
|
8
|
+
|
9
|
+
def import
|
10
|
+
CSV.foreach(@data, @csv_options)
|
11
|
+
.with_object([]) do |row, array|
|
12
|
+
row = convert_to_array!(row)
|
13
|
+
array << process_import_row!(row)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Lite::Report::Base
|
4
|
+
|
5
|
+
include Lite::Report::Helpers::Converters
|
6
|
+
include Lite::Report::Helpers::Encoders
|
7
|
+
include Lite::Report::Helpers::Filters
|
8
|
+
include Lite::Report::Helpers::Headers
|
9
|
+
include Lite::Report::Helpers::Processors
|
10
|
+
include Lite::Report::Helpers::Records
|
11
|
+
include Lite::Report::Helpers::Transporters
|
12
|
+
|
13
|
+
def initialize(data, csv_options: {}, data_options: {}, import_options: {})
|
14
|
+
@data = data
|
15
|
+
@csv_options = Lite::Report.configuration.csv_options.merge(csv_options)
|
16
|
+
@data_options = Lite::Report.configuration.data_options.merge(data_options)
|
17
|
+
@import_options = Lite::Report.configuration.import_options.merge(import_options)
|
18
|
+
end
|
19
|
+
|
20
|
+
class << self
|
21
|
+
|
22
|
+
def export(data, csv_options: {}, data_options: {}, import_options: {})
|
23
|
+
klass = new(
|
24
|
+
data,
|
25
|
+
csv_options: csv_options,
|
26
|
+
data_options: data_options,
|
27
|
+
import_options: import_options
|
28
|
+
)
|
29
|
+
|
30
|
+
klass.export
|
31
|
+
end
|
32
|
+
|
33
|
+
def import(data, csv_options: {}, data_options: {}, import_options: {})
|
34
|
+
klass = new(
|
35
|
+
data,
|
36
|
+
csv_options: csv_options,
|
37
|
+
data_options: data_options,
|
38
|
+
import_options: import_options
|
39
|
+
)
|
40
|
+
|
41
|
+
klass.import
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def values!(row)
|
49
|
+
case row.class.name
|
50
|
+
when 'CSV::Row' then row.fields
|
51
|
+
when 'Hash' then row.values
|
52
|
+
else row
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lite
|
4
|
+
module Report
|
5
|
+
|
6
|
+
class Configuration
|
7
|
+
|
8
|
+
attr_accessor :csv_options, :data_options, :import_options
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@csv_options = {}
|
12
|
+
@data_options = {}
|
13
|
+
@import_adapter = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.configuration
|
19
|
+
@configuration ||= Configuration.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.configuration=(config)
|
23
|
+
@configuration = config
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.configure
|
27
|
+
yield(configuration)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Lite::Report::Hash < Lite::Report::Base
|
4
|
+
|
5
|
+
def export
|
6
|
+
assign_headers_to_csv_options!
|
7
|
+
generate_or_stream_export!
|
8
|
+
end
|
9
|
+
|
10
|
+
def import
|
11
|
+
CSV.foreach(@data, @csv_options)
|
12
|
+
.with_object([]) do |row, array|
|
13
|
+
next if header_row?(row)
|
14
|
+
|
15
|
+
row = convert_to_hash!(row)
|
16
|
+
array << process_import_row!(row)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def assign_headers_to_csv_options!
|
23
|
+
return unless write_headers?
|
24
|
+
|
25
|
+
@csv_options[:headers] ||= @data.first.keys
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lite
|
4
|
+
module Report
|
5
|
+
module Helpers
|
6
|
+
module Converters
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def convert_to_array!(row)
|
11
|
+
case row.class.name
|
12
|
+
when 'CSV::Row' then row.fields
|
13
|
+
else row
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def convert_to_hash!(row)
|
18
|
+
case row.class.name
|
19
|
+
when 'Array' then ::Hash[(0..(row.size - 1)).zip(row)]
|
20
|
+
when 'CSV::Row' then row.to_hash
|
21
|
+
else row
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lite
|
4
|
+
module Report
|
5
|
+
module Helpers
|
6
|
+
module Encoders
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def encode(cell)
|
11
|
+
return cell unless cell.is_a?(String)
|
12
|
+
|
13
|
+
cell.tr('"', '').encode!(*@data_options[:encode])
|
14
|
+
end
|
15
|
+
|
16
|
+
def encode?(delete: false)
|
17
|
+
return @data_options.delete(:encode) if delete
|
18
|
+
|
19
|
+
@data_options[:encode]
|
20
|
+
end
|
21
|
+
|
22
|
+
def encode!(row)
|
23
|
+
case row.class.name
|
24
|
+
when 'Hash' then encode_hash!(row)
|
25
|
+
else encode_array!(row)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def encode_array!(row)
|
30
|
+
row.map { |cell| encode(cell) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def encode_hash!(row)
|
34
|
+
row.map.with_object({}) do |(key, val), hash|
|
35
|
+
hash[encode(key)] = encode(val)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lite
|
4
|
+
module Report
|
5
|
+
module Helpers
|
6
|
+
module Filters
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def except?(delete: false)
|
11
|
+
return @data_options.delete(:except) if delete
|
12
|
+
|
13
|
+
@data_options[:except]
|
14
|
+
end
|
15
|
+
|
16
|
+
def filter?(delete: false)
|
17
|
+
only?(delete: delete) || except?(delete: delete)
|
18
|
+
end
|
19
|
+
|
20
|
+
def filter!(row)
|
21
|
+
case row.class.name
|
22
|
+
when 'Array' then filter_array!(row)
|
23
|
+
when 'Hash' then filter_hash!(row)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def filter_array!(row)
|
28
|
+
if only?
|
29
|
+
row.keep_if.with_index { |_, i| @data_options[:only].include?(i) }
|
30
|
+
elsif except?
|
31
|
+
row.delete_if.with_index { |_, i| @data_options[:except].include?(i) }
|
32
|
+
else
|
33
|
+
row
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def filter_hash!(row)
|
38
|
+
if only?
|
39
|
+
row.keep_if { |key, _| @data_options[:only].include?(key) }
|
40
|
+
elsif except?
|
41
|
+
row.keep_if { |key, _| @data_options[:except].include?(key) }
|
42
|
+
else
|
43
|
+
row
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def only?(delete: false)
|
48
|
+
return @data_options.delete(:only) if delete
|
49
|
+
|
50
|
+
@data_options[:only]
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lite
|
4
|
+
module Report
|
5
|
+
module Helpers
|
6
|
+
module Headers
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def header_row?(row)
|
11
|
+
return false unless row.respond_to?(:header_row?)
|
12
|
+
|
13
|
+
row.header_row?
|
14
|
+
end
|
15
|
+
|
16
|
+
def headers?(delete: false)
|
17
|
+
return @csv_options.delete(:headers) if delete
|
18
|
+
|
19
|
+
@csv_options[:headers]
|
20
|
+
end
|
21
|
+
|
22
|
+
def return_headers?(delete: false)
|
23
|
+
return @csv_options.delete(:return_headers) if delete
|
24
|
+
|
25
|
+
@csv_options[:return_headers]
|
26
|
+
end
|
27
|
+
|
28
|
+
def write_headers?(delete: false)
|
29
|
+
return @csv_options.delete(:write_headers) if delete
|
30
|
+
|
31
|
+
@csv_options[:write_headers]
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lite
|
4
|
+
module Report
|
5
|
+
module Helpers
|
6
|
+
module Processors
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def process_export_row!(row)
|
11
|
+
row = filter!(row) if filter?
|
12
|
+
row = values!(row)
|
13
|
+
row = encode!(row) if encode?
|
14
|
+
row
|
15
|
+
end
|
16
|
+
|
17
|
+
def process_import_row!(row)
|
18
|
+
row = filter!(row) if filter?
|
19
|
+
row = encode!(row) if encode?
|
20
|
+
row
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lite
|
4
|
+
module Report
|
5
|
+
module Helpers
|
6
|
+
module Records
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def class_columns(data)
|
11
|
+
return data.klass.column_names if ransack_class?(data)
|
12
|
+
|
13
|
+
data.column_names
|
14
|
+
end
|
15
|
+
|
16
|
+
def klass
|
17
|
+
@data_options[:klass]
|
18
|
+
end
|
19
|
+
|
20
|
+
def ransack_class?(data)
|
21
|
+
return false unless defined?(Ransack)
|
22
|
+
|
23
|
+
data.is_a?(Ransack::Search)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|