lite-report 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1 @@
1
+ theme: jekyll-theme-leap-day
@@ -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__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -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
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ Lite::Report.configure do |config|
4
+ config.csv_options = {}
5
+ config.data_options = {}
6
+ config.import_options = {}
7
+ end
@@ -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