acts_as_table 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.
Files changed (34) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +1 -0
  3. data/LICENSE +30 -0
  4. data/README.md +256 -0
  5. data/Rakefile +13 -0
  6. data/app/models/acts_as_table/belongs_to.rb +81 -0
  7. data/app/models/acts_as_table/column_model.rb +89 -0
  8. data/app/models/acts_as_table/foreign_key.rb +299 -0
  9. data/app/models/acts_as_table/foreign_key_map.rb +121 -0
  10. data/app/models/acts_as_table/has_many.rb +90 -0
  11. data/app/models/acts_as_table/has_many_target.rb +40 -0
  12. data/app/models/acts_as_table/lense.rb +131 -0
  13. data/app/models/acts_as_table/primary_key.rb +108 -0
  14. data/app/models/acts_as_table/record.rb +109 -0
  15. data/app/models/acts_as_table/record_error.rb +50 -0
  16. data/app/models/acts_as_table/record_model.rb +194 -0
  17. data/app/models/acts_as_table/row_model.rb +285 -0
  18. data/app/models/acts_as_table/table.rb +41 -0
  19. data/app/models/acts_as_table/value.rb +80 -0
  20. data/app/models/concerns/acts_as_table/record_model_class_methods.rb +554 -0
  21. data/app/models/concerns/acts_as_table/value_provider.rb +223 -0
  22. data/app/models/concerns/acts_as_table/value_provider_association_methods.rb +57 -0
  23. data/config/locales/en.yml +8 -0
  24. data/db/migrate/1_acts_as_table_migration.rb +186 -0
  25. data/lib/acts_as_table.rb +288 -0
  26. data/lib/acts_as_table/adapter.rb +81 -0
  27. data/lib/acts_as_table/engine.rb +14 -0
  28. data/lib/acts_as_table/headers.rb +196 -0
  29. data/lib/acts_as_table/mapper.rb +464 -0
  30. data/lib/acts_as_table/path.rb +157 -0
  31. data/lib/acts_as_table/reader.rb +149 -0
  32. data/lib/acts_as_table/version.rb +4 -0
  33. data/lib/acts_as_table/writer.rb +116 -0
  34. metadata +181 -0
@@ -0,0 +1,157 @@
1
+ module ActsAsTable
2
+ # ActsAsTable path object.
3
+ #
4
+ # @!attribute [r] klass
5
+ # Returns the class for this ActsAsTable path object.
6
+ #
7
+ # @return [Class]
8
+ # @!attribute [r] parent
9
+ # Returns the parent of this ActsAsTable path object or `nil`, if this ActsAsTable path object is the start.
10
+ #
11
+ # @return [ActsAsTable::Path, nil]
12
+ # @!attribute [r] options
13
+ # Returns the options for this ActsAsTable path object.
14
+ #
15
+ # @return [Hash<Symbol, Object>]
16
+ # @!method belongs_to(method_name, **options)
17
+ # Reflect on a `:belongs_to` association using this ActsAsTable path object.
18
+ #
19
+ # @param [#to_s] method_name
20
+ # @param [Hash<Symbol, Object>] options
21
+ # @option options [Object] :data
22
+ # @return [ActsAsTable::Path]
23
+ # @raise [ArgumentError] If the association is invalid.
24
+ # @!method has_one(method_name, **options)
25
+ # Reflect on a `:has_one` association using this ActsAsTable path object.
26
+ #
27
+ # @param [#to_s] method_name
28
+ # @param [Hash<Symbol, Object>] options
29
+ # @option options [Object] :data
30
+ # @return [ActsAsTable::Path]
31
+ # @raise [ArgumentError] If the association is invalid.
32
+ # @!method has_many(method_name, index, **options)
33
+ # Reflect on a `:has_many` association using this ActsAsTable path object.
34
+ #
35
+ # @param [#to_s] method_name
36
+ # @param [Integer] index
37
+ # @param [Hash<Symbol, Object>] options
38
+ # @option options [Object] :data
39
+ # @return [ActsAsTable::Path]
40
+ # @raise [ArgumentError] If the association is invalid.
41
+ # @!method has_and_belongs_to_many(method_name, index, **options)
42
+ # Reflect on a `:has_and_belongs_to_many` association using this ActsAsTable path object.
43
+ #
44
+ # @param [#to_s] method_name
45
+ # @param [Integer] index
46
+ # @param [Hash<Symbol, Object>] options
47
+ # @option options [Object] :data
48
+ # @return [ActsAsTable::Path]
49
+ # @raise [ArgumentError] If the association is invalid.
50
+ class Path
51
+ include ::Enumerable
52
+
53
+ attr_reader :klass, :parent, :options
54
+
55
+ # Returns a new ActsAsTable path object for the given class, parent (optional) and options.
56
+ #
57
+ # @param [Class] klass
58
+ # @param [ActsAsTable::Path, nil] parent
59
+ # @param [Hash<Symbol, Object>] options
60
+ # @option options [#to_s] :macro
61
+ # @option options [#to_s] :method_name
62
+ # @option options [Integer, nil] :index
63
+ # @option options [Object] :data
64
+ # @return [ActsAsTable::Path]
65
+ def initialize(klass, parent = nil, **options)
66
+ options.assert_valid_keys(:data, :index, :macro, :method_name)
67
+
68
+ @klass, @parent, @options = klass, parent, options.dup
69
+ end
70
+
71
+ # Enumerate this ActsAsTable path object, its parent, its grandparent, etc.
72
+ #
73
+ # @yieldparam [ActsAsTable::Path] path
74
+ # @yieldreturn [void]
75
+ # @return [Enumerable<ActsAsTable::Path>]
76
+ def each(&block)
77
+ ::Enumerator.new { |enumerator|
78
+ # @return [ActsAsTable::Path, nil]
79
+ path = self
80
+
81
+ until path.nil?
82
+ enumerator << path
83
+
84
+ # @return [ActsAsTable::Path, nil]
85
+ path = path.parent
86
+ end
87
+ }.each(&block)
88
+ end
89
+
90
+ # Returns the symbolic name for this ActsAsTable path object.
91
+ #
92
+ # @return [Symbol]
93
+ def to_sym
94
+ if self.parent.nil?
95
+ nil
96
+ else
97
+ self.inject([]) { |acc, path|
98
+ acc << path.options.values_at(:method_name, :index)
99
+ acc
100
+ }.reverse.flatten(1).compact.collect(&:to_s).join('_').to_sym
101
+ end
102
+ end
103
+
104
+ # Terminates this ActsAsTable path object and returns its symbolic name.
105
+ #
106
+ # @param [#to_s] method_name
107
+ # @return [Symbol]
108
+ def attribute(method_name)
109
+ unless [:"#{method_name}", :"#{method_name}="].all? { |sym| @klass.instance_methods.include?(sym) } || @klass.column_names.include?(method_name.to_s)
110
+ raise ::ArgumentError.new("method_name - #{method_name.inspect} is invalid")
111
+ end
112
+
113
+ self.inject([[method_name]]) { |acc, path|
114
+ acc << path.options.values_at(:method_name, :index)
115
+ acc
116
+ }.reverse.flatten(1).compact.collect(&:to_s).join('_').to_sym
117
+ end
118
+
119
+ %i(belongs_to has_one).each do |macro|
120
+ define_method(macro) do |method_name, **options|
121
+ options.assert_valid_keys(:data)
122
+
123
+ # @return [ActiveRecord::Reflection::MacroReflection]
124
+ reflection = @klass.reflect_on_association(method_name)
125
+
126
+ if reflection.nil? || (reflection.macro != macro)
127
+ raise ::ArgumentError.new("method_name - #{method_name.inspect} is invalid")
128
+ end
129
+
130
+ self.class.new(reflection.klass, self, **options.merge({
131
+ macro: macro,
132
+ method_name: method_name,
133
+ index: nil,
134
+ }))
135
+ end
136
+ end
137
+
138
+ %i(has_many has_and_belongs_to_many).each do |macro|
139
+ define_method(macro) do |method_name, index, **options|
140
+ options.assert_valid_keys(:data)
141
+
142
+ # @return [ActiveRecord::Reflection::MacroReflection]
143
+ reflection = @klass.reflect_on_association(method_name)
144
+
145
+ if reflection.nil? || (reflection.macro != macro)
146
+ raise ::ArgumentError.new("method_name - #{method_name.inspect} is invalid")
147
+ end
148
+
149
+ self.class.new(reflection.klass, self, **options.merge({
150
+ macro: macro,
151
+ method_name: method_name,
152
+ index: index,
153
+ }))
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,149 @@
1
+ module ActsAsTable
2
+ # ActsAsTable reader object.
3
+ #
4
+ # @!attribute [r] row_model
5
+ # Returns the ActsAsTable row model for this ActsAsTable reader object.
6
+ #
7
+ # @return [ActsAsTable::RowModel]
8
+ # @!attribute [r] input
9
+ # Returns the input stream for this ActsAsTable reader object.
10
+ #
11
+ # @return [IO]
12
+ # @!attribute [r] options
13
+ # Returns the options for this ActsAsTable reader object.
14
+ #
15
+ # @return [Hash<Symbol, Object>]
16
+ class Reader
17
+ # Returns a new ActsAsTable reader object based on a symbolic name using the given arguments.
18
+ #
19
+ # @param [Symbol] format
20
+ # @param [Array<Object>] args
21
+ # @yieldparam [ActsAsTable::Reader] reader
22
+ # @yieldreturn [void]
23
+ # @return [ActsAsTable::Reader]
24
+ # @raise [ArgumentError] If the given symbolic name is invalid.
25
+ def self.for(format, *args, &block)
26
+ ActsAsTable.for(format).reader(*args, &block)
27
+ end
28
+
29
+ attr_reader :row_model, :input, :options
30
+
31
+ # Returns a new ActsAsTable reader object using the given ActsAsTable row model, input stream and options.
32
+ #
33
+ # @param [ActsAsTable::RowModel] row_model
34
+ # @param [IO] input
35
+ # @param [Hash<Symbol, Object>] options
36
+ # @yieldparam [ActsAsTable::Reader] reader
37
+ # @yieldreturn [void]
38
+ # @return [ActsAsTable::Reader]
39
+ def initialize(row_model, input = $stdin, **options, &block)
40
+ @row_model, @input, @options = row_model, input, options.dup
41
+
42
+ if block_given?
43
+ case block.arity
44
+ when 1 then block.call(self)
45
+ else self.instance_eval(&block)
46
+ end
47
+ end
48
+ end
49
+
50
+ # Delegates to the input stream for this ActsAsTable reader object.
51
+ #
52
+ # @param [String] method_name
53
+ # @param [Array<Object>] args
54
+ # @yield [*args, &block]
55
+ # @yieldreturn [Object]
56
+ # @return [Object]
57
+ # @raise [NoMethodError]
58
+ def method_missing(method_name, *args, &block)
59
+ @input.respond_to?(method_name, false) ? @input.send(method_name, *args, &block) : super(method_name, *args, &block)
60
+ end
61
+
62
+ # Delegates to the input stream for this ActsAsTable reader object.
63
+ #
64
+ # @param [String] method_name
65
+ # @param [Boolean] include_all
66
+ # @return [Boolean]
67
+ def respond_to?(method_name, include_all = false)
68
+ @input.respond_to?(method_name, false) || super(method_name, include_all)
69
+ end
70
+
71
+ # Returns a pair, where the first element is the headers and the second element is a flag that indicates if input stream is at end of file.
72
+ #
73
+ # @return [Array<Object>]
74
+ # @raise [ArgumentError] If the headers do not match the ActsAsTable row model for this ActsAsTable reader object.
75
+ def read_headers
76
+ # @return [ActsAsTable::Headers::Array]
77
+ headers = @row_model.to_headers
78
+
79
+ # @return [Boolean]
80
+ eof = false
81
+
82
+ # @return [Array<Array<String>, nil>]
83
+ rows = ::Array.new(headers.size) { |index|
84
+ row, eof = *self.read_row
85
+
86
+ unless row.nil?
87
+ row += ::Array.new(headers[index].size - row.size) { nil }
88
+ end
89
+
90
+ row
91
+ }
92
+
93
+ if rows.any?(&:nil?)
94
+ raise ::ArgumentError.new("#{self.class}#read_headers - must exist")
95
+ end
96
+
97
+ unless [headers, rows].transpose.all? { |pair| pair[0] == pair[1] }
98
+ raise ::ArgumentError.new("#{self.class}#read_headers - invalid")
99
+ end
100
+
101
+ [rows, eof]
102
+ end
103
+
104
+ # Returns a pair, where the first element is the next row or +nil+ if input stream is at end of file and the second element indicates if input stream is at end of file.
105
+ #
106
+ # @return [Object]
107
+ def read_row
108
+ raise ::NotImplementedError.new("#{self.class}#read_row")
109
+ end
110
+
111
+ # Enumerates the rows in the input stream.
112
+ #
113
+ # @yieldparam [Array<String, nil>, nil] row
114
+ # @yieldreturn [void]
115
+ # @return [Enumerable<Array<String, nil>, nil>]
116
+ # @raise [ArgumentError] If the headers do not match the ActsAsTable row model for this ActsAsTable reader object.
117
+ def each_row(&block)
118
+ ::Enumerator.new { |enumerator|
119
+ headers, eof = *self.read_headers
120
+
121
+ until eof
122
+ row, eof = *self.read_row
123
+
124
+ unless eof
125
+ enumerator << row
126
+ end
127
+ end
128
+ }.each(&block)
129
+ end
130
+
131
+ # Returns a new ActsAsTable table object by reading all rows in the input stream.
132
+ #
133
+ # @return [ActsAsTable::Table]
134
+ # @raise [ArgumentError] If the name of a class for a given record does not match the class name for the corresponding ActsAsTable record model.
135
+ def read_table
136
+ ActsAsTable::Table.new do |table|
137
+ table.row_model = @row_model
138
+
139
+ self.each_row do |row|
140
+ records = table.from_row(row)
141
+
142
+ records.each do |record|
143
+ record.position = self.lineno
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,4 @@
1
+ module ActsAsTable
2
+ # @return [String]
3
+ VERSION = '0.0.1'
4
+ end
@@ -0,0 +1,116 @@
1
+ module ActsAsTable
2
+ # ActsAsTable writer object.
3
+ #
4
+ # @!attribute [r] row_model
5
+ # Returns the ActsAsTable row model for this ActsAsTable reader object.
6
+ #
7
+ # @return [ActsAsTable::RowModel]
8
+ # @!attribute [r] output
9
+ # Returns the output stream for this ActsAsTable reader object.
10
+ #
11
+ # @return [IO]
12
+ # @!attribute [r] options
13
+ # Returns the options for this ActsAsTable reader object.
14
+ #
15
+ # @return [Hash<Symbol, Object>]
16
+ class Writer
17
+ # Returns a new ActsAsTable writer object based on a symbolic name using the given arguments.
18
+ #
19
+ # @param [Symbol] format
20
+ # @param [Array<Object>] args
21
+ # @yieldparam [ActsAsTable::Writer] writer
22
+ # @yieldreturn [void]
23
+ # @return [ActsAsTable::Writer]
24
+ # @raise [ArgumentError] If the given symbolic name is invalid.
25
+ def self.for(format, *args, &block)
26
+ ActsAsTable.for(format).writer(*args, &block)
27
+ end
28
+
29
+ attr_reader :row_model, :output, :options
30
+
31
+ # Returns a new ActsAsTable writer object using the given ActsAsTable row model, output stream and options.
32
+ #
33
+ # @param [ActsAsTable::RowModel] row_model
34
+ # @param [IO] output
35
+ # @param [Hash<Symbol, Object>] options
36
+ # @yieldparam [ActsAsTable::Writer] writer
37
+ # @yieldreturn [void]
38
+ # @return [ActsAsTable::Writer]
39
+ def initialize(row_model, output = $stdout, **options, &block)
40
+ @row_model, @output, @options = row_model, output, options.dup
41
+
42
+ if block_given?
43
+ self.write_prologue
44
+
45
+ case block.arity
46
+ when 1 then block.call(self)
47
+ else self.instance_eval(&block)
48
+ end
49
+
50
+ self.write_epilogue
51
+ end
52
+ end
53
+
54
+ # Delegates to the output stream for this ActsAsTable writer object.
55
+ #
56
+ # @param [String] method_name
57
+ # @param [Array<Object>] args
58
+ # @yield [*args, &block]
59
+ # @yieldreturn [Object]
60
+ # @return [Object]
61
+ # @raise [NoMethodError]
62
+ def method_missing(method_name, *args, &block)
63
+ @output.respond_to?(method_name, false) ? @output.send(method_name, *args, &block) : super(method_name, *args, &block)
64
+ end
65
+
66
+ # Delegates to the output stream for this ActsAsTable writer object.
67
+ #
68
+ # @param [String] method_name
69
+ # @param [Boolean] include_all
70
+ # @return [Boolean]
71
+ def respond_to?(method_name, include_all = false)
72
+ @output.respond_to?(method_name, false) || super(method_name, include_all)
73
+ end
74
+
75
+ # Writes the epilogue to the output stream.
76
+ #
77
+ # @return [ActsAsTable::Writer]
78
+ def write_epilogue
79
+ self
80
+ end
81
+
82
+ # Writes the prologue to the output stream.
83
+ #
84
+ # @return [ActsAsTable::Writer]
85
+ def write_prologue
86
+ # @return [ActsAsTable::Headers::Array]
87
+ headers = @row_model.to_headers
88
+
89
+ headers.each do |header|
90
+ self.write_row(header)
91
+ end
92
+
93
+ self
94
+ end
95
+
96
+ # Writes a record to the output stream.
97
+ #
98
+ # @param [ActiveRecord::Base] base
99
+ # @return [ActsAsTable::Writer]
100
+ # @raise [ArgumentError] If the name of a class for a given record does not match the class name for the corresponding ActsAsTable record model.
101
+ def write_base(base)
102
+ row = @row_model.to_row(base)
103
+
104
+ self.write_row(row)
105
+ end
106
+ alias_method :<<, :write_base
107
+
108
+ # Writes a row to the output stream.
109
+ #
110
+ # @param [Array<String, nil>, nil] row
111
+ # @return [ActsAsTable::Writer]
112
+ def write_row(row)
113
+ raise ::NotImplementedError.new("#{self.class}#write_row")
114
+ end
115
+ end
116
+ end
metadata ADDED
@@ -0,0 +1,181 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts_as_table
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Mark Borkum
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-01-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '6.1'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '4.2'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '6.1'
33
+ - !ruby/object:Gem::Dependency
34
+ name: rake
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: redcarpet
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: yard
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: yard-activerecord
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: yard-activesupport-concern
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: yard-rails
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ description: ActsAsTable is a Ruby on Rails plugin for working with tabular data.
118
+ email:
119
+ - mark.borkum@pnnl.gov
120
+ executables: []
121
+ extensions: []
122
+ extra_rdoc_files: []
123
+ files:
124
+ - ".yardopts"
125
+ - LICENSE
126
+ - README.md
127
+ - Rakefile
128
+ - app/models/acts_as_table/belongs_to.rb
129
+ - app/models/acts_as_table/column_model.rb
130
+ - app/models/acts_as_table/foreign_key.rb
131
+ - app/models/acts_as_table/foreign_key_map.rb
132
+ - app/models/acts_as_table/has_many.rb
133
+ - app/models/acts_as_table/has_many_target.rb
134
+ - app/models/acts_as_table/lense.rb
135
+ - app/models/acts_as_table/primary_key.rb
136
+ - app/models/acts_as_table/record.rb
137
+ - app/models/acts_as_table/record_error.rb
138
+ - app/models/acts_as_table/record_model.rb
139
+ - app/models/acts_as_table/row_model.rb
140
+ - app/models/acts_as_table/table.rb
141
+ - app/models/acts_as_table/value.rb
142
+ - app/models/concerns/acts_as_table/record_model_class_methods.rb
143
+ - app/models/concerns/acts_as_table/value_provider.rb
144
+ - app/models/concerns/acts_as_table/value_provider_association_methods.rb
145
+ - config/locales/en.yml
146
+ - db/migrate/1_acts_as_table_migration.rb
147
+ - lib/acts_as_table.rb
148
+ - lib/acts_as_table/adapter.rb
149
+ - lib/acts_as_table/engine.rb
150
+ - lib/acts_as_table/headers.rb
151
+ - lib/acts_as_table/mapper.rb
152
+ - lib/acts_as_table/path.rb
153
+ - lib/acts_as_table/reader.rb
154
+ - lib/acts_as_table/version.rb
155
+ - lib/acts_as_table/writer.rb
156
+ homepage: https://github.com/pnnl/acts_as_table
157
+ licenses:
158
+ - BSD-3-Clause
159
+ metadata:
160
+ bug_tracker_uri: https://github.com/pnnl/acts_as_table/issues
161
+ source_code_uri: https://github.com/pnnl/acts_as_table
162
+ post_install_message:
163
+ rdoc_options: []
164
+ require_paths:
165
+ - lib
166
+ required_ruby_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ required_rubygems_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ requirements: []
177
+ rubygems_version: 3.0.8
178
+ signing_key:
179
+ specification_version: 4
180
+ summary: A Ruby on Rails plugin for working with tabular data.
181
+ test_files: []