ruby_report 0.0.1
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/CHANGELOG.md +2 -0
- data/LICENSE.txt +21 -0
- data/README.md +145 -0
- data/lib/ruby_report/builder/default_header_builder.rb +25 -0
- data/lib/ruby_report/builder/default_row_builder.rb +11 -0
- data/lib/ruby_report/decorator.rb +12 -0
- data/lib/ruby_report/formatter.rb +24 -0
- data/lib/ruby_report/generator/base.rb +15 -0
- data/lib/ruby_report/generator/csv.rb +31 -0
- data/lib/ruby_report/generator/hash.rb +19 -0
- data/lib/ruby_report/generator/xlsx.rb +96 -0
- data/lib/ruby_report/report.rb +137 -0
- data/lib/ruby_report/version.rb +5 -0
- data/lib/ruby_report.rb +15 -0
- metadata +137 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6fe86c76ce5314abc47fa276b0fa779c235a76d5cfb2ec9697eb40c69d1585b2
|
4
|
+
data.tar.gz: 0a89259818e654808d7ee0de1a579fd2b3c30e2a347b75a8a041b1a1f92beb8f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 570979045b5f739cc43b845b312311955d517e19a988e1ac1f92ddc93fe91d75aab7400120b7d2143b6cd9e5af403ff37ebdb66df9fc97b636b2064b836cb0cb
|
7
|
+
data.tar.gz: a7025a83548a80f90169c56cf0b2a4d5a903ad6611e5adc68749708618171910222bf5a96b27fc76de5a530c3f04ed747799ed2102b710993fa7cb60af31b238
|
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) Alexandr Zavgorodnev
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
# Ruby Report
|
2
|
+
A simple report generator
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
Add this line to your application's `Gemfile`:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
gem "ruby_report"
|
9
|
+
gem "caxlsx" # optional: for generate xlsx
|
10
|
+
```
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
```sh
|
15
|
+
bundle install
|
16
|
+
```
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
Create class
|
21
|
+
```ruby
|
22
|
+
class UserReport < RubyReport::Report
|
23
|
+
columns :name, :age, :role, :created_at
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
Initialize object with data
|
28
|
+
```ruby
|
29
|
+
# data is ActiveRecords or array of objects
|
30
|
+
report = UserReport.new(data: User.all)
|
31
|
+
```
|
32
|
+
|
33
|
+
Generate report
|
34
|
+
```ruby
|
35
|
+
# Hash
|
36
|
+
report.to_h # {header: ["Name", "Age", "Role"], rows: [["Sasha", 18, "Student"]]}
|
37
|
+
|
38
|
+
# CSV
|
39
|
+
report.to_csv # IOString
|
40
|
+
|
41
|
+
# XLSX
|
42
|
+
report.to_xlsx(worksheet_name: "Worksheet") # IOString
|
43
|
+
```
|
44
|
+
|
45
|
+
## Details
|
46
|
+
Get header
|
47
|
+
```ruby
|
48
|
+
report.header # ["Name", "Age", "Role"]
|
49
|
+
```
|
50
|
+
|
51
|
+
Default translates for header get from i18n
|
52
|
+
```ruby
|
53
|
+
I18n.t("ruby_reports.#{report.class.name.underscore}.headers.#{key}")
|
54
|
+
```
|
55
|
+
|
56
|
+
Determine custom header
|
57
|
+
```ruby
|
58
|
+
UserReport.new(data: data, header_builder: ->(key, _report) { "Custom #{key}" })
|
59
|
+
```
|
60
|
+
|
61
|
+
Get rows
|
62
|
+
```ruby
|
63
|
+
report.rows # [["Sasha", 18, "Student"], ["Jack", 30, "Worker"]]
|
64
|
+
```
|
65
|
+
|
66
|
+
Select columns
|
67
|
+
```ruby
|
68
|
+
report = UserReport.new(data: data, columns: [:name, :age])
|
69
|
+
report.headers #["Name", "Age"]
|
70
|
+
report.rows #[["Sasha", 18], ["Jack", 30]]
|
71
|
+
```
|
72
|
+
|
73
|
+
Custom row
|
74
|
+
```ruby
|
75
|
+
UserReport.new(data: data, row_resolver: ->(row) { row.user })
|
76
|
+
```
|
77
|
+
|
78
|
+
Custom row builder
|
79
|
+
```ruby
|
80
|
+
UserReport.new(data: data, row_builder: ->(_row, _key, _report) { "" })
|
81
|
+
```
|
82
|
+
|
83
|
+
Decorators
|
84
|
+
```ruby
|
85
|
+
class UserDecorator < RubyReport::Decorator
|
86
|
+
def role
|
87
|
+
I18n.t("roles.#{object.role}")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class UserReport < RubyReport::Report
|
92
|
+
columns :name, :age, :role, decorators: [UserDecorator]
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
96
|
+
Formatters
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
class TimeFormatter < RubyReport::Formatter
|
100
|
+
def format(value)
|
101
|
+
return value unless [::Time, ActiveSupport::TimeWithZone].include?(value.class)
|
102
|
+
value.utc.to_formatted_s(:report)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class UserReport < RubyReport::Report
|
107
|
+
columns :name, :age, :role, :created_at, formatters: [TimeFormatter]
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
Decorator and Formatter with scope
|
112
|
+
```ruby
|
113
|
+
class UserDecorator < RubyReport::Decorator
|
114
|
+
def role
|
115
|
+
I18n.t("roles.#{object.role}", account_name: scope[:account].name)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
report = UserReport.new(data: users, scope: {account: account})
|
120
|
+
```
|
121
|
+
|
122
|
+
Append/prepend other reports
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
class AccountReport < RubyReport::Report
|
126
|
+
columns :name
|
127
|
+
end
|
128
|
+
|
129
|
+
class AddressReport < RubyReport::Report
|
130
|
+
columns :street
|
131
|
+
end
|
132
|
+
|
133
|
+
user_report.prepend_report(account_report)
|
134
|
+
user_report.add_report(address_report)
|
135
|
+
```
|
136
|
+
|
137
|
+
XLSX with any worksheets
|
138
|
+
```ruby
|
139
|
+
require "ruby_report/generator/xlsx"
|
140
|
+
|
141
|
+
generator = RubyReport::Generator::Xlsx.new
|
142
|
+
generator.add_report(report, worksheet_name: "Worksheet 1")
|
143
|
+
generator.add_report(other_report, worksheet_name: "Worksheet 2")
|
144
|
+
generator.generate # IOString
|
145
|
+
```
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyReport
|
4
|
+
module Builder
|
5
|
+
module DefaultHeaderBuilder
|
6
|
+
def self.call(key, report)
|
7
|
+
if defined?(::I18n)
|
8
|
+
::I18n.t("ruby_report.#{underscore(report.class.name.to_s)}.headers.#{key}")
|
9
|
+
else
|
10
|
+
key.to_s
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def self.underscore(name)
|
17
|
+
word = name.gsub("::", "/")
|
18
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
|
19
|
+
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
20
|
+
word.downcase!
|
21
|
+
word
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyReport
|
4
|
+
class Formatter < SimpleDelegator
|
5
|
+
attr_reader :scope
|
6
|
+
|
7
|
+
def initialize(obj, scope = {})
|
8
|
+
super(obj)
|
9
|
+
@scope = scope
|
10
|
+
end
|
11
|
+
|
12
|
+
def method_missing(method, *args, &block)
|
13
|
+
format(super)
|
14
|
+
end
|
15
|
+
|
16
|
+
def respond_to_missing?(method, include_private)
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def format(value)
|
21
|
+
value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "csv"
|
4
|
+
|
5
|
+
module RubyReport
|
6
|
+
module Generator
|
7
|
+
class Csv < Base
|
8
|
+
def add_report(report, **_opts)
|
9
|
+
@report = report
|
10
|
+
end
|
11
|
+
|
12
|
+
def generate
|
13
|
+
temp_file = ::Tempfile.new
|
14
|
+
|
15
|
+
::CSV.open(temp_file.path, "wb") do |csv|
|
16
|
+
csv << report.header
|
17
|
+
|
18
|
+
report.each_row do |row|
|
19
|
+
csv << row
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
temp_file
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :report
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyReport
|
4
|
+
module Generator
|
5
|
+
class Hash < Base
|
6
|
+
def add_report(report, **_opts)
|
7
|
+
@report = report
|
8
|
+
end
|
9
|
+
|
10
|
+
def generate
|
11
|
+
{header: report.header, rows: report.rows}
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_reader :report
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "caxlsx"
|
4
|
+
|
5
|
+
module RubyReport
|
6
|
+
module Generator
|
7
|
+
class Xlsx < Base
|
8
|
+
WORKSHEET_LETTERS_COUNT = 25
|
9
|
+
ESCAPE_REGEXP = /["~#%&:;<>!=',@{|}\/?*()+\[\]$]/
|
10
|
+
XLSX_XSS_SYMBOLS = %w[+ - = @ {=].freeze
|
11
|
+
|
12
|
+
class Worksheet
|
13
|
+
SIZES = {header_height: 40, item_height: 20}.freeze
|
14
|
+
ALIGNMENT = {vertical: :center, horizontal: :left, wrap_text: true}.freeze
|
15
|
+
COLORS = {tb: "0a9700", white: "ff"}.freeze
|
16
|
+
|
17
|
+
def initialize(workbook, name)
|
18
|
+
@workbook = workbook
|
19
|
+
@worksheet = @workbook.add_worksheet(name: name)
|
20
|
+
@styles = ::OpenStruct.new(
|
21
|
+
item: @workbook.styles.add_style(alignment: ALIGNMENT),
|
22
|
+
header: @workbook.styles.add_style(
|
23
|
+
bg_color: COLORS.fetch(:tb),
|
24
|
+
fg_color: COLORS.fetch(:white),
|
25
|
+
alignment: ALIGNMENT
|
26
|
+
)
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_header(data)
|
31
|
+
worksheet.add_row(
|
32
|
+
data, style: styles.header, height: SIZES.fetch(:header_height)
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
def add_row(data)
|
37
|
+
worksheet.add_row(
|
38
|
+
data, style: styles.item, height: SIZES.fetch(:item_height)
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
attr_reader :workbook, :worksheet, :styles
|
45
|
+
end
|
46
|
+
|
47
|
+
def initialize
|
48
|
+
@package = ::Axlsx::Package.new.tap { |package| package.use_shared_strings = true }
|
49
|
+
@workbook = package.workbook
|
50
|
+
@reports = []
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_report(report, worksheet_name:)
|
54
|
+
reports << {
|
55
|
+
report: report,
|
56
|
+
worksheet: Worksheet.new(workbook, sanitize_worksheet_name(worksheet_name)),
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
def generate
|
61
|
+
reports.each do |report|
|
62
|
+
worksheet = report[:worksheet]
|
63
|
+
report = report[:report]
|
64
|
+
|
65
|
+
worksheet.add_header(report.header)
|
66
|
+
|
67
|
+
report.each_row do |row|
|
68
|
+
next if row.empty?
|
69
|
+
|
70
|
+
worksheet.add_row(sanitize_row(row))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
package.to_stream
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
attr_reader :package, :workbook, :reports
|
80
|
+
|
81
|
+
def sanitize_row(row)
|
82
|
+
row.map do |el|
|
83
|
+
el.is_a?(String) && el.start_with?(*XLSX_XSS_SYMBOLS) ? "'#{el}" : el
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def sanitize_worksheet_name(name)
|
88
|
+
truncate(name.gsub(ESCAPE_REGEXP, ""), WORKSHEET_LETTERS_COUNT)
|
89
|
+
end
|
90
|
+
|
91
|
+
def truncate(string, length)
|
92
|
+
string.length > length ? string[0...length] : string
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyReport
|
4
|
+
class Report
|
5
|
+
class << self
|
6
|
+
attr_reader :columns_set, :decorators, :formatters
|
7
|
+
|
8
|
+
def columns(*keys, decorators: ::RubyReport::Decorator, formatters: ::RubyReport::Formatter)
|
9
|
+
@columns_set = Set.new(keys)
|
10
|
+
@decorators = decorators
|
11
|
+
@formatters = formatters
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(
|
16
|
+
data:, scope: nil, columns: nil,
|
17
|
+
header_builder: ::RubyReport::Builder::DefaultHeaderBuilder,
|
18
|
+
row_builder: ::RubyReport::Builder::DefaultRowBuilder,
|
19
|
+
row_resolver: ->(row) { row }
|
20
|
+
)
|
21
|
+
@data = data
|
22
|
+
@scope = scope
|
23
|
+
@columns =
|
24
|
+
if columns.nil?
|
25
|
+
self.class.columns_set || raise("Columns not defined")
|
26
|
+
else
|
27
|
+
Set.new(columns)
|
28
|
+
end
|
29
|
+
@header_builder = header_builder
|
30
|
+
@row_builder = row_builder
|
31
|
+
@row_resolver = row_resolver
|
32
|
+
@reports = [self]
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_report(report)
|
36
|
+
reports << report
|
37
|
+
end
|
38
|
+
|
39
|
+
def prepend_report(report)
|
40
|
+
reports.unshift(report)
|
41
|
+
end
|
42
|
+
|
43
|
+
def header
|
44
|
+
@header ||= reports.flat_map do |report|
|
45
|
+
if report == self
|
46
|
+
report.build_header
|
47
|
+
else
|
48
|
+
report.header
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def rows
|
54
|
+
@rows ||= each_row.to_a
|
55
|
+
end
|
56
|
+
|
57
|
+
def each_row
|
58
|
+
return enum_for(:each_row) unless block_given?
|
59
|
+
|
60
|
+
method =
|
61
|
+
if data.respond_to?(:find_each)
|
62
|
+
:find_each
|
63
|
+
else
|
64
|
+
:each
|
65
|
+
end
|
66
|
+
|
67
|
+
data.public_send(method) do |row|
|
68
|
+
yield collect_row(row)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_with(generator, **opts)
|
73
|
+
report = generator.new
|
74
|
+
report.add_report(self, **opts)
|
75
|
+
report.generate
|
76
|
+
end
|
77
|
+
|
78
|
+
[:hash, :csv, :xlsx].each do |type|
|
79
|
+
define_method("to_#{type}") do |**opts|
|
80
|
+
require "ruby_report/generator/#{type}"
|
81
|
+
|
82
|
+
to_with(
|
83
|
+
Object.const_get("::RubyReport::Generator::#{type.to_s.capitalize}"),
|
84
|
+
**opts
|
85
|
+
)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
alias_method :to_h, :to_hash
|
90
|
+
|
91
|
+
def build_header
|
92
|
+
columns.map do |key|
|
93
|
+
header_builder.call(key, self)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def build_row(row)
|
98
|
+
current_row = row_resolver.call(row)
|
99
|
+
|
100
|
+
return [] unless current_row
|
101
|
+
|
102
|
+
Array(decorators).each { |decorator| current_row = decorator.new(current_row, scope) }
|
103
|
+
Array(formatters).each { |formatter| current_row = formatter.new(current_row, scope) }
|
104
|
+
|
105
|
+
columns.map do |key|
|
106
|
+
row_builder.call(current_row, key, self)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def collect_row(row)
|
111
|
+
result_row = []
|
112
|
+
|
113
|
+
reports.each do |report|
|
114
|
+
result_row +=
|
115
|
+
if report == self
|
116
|
+
report.build_row(row)
|
117
|
+
else
|
118
|
+
report.collect_row(row)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
result_row
|
123
|
+
end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
attr_reader :data, :scope, :columns, :header_builder, :row_builder, :row_resolver, :reports
|
128
|
+
|
129
|
+
def decorators
|
130
|
+
self.class.decorators
|
131
|
+
end
|
132
|
+
|
133
|
+
def formatters
|
134
|
+
self.class.formatters
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
data/lib/ruby_report.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ruby_report/builder/default_header_builder"
|
4
|
+
require "ruby_report/builder/default_row_builder"
|
5
|
+
|
6
|
+
require "ruby_report/generator/base"
|
7
|
+
|
8
|
+
require "delegate"
|
9
|
+
require "ruby_report/decorator"
|
10
|
+
require "ruby_report/formatter"
|
11
|
+
|
12
|
+
require "ruby_report/report"
|
13
|
+
|
14
|
+
module RubyReport
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby_report
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alexandr Zavgorodnev
|
8
|
+
bindir: bin
|
9
|
+
cert_chain: []
|
10
|
+
date: 2025-04-20 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: bundler
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - ">="
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '1.16'
|
19
|
+
type: :development
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - ">="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '1.16'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rake
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '13.0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '13.0'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: rspec
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '3.0'
|
47
|
+
type: :development
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '3.0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: pry
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 0.14.2
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.14.2
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: caxlsx
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 4.0.0
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 4.0.0
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: creek
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 2.6.3
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 2.6.3
|
96
|
+
description: A simple report generator
|
97
|
+
email: klondaiker@bk.ru
|
98
|
+
executables: []
|
99
|
+
extensions: []
|
100
|
+
extra_rdoc_files: []
|
101
|
+
files:
|
102
|
+
- CHANGELOG.md
|
103
|
+
- LICENSE.txt
|
104
|
+
- README.md
|
105
|
+
- lib/ruby_report.rb
|
106
|
+
- lib/ruby_report/builder/default_header_builder.rb
|
107
|
+
- lib/ruby_report/builder/default_row_builder.rb
|
108
|
+
- lib/ruby_report/decorator.rb
|
109
|
+
- lib/ruby_report/formatter.rb
|
110
|
+
- lib/ruby_report/generator/base.rb
|
111
|
+
- lib/ruby_report/generator/csv.rb
|
112
|
+
- lib/ruby_report/generator/hash.rb
|
113
|
+
- lib/ruby_report/generator/xlsx.rb
|
114
|
+
- lib/ruby_report/report.rb
|
115
|
+
- lib/ruby_report/version.rb
|
116
|
+
homepage: https://github/klondaiker/ruby_report
|
117
|
+
licenses:
|
118
|
+
- MIT
|
119
|
+
metadata: {}
|
120
|
+
rdoc_options: []
|
121
|
+
require_paths:
|
122
|
+
- lib
|
123
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: 2.7.0
|
128
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
requirements: []
|
134
|
+
rubygems_version: 3.6.2
|
135
|
+
specification_version: 4
|
136
|
+
summary: 0.0.0
|
137
|
+
test_files: []
|