table_structure 0.3.20 → 0.3.21
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 +4 -4
- data/CHANGELOG.md +8 -0
- data/Gemfile.lock +1 -1
- data/README.md +53 -52
- data/lib/table_structure.rb +7 -5
- data/lib/table_structure/iterator.rb +97 -12
- data/lib/table_structure/schema.rb +64 -85
- data/lib/table_structure/schema/column_converter.rb +48 -0
- data/lib/table_structure/schema/columns/schema.rb +3 -2
- data/lib/table_structure/schema/{keys_generator.rb → key_converter.rb} +2 -2
- data/lib/table_structure/schema/row_builder.rb +22 -0
- data/lib/table_structure/table.rb +72 -0
- data/lib/table_structure/table/column_converter.rb +46 -0
- data/lib/table_structure/table/context_builder.rb +49 -0
- data/lib/table_structure/table/iterator.rb +13 -15
- data/lib/table_structure/table/row_builder.rb +38 -0
- data/lib/table_structure/version.rb +1 -1
- data/lib/table_structure/writer.rb +7 -33
- metadata +9 -7
- data/lib/table_structure/schema/column_converters.rb +0 -83
- data/lib/table_structure/schema/context_builders.rb +0 -55
- data/lib/table_structure/schema/row_builders.rb +0 -58
- data/lib/table_structure/schema/table.rb +0 -61
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: c8d52660a94da1c1fbcc8a14a8332214c32ba1627a50239ee72f9916e12c8502
         | 
| 4 | 
            +
              data.tar.gz: 2156f6ebaa0ee6fd88dfb282a3c339e20101da8bf33cd250355eff7557915921
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 9e5091c8a9c362a09b563e608cf78b74fddb53526ebd53ef30700f4c975429689c5ab8e27f72918d7c4fbdcd798b7911f20dd70593a313fe59bdb88d5deb8e35
         | 
| 7 | 
            +
              data.tar.gz: 6ae2d481a839d63271009435173250f929009bd2273a59f3aaa974cc14e7612d7cb55258c82c2fe189f304277249d298e0eaaa7d15d1d20b6acc53cee3bb02f9
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,3 +1,11 @@ | |
| 1 | 
            +
            # 0.3.21
         | 
| 2 | 
            +
            Changes:
         | 
| 3 | 
            +
            - Add `TableStructure::Table`
         | 
| 4 | 
            +
              - This provides methods for converting data with the schema.
         | 
| 5 | 
            +
              - Use `TableStructure::Table.new` instead of `TableStructure::Schema#create_table`.
         | 
| 6 | 
            +
            - `TableStructure::Schema`
         | 
| 7 | 
            +
              - `TableStructure::Schema#create_table` has been deprecated. Use `TableStructure::Table.new` instead.
         | 
| 8 | 
            +
             | 
| 1 9 | 
             
            # 0.3.20
         | 
| 2 10 | 
             
            Changes:
         | 
| 3 11 | 
             
            - `TableStructure::Schema`
         | 
    
        data/Gemfile.lock
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -8,6 +8,8 @@ | |
| 8 8 | 
             
              - Converts data with the schema, and outputs table structured data.
         | 
| 9 9 | 
             
            - `TableStructure::Iterator`
         | 
| 10 10 | 
             
              - Converts data with the schema, and enumerates table structured data.
         | 
| 11 | 
            +
            - `TableStructure::Table`
         | 
| 12 | 
            +
              - Provides methods for converting data with the schema.
         | 
| 11 13 |  | 
| 12 14 | 
             
            ## Installation
         | 
| 13 15 |  | 
| @@ -127,7 +129,6 @@ response_body = Enumerator.new do |y| | |
| 127 129 | 
             
              writer.write(items, to: CSV.new(y))
         | 
| 128 130 | 
             
            end
         | 
| 129 131 | 
             
            ```
         | 
| 130 | 
            -
            [Sample with docker](https://github.com/jsmmr/ruby_table_structure_sample)
         | 
| 131 132 |  | 
| 132 133 | 
             
            You can also convert CSV character code:
         | 
| 133 134 | 
             
            ```ruby
         | 
| @@ -147,27 +148,31 @@ end | |
| 147 148 | 
             
            ```
         | 
| 148 149 |  | 
| 149 150 | 
             
            #### TableStructure::Iterator
         | 
| 150 | 
            -
             | 
| 151 | 
            -
            To use this option, define `column(s) | 
| 151 | 
            +
            If you want to convert the item to row as Hash instead of Array, specify `row_type: :hash`.
         | 
| 152 | 
            +
            To use this option, define `:key` on `column(s)`.
         | 
| 152 153 |  | 
| 153 154 | 
             
            Define a schema:
         | 
| 154 155 | 
             
            ```ruby
         | 
| 155 156 | 
             
            class SampleTableSchema
         | 
| 156 157 | 
             
              include TableStructure::Schema
         | 
| 157 158 |  | 
| 158 | 
            -
              # If header is  | 
| 159 | 
            -
              column   | 
| 159 | 
            +
              # If `:header` is set to `false`, `:name` is optional.
         | 
| 160 | 
            +
              column  name: 'ID',
         | 
| 161 | 
            +
                      key: :id,
         | 
| 160 162 | 
             
                      value: ->(row, *) { row[:id] }
         | 
| 161 163 |  | 
| 162 | 
            -
              column   | 
| 164 | 
            +
              column  name: 'Name',
         | 
| 165 | 
            +
                      key: :name,
         | 
| 163 166 | 
             
                      value: ->(row, *) { row[:name] }
         | 
| 164 167 |  | 
| 165 | 
            -
              columns  | 
| 168 | 
            +
              columns name: ['Pet 1', 'Pet 2', 'Pet 3'],
         | 
| 169 | 
            +
                      key: %i[pet1 pet2 pet3],
         | 
| 166 170 | 
             
                      value: ->(row, *) { row[:pets] }
         | 
| 167 171 |  | 
| 168 172 | 
             
              columns ->(table) {
         | 
| 169 173 | 
             
                table[:questions].map do |question|
         | 
| 170 174 | 
             
                  {
         | 
| 175 | 
            +
                    name: question[:id],
         | 
| 171 176 | 
             
                    key: question[:id].downcase.to_sym,
         | 
| 172 177 | 
             
                    value: ->(row, *) { row[:answers][question[:id]] }
         | 
| 173 178 | 
             
                  }
         | 
| @@ -175,7 +180,7 @@ class SampleTableSchema | |
| 175 180 | 
             
              }
         | 
| 176 181 |  | 
| 177 182 | 
             
              ## If the schemas are nested, :key must be unique in parent and child schemas.
         | 
| 178 | 
            -
              ## This can also be avoided by  | 
| 183 | 
            +
              ## This can also be avoided by using :key_prefix or :key_suffix option.
         | 
| 179 184 | 
             
              # columns ->(table) { NestedTableSchema.new(context: table, key_prefix: 'foo_', key_suffix: '_bar') }
         | 
| 180 185 | 
             
            end
         | 
| 181 186 | 
             
            ```
         | 
| @@ -191,7 +196,7 @@ context = { | |
| 191 196 | 
             
            }
         | 
| 192 197 |  | 
| 193 198 | 
             
            schema = SampleTableSchema.new(context: context)
         | 
| 194 | 
            -
            iterator = TableStructure::Iterator.new(schema,  | 
| 199 | 
            +
            iterator = TableStructure::Iterator.new(schema, header: false, row_type: :hash)
         | 
| 195 200 | 
             
            ```
         | 
| 196 201 |  | 
| 197 202 | 
             
            Enumerate the items converted by the schema:
         | 
| @@ -225,6 +230,33 @@ enum.lazy.select { |item| item[:q1] == '⭕️' }.take(1).force | |
| 225 230 | 
             
            # => [{:id=>1, :name=>"Taro", :pet1=>"🐱", :pet2=>"🐶", :pet3=>nil, :q1=>"⭕️", :q2=>"❌", :q3=>"⭕️"}]
         | 
| 226 231 | 
             
            ```
         | 
| 227 232 |  | 
| 233 | 
            +
            #### TableStructure::Table
         | 
| 234 | 
            +
             | 
| 235 | 
            +
            Initialize a table with the schema and render the table:
         | 
| 236 | 
            +
            ```erb
         | 
| 237 | 
            +
            <% TableStructure::Table.new(schema, row_type: :hash) do |table| %>
         | 
| 238 | 
            +
              <table>
         | 
| 239 | 
            +
                <thead>
         | 
| 240 | 
            +
                  <tr>
         | 
| 241 | 
            +
                    <% table.header.each do |key, value| %>
         | 
| 242 | 
            +
                      <th class="<%= key %>"><%= value %></th>
         | 
| 243 | 
            +
                    <% end %>
         | 
| 244 | 
            +
                  </tr>
         | 
| 245 | 
            +
                </thead>
         | 
| 246 | 
            +
             | 
| 247 | 
            +
                <tbody>
         | 
| 248 | 
            +
                  <% table.body(@items).each do |row| %>
         | 
| 249 | 
            +
                    <tr>
         | 
| 250 | 
            +
                      <% row.each do |key, value| %>
         | 
| 251 | 
            +
                        <td class="<%= key %>"><%= value %></td>
         | 
| 252 | 
            +
                      <% end %>
         | 
| 253 | 
            +
                    </tr>
         | 
| 254 | 
            +
                  <% end %>
         | 
| 255 | 
            +
                </tbody>
         | 
| 256 | 
            +
              </table>
         | 
| 257 | 
            +
            <% end %>
         | 
| 258 | 
            +
            ```
         | 
| 259 | 
            +
             | 
| 228 260 | 
             
            ### Advanced
         | 
| 229 261 |  | 
| 230 262 | 
             
            You can add definitions when initializing the schema.
         | 
| @@ -244,7 +276,7 @@ schema = UserTableSchema.new do | |
| 244 276 | 
             
            end
         | 
| 245 277 | 
             
            ```
         | 
| 246 278 |  | 
| 247 | 
            -
            You can also omit columns by  | 
| 279 | 
            +
            You can also omit columns by using `:omitted`.
         | 
| 248 280 | 
             
            ```ruby
         | 
| 249 281 | 
             
            class UserTableSchema
         | 
| 250 282 | 
             
              include TableStructure::Schema
         | 
| @@ -265,7 +297,7 @@ context = { admin: true } | |
| 265 297 | 
             
            schema = UserTableSchema.new(context: context)
         | 
| 266 298 | 
             
            ```
         | 
| 267 299 |  | 
| 268 | 
            -
            You can also omit columns by  | 
| 300 | 
            +
            You can also omit columns by using `:nil_definitions_ignored` option.
         | 
| 269 301 | 
             
            If this option is set to `true` and `column(s)` difinition returns `nil`, the difinition is ignored.
         | 
| 270 302 | 
             
            ```ruby
         | 
| 271 303 | 
             
            class SampleTableSchema
         | 
| @@ -327,37 +359,27 @@ end | |
| 327 359 | 
             
            class SampleTableSchema
         | 
| 328 360 | 
             
              include TableStructure::Schema
         | 
| 329 361 |  | 
| 330 | 
            -
              columns  | 
| 362 | 
            +
              columns UserTableSchema
         | 
| 331 363 | 
             
              ## or
         | 
| 332 | 
            -
              # columns UserTableSchema
         | 
| 364 | 
            +
              # columns ->(table) { UserTableSchema.new(context: table) }
         | 
| 333 365 |  | 
| 334 | 
            -
              columns  | 
| 366 | 
            +
              columns PetTableSchema
         | 
| 335 367 | 
             
              ## or
         | 
| 336 | 
            -
              # columns PetTableSchema
         | 
| 368 | 
            +
              # columns ->(table) { PetTableSchema.new(context: table) }
         | 
| 337 369 |  | 
| 338 | 
            -
              columns  | 
| 370 | 
            +
              columns QuestionTableSchema
         | 
| 339 371 | 
             
              ## or
         | 
| 340 | 
            -
              # columns QuestionTableSchema
         | 
| 372 | 
            +
              # columns ->(table) { QuestionTableSchema.new(context: table) }
         | 
| 341 373 | 
             
            end
         | 
| 342 | 
            -
             | 
| 343 | 
            -
            context = {
         | 
| 344 | 
            -
              questions: [
         | 
| 345 | 
            -
                { id: 'Q1', text: 'Do you like sushi?' },
         | 
| 346 | 
            -
                { id: 'Q2', text: 'Do you like yakiniku?' },
         | 
| 347 | 
            -
                { id: 'Q3', text: 'Do you like ramen?' }
         | 
| 348 | 
            -
              ]
         | 
| 349 | 
            -
            }
         | 
| 350 | 
            -
             | 
| 351 | 
            -
            schema = SampleTableSchema.new(context: context)
         | 
| 352 374 | 
             
            ```
         | 
| 353 375 |  | 
| 354 376 | 
             
            You can also concatenate or merge the schema classes.
         | 
| 355 377 | 
             
            Both create a schema class, with a few differences.
         | 
| 356 378 | 
             
            - `+`
         | 
| 357 379 | 
             
              - Similar to nesting the schemas.
         | 
| 358 | 
            -
                `column_converter`  | 
| 380 | 
            +
                `column_converter` works only to columns in the schema that they was defined.
         | 
| 359 381 | 
             
            - `merge`
         | 
| 360 | 
            -
              - If there are some definitions of `column_converter`  | 
| 382 | 
            +
              - If there are some definitions of `column_converter` with the same name in the schemas to be merged, the one in the schema that is merged last will work to all columns.
         | 
| 361 383 |  | 
| 362 384 | 
             
            ```ruby
         | 
| 363 385 | 
             
            class UserTableSchema
         | 
| @@ -444,30 +466,9 @@ class SampleTableSchema | |
| 444 466 | 
             
            end
         | 
| 445 467 | 
             
            ```
         | 
| 446 468 |  | 
| 447 | 
            -
             | 
| 448 | 
            -
            ```erb
         | 
| 449 | 
            -
            <% @schema.create_table(row_type: :hash) do |table| %>
         | 
| 450 | 
            -
              <table>
         | 
| 451 | 
            -
                <thead>
         | 
| 452 | 
            -
                  <tr>
         | 
| 453 | 
            -
                    <% table.header.each do |key, value| %>
         | 
| 454 | 
            -
                      <th class="<%= key %>"><%= value %></th>
         | 
| 455 | 
            -
                    <% end %>
         | 
| 456 | 
            -
                  </tr>
         | 
| 457 | 
            -
                </thead>
         | 
| 469 | 
            +
            ## Sample with docker
         | 
| 458 470 |  | 
| 459 | 
            -
             | 
| 460 | 
            -
                  <% table.body(@items).each do |row| %>
         | 
| 461 | 
            -
                    <tr>
         | 
| 462 | 
            -
                      <% row.each do |key, value| %>
         | 
| 463 | 
            -
                        <td class="<%= key %>"><%= value %></td>
         | 
| 464 | 
            -
                      <% end %>
         | 
| 465 | 
            -
                    </tr>
         | 
| 466 | 
            -
                  <% end %>
         | 
| 467 | 
            -
                </tbody>
         | 
| 468 | 
            -
              </table>
         | 
| 469 | 
            -
            <% end %>
         | 
| 470 | 
            -
            ```
         | 
| 471 | 
            +
            https://github.com/jsmmr/ruby_table_structure_sample
         | 
| 471 472 |  | 
| 472 473 | 
             
            ## Contributing
         | 
| 473 474 |  | 
    
        data/lib/table_structure.rb
    CHANGED
    
    | @@ -21,14 +21,16 @@ module TableStructure | |
| 21 21 | 
             
              require 'table_structure/schema/definition/columns/attributes'
         | 
| 22 22 | 
             
              require 'table_structure/schema/definition/columns/schema_class'
         | 
| 23 23 | 
             
              require 'table_structure/schema/definition/columns/schema_instance'
         | 
| 24 | 
            -
              require 'table_structure/schema/ | 
| 25 | 
            -
              require 'table_structure/schema/ | 
| 26 | 
            -
              require 'table_structure/schema/ | 
| 27 | 
            -
              require 'table_structure/schema/keys_generator'
         | 
| 28 | 
            -
              require 'table_structure/schema/table'
         | 
| 24 | 
            +
              require 'table_structure/schema/column_converter'
         | 
| 25 | 
            +
              require 'table_structure/schema/row_builder'
         | 
| 26 | 
            +
              require 'table_structure/schema/key_converter'
         | 
| 29 27 | 
             
              require 'table_structure/schema/columns/attributes'
         | 
| 30 28 | 
             
              require 'table_structure/schema/columns/schema'
         | 
| 31 29 | 
             
              require 'table_structure/schema/utils'
         | 
| 30 | 
            +
              require 'table_structure/table'
         | 
| 31 | 
            +
              require 'table_structure/table/column_converter'
         | 
| 32 | 
            +
              require 'table_structure/table/context_builder'
         | 
| 33 | 
            +
              require 'table_structure/table/row_builder'
         | 
| 32 34 | 
             
              require 'table_structure/table/iterator'
         | 
| 33 35 | 
             
              require 'table_structure/writer'
         | 
| 34 36 | 
             
              require 'table_structure/csv/writer'
         | 
| @@ -2,21 +2,106 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            module TableStructure
         | 
| 4 4 | 
             
              class Iterator
         | 
| 5 | 
            -
                def initialize( | 
| 6 | 
            -
                   | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
                   | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
                     | 
| 5 | 
            +
                def initialize(
         | 
| 6 | 
            +
                  schema,
         | 
| 7 | 
            +
                  header: { context: nil },
         | 
| 8 | 
            +
                  row_type: :array,
         | 
| 9 | 
            +
                  **deprecated_options
         | 
| 10 | 
            +
                )
         | 
| 11 | 
            +
                  if deprecated_options.key?(:header_omitted)
         | 
| 12 | 
            +
                    header_omitted = deprecated_options[:header_omitted]
         | 
| 13 | 
            +
                    warn "[TableStructure] `header_omitted: #{!!header_omitted}` option has been deprecated. Use `header: #{!header_omitted}` option instead."
         | 
| 14 | 
            +
                    header = !header_omitted
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  if deprecated_options.key?(:header_context)
         | 
| 18 | 
            +
                    header_context = deprecated_options[:header_context]
         | 
| 19 | 
            +
                    warn '[TableStructure] `:header_context` option has been deprecated. Use `header: { context: ... }` option instead.'
         | 
| 20 | 
            +
                    header = { context: header_context }
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  if deprecated_options.key?(:result_type)
         | 
| 24 | 
            +
                    warn '[TableStructure] `:result_type` option has been deprecated. Use `:row_type` option instead.'
         | 
| 25 | 
            +
                    row_type = deprecated_options[:result_type]
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  unless schema.is_a?(Schema)
         | 
| 29 | 
            +
                    raise ::TableStructure::Error, "Must be use Schema. #{schema}"
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  @schema = schema
         | 
| 33 | 
            +
                  @options = {
         | 
| 34 | 
            +
                    header: header,
         | 
| 35 | 
            +
                    row_type: row_type
         | 
| 36 | 
            +
                  }
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def iterate(
         | 
| 40 | 
            +
                  items,
         | 
| 41 | 
            +
                  **deprecated_options,
         | 
| 42 | 
            +
                  &block
         | 
| 43 | 
            +
                )
         | 
| 44 | 
            +
                  header = @options[:header]
         | 
| 45 | 
            +
                  row_type = @options[:row_type]
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  if deprecated_options.key?(:header)
         | 
| 48 | 
            +
                    header = deprecated_options[:header]
         | 
| 49 | 
            +
                    warn '[TableStructure] Use :header option on initialize method.'
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  if deprecated_options.key?(:header_omitted)
         | 
| 53 | 
            +
                    header_omitted = deprecated_options[:header_omitted]
         | 
| 54 | 
            +
                    warn "[TableStructure] `header_omitted: #{!!header_omitted}` option has been deprecated. Use `header: #{!header_omitted}` option instead."
         | 
| 55 | 
            +
                    header = !header_omitted
         | 
| 14 56 | 
             
                  end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                  if deprecated_options.key?(:header_context)
         | 
| 59 | 
            +
                    header_context = deprecated_options[:header_context]
         | 
| 60 | 
            +
                    warn '[TableStructure] `:header_context` option has been deprecated. Use `header: { context: ... }` option instead.'
         | 
| 61 | 
            +
                    header = { context: header_context }
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                  if deprecated_options.key?(:row_type)
         | 
| 65 | 
            +
                    row_type = deprecated_options[:row_type]
         | 
| 66 | 
            +
                    warn '[TableStructure] Use :row_type option on initialize method.'
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                  if deprecated_options.key?(:result_type)
         | 
| 70 | 
            +
                    warn '[TableStructure] `:result_type` option has been deprecated. Use `:row_type` option instead.'
         | 
| 71 | 
            +
                    row_type = deprecated_options[:result_type]
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                  items = enumerize(items)
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  enum =
         | 
| 77 | 
            +
                    Table::Iterator
         | 
| 78 | 
            +
                    .new(
         | 
| 79 | 
            +
                      Table.new(@schema, row_type: row_type),
         | 
| 80 | 
            +
                      header: header
         | 
| 81 | 
            +
                    )
         | 
| 82 | 
            +
                    .iterate(items)
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                  if block_given?
         | 
| 85 | 
            +
                    enum =
         | 
| 86 | 
            +
                      enum
         | 
| 87 | 
            +
                      .lazy
         | 
| 88 | 
            +
                      .map { |row| block.call(row) }
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  enum
         | 
| 15 92 | 
             
                end
         | 
| 16 93 |  | 
| 17 | 
            -
                 | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 94 | 
            +
                private
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                def enumerize(items)
         | 
| 97 | 
            +
                  if items.respond_to?(:each)
         | 
| 98 | 
            +
                    items
         | 
| 99 | 
            +
                  elsif items.respond_to?(:call)
         | 
| 100 | 
            +
                    warn "[TableStructure] Use `Enumerator` to wrap items instead of `lambda`. The use of `lambda` has been deprecated. #{items}"
         | 
| 101 | 
            +
                    Enumerator.new { |y| items.call(y) }
         | 
| 102 | 
            +
                  else
         | 
| 103 | 
            +
                    raise ::TableStructure::Error, "Must be enumerable. #{items}"
         | 
| 104 | 
            +
                  end
         | 
| 20 105 | 
             
                end
         | 
| 21 106 | 
             
              end
         | 
| 22 107 | 
             
            end
         | 
| @@ -21,15 +21,12 @@ module TableStructure | |
| 21 21 | 
             
                  end
         | 
| 22 22 | 
             
                end
         | 
| 23 23 |  | 
| 24 | 
            -
                 | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
                  :context,
         | 
| 31 | 
            -
                  :options
         | 
| 32 | 
            -
                )
         | 
| 24 | 
            +
                attr_reader :columns,
         | 
| 25 | 
            +
                            :context_builders,
         | 
| 26 | 
            +
                            :column_converters,
         | 
| 27 | 
            +
                            :key_converter,
         | 
| 28 | 
            +
                            :row_builders,
         | 
| 29 | 
            +
                            :context
         | 
| 33 30 |  | 
| 34 31 | 
             
                def initialize(
         | 
| 35 32 | 
             
                  name: self.class.name,
         | 
| @@ -42,20 +39,27 @@ module TableStructure | |
| 42 39 | 
             
                  **deprecated_options,
         | 
| 43 40 | 
             
                  &block
         | 
| 44 41 | 
             
                )
         | 
| 45 | 
            -
                   | 
| 46 | 
            -
                     | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 42 | 
            +
                  if deprecated_options.key?(:row_type)
         | 
| 43 | 
            +
                    raise ::TableStructure::Error, 'Use :row_type option with Table, Writer or Iterator.'
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  if deprecated_options.key?(:result_type)
         | 
| 47 | 
            +
                    raise ::TableStructure::Error, ':result_type option has been deprecated. Use :row_type option instead.'
         | 
| 50 48 | 
             
                  end
         | 
| 51 49 |  | 
| 52 | 
            -
                  options = | 
| 53 | 
            -
                     | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 50 | 
            +
                  options =
         | 
| 51 | 
            +
                    [
         | 
| 52 | 
            +
                      self.class.options,
         | 
| 53 | 
            +
                      {
         | 
| 54 | 
            +
                        name_prefix: name_prefix,
         | 
| 55 | 
            +
                        name_suffix: name_suffix,
         | 
| 56 | 
            +
                        key_prefix: key_prefix,
         | 
| 57 | 
            +
                        key_suffix: key_suffix,
         | 
| 58 | 
            +
                        nil_definitions_ignored: nil_definitions_ignored
         | 
| 59 | 
            +
                      },
         | 
| 60 | 
            +
                      deprecated_options
         | 
| 61 | 
            +
                    ]
         | 
| 62 | 
            +
                    .reduce({}, &:merge!)
         | 
| 59 63 |  | 
| 60 64 | 
             
                  schema_classes = [self.class]
         | 
| 61 65 |  | 
| @@ -63,90 +67,65 @@ module TableStructure | |
| 63 67 | 
             
                    schema_classes << ::TableStructure::Schema.create_class(&block)
         | 
| 64 68 | 
             
                  end
         | 
| 65 69 |  | 
| 66 | 
            -
                  context_builders = | 
| 67 | 
            -
                    schema_classes | 
| 68 | 
            -
             | 
| 70 | 
            +
                  @context_builders =
         | 
| 71 | 
            +
                    schema_classes
         | 
| 72 | 
            +
                    .map(&:context_builders)
         | 
| 73 | 
            +
                    .reduce({}, &:merge!)
         | 
| 69 74 |  | 
| 70 | 
            -
                   | 
| 71 | 
            -
             | 
| 72 | 
            -
                  )
         | 
| 75 | 
            +
                  table_context_builder = @context_builders.delete(:table)
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  @context = table_context_builder ? table_context_builder.call(context) : context
         | 
| 73 78 |  | 
| 74 | 
            -
                   | 
| 75 | 
            -
                    schema_classes | 
| 79 | 
            +
                  @column_converters =
         | 
| 80 | 
            +
                    schema_classes
         | 
| 81 | 
            +
                    .map(&:column_converters)
         | 
| 82 | 
            +
                    .reduce({}, &:merge!)
         | 
| 83 | 
            +
                    .merge(
         | 
| 84 | 
            +
                      ColumnConverter.create_optional_converters(
         | 
| 85 | 
            +
                        name_prefix: options.delete(:name_prefix),
         | 
| 86 | 
            +
                        name_suffix: options.delete(:name_suffix)
         | 
| 87 | 
            +
                      )
         | 
| 88 | 
            +
                    )
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                  @key_converter = KeyConverter.new(
         | 
| 91 | 
            +
                    prefix: options.delete(:key_prefix),
         | 
| 92 | 
            +
                    suffix: options.delete(:key_suffix)
         | 
| 76 93 | 
             
                  )
         | 
| 77 94 |  | 
| 78 | 
            -
                   | 
| 95 | 
            +
                  @row_builders =
         | 
| 96 | 
            +
                    RowBuilder.prepend_default_builders(
         | 
| 97 | 
            +
                      schema_classes
         | 
| 98 | 
            +
                        .map(&:row_builders)
         | 
| 99 | 
            +
                        .reduce({}, &:merge!)
         | 
| 100 | 
            +
                    )
         | 
| 79 101 |  | 
| 80 | 
            -
                  columns =
         | 
| 102 | 
            +
                  @columns =
         | 
| 81 103 | 
             
                    Definition::Columns::Compiler
         | 
| 82 104 | 
             
                    .new(
         | 
| 83 105 | 
             
                      name,
         | 
| 84 106 | 
             
                      schema_classes.map(&:column_definitions).reduce([], &:concat),
         | 
| 85 | 
            -
                      options
         | 
| 107 | 
            +
                      { nil_definitions_ignored: options.delete(:nil_definitions_ignored) }
         | 
| 86 108 | 
             
                    )
         | 
| 87 | 
            -
                    .compile( | 
| 109 | 
            +
                    .compile(@context)
         | 
| 88 110 |  | 
| 89 | 
            -
                  @ | 
| 90 | 
            -
                    MyDefinition.new(
         | 
| 91 | 
            -
                      name,
         | 
| 92 | 
            -
                      columns,
         | 
| 93 | 
            -
                      context_builders,
         | 
| 94 | 
            -
                      column_converters,
         | 
| 95 | 
            -
                      row_builders,
         | 
| 96 | 
            -
                      table_context,
         | 
| 97 | 
            -
                      options
         | 
| 98 | 
            -
                    )
         | 
| 111 | 
            +
                  @options = options
         | 
| 99 112 | 
             
                end
         | 
| 100 113 |  | 
| 101 | 
            -
                def create_table(row_type: :array, **deprecated_options)
         | 
| 102 | 
            -
                   | 
| 114 | 
            +
                def create_table(row_type: :array, **deprecated_options, &block)
         | 
| 115 | 
            +
                  warn '[TableStructure] `TableStructure::Schema#create_table` has been deprecated. Use `TableStructure::Table.new` instead.'
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                  options = @options.merge(deprecated_options)
         | 
| 103 118 |  | 
| 104 119 | 
             
                  if options.key?(:result_type)
         | 
| 105 120 | 
             
                    warn '[TableStructure] `:result_type` option has been deprecated. Use `:row_type` option instead.'
         | 
| 106 121 | 
             
                    options[:row_type] = options[:result_type]
         | 
| 107 122 | 
             
                  end
         | 
| 108 123 |  | 
| 109 | 
            -
                   | 
| 110 | 
            -
             | 
| 111 | 
            -
                    suffix: options[:key_suffix]
         | 
| 112 | 
            -
                  }
         | 
| 113 | 
            -
             | 
| 114 | 
            -
                  keys_generator = KeysGenerator.new(
         | 
| 115 | 
            -
                    **keys_generator_options
         | 
| 116 | 
            -
                  )
         | 
| 117 | 
            -
             | 
| 118 | 
            -
                  table = Table.new(
         | 
| 119 | 
            -
                    columns: @_definition_.columns,
         | 
| 120 | 
            -
                    context: @_definition_.context,
         | 
| 121 | 
            -
                    keys_generator: keys_generator
         | 
| 122 | 
            -
                  )
         | 
| 123 | 
            -
             | 
| 124 | 
            -
                  @_definition_
         | 
| 125 | 
            -
                    .context_builders
         | 
| 126 | 
            -
                    .extend_methods_for(table)
         | 
| 127 | 
            -
             | 
| 128 | 
            -
                  column_converters_options = {
         | 
| 129 | 
            -
                    name_prefix: options[:name_prefix],
         | 
| 130 | 
            -
                    name_suffix: options[:name_suffix]
         | 
| 131 | 
            -
                  }
         | 
| 132 | 
            -
             | 
| 133 | 
            -
                  @_definition_
         | 
| 134 | 
            -
                    .column_converters
         | 
| 135 | 
            -
                    .extend_methods_for(table, **column_converters_options)
         | 
| 136 | 
            -
             | 
| 137 | 
            -
                  row_builders_options = {
         | 
| 138 | 
            -
                    row_type: options[:row_type] || row_type
         | 
| 139 | 
            -
                  }
         | 
| 140 | 
            -
             | 
| 141 | 
            -
                  @_definition_
         | 
| 142 | 
            -
                    .row_builders
         | 
| 143 | 
            -
                    .extend_methods_for(table, **row_builders_options)
         | 
| 124 | 
            +
                  ::TableStructure::Table.new(self, row_type: options[:row_type] || row_type, &block)
         | 
| 125 | 
            +
                end
         | 
| 144 126 |  | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 147 | 
            -
                  else
         | 
| 148 | 
            -
                    table
         | 
| 149 | 
            -
                  end
         | 
| 127 | 
            +
                def contain_callable?(attribute)
         | 
| 128 | 
            +
                  @columns.any? { |column| column.contain_callable?(attribute) }
         | 
| 150 129 | 
             
                end
         | 
| 151 130 | 
             
              end
         | 
| 152 131 | 
             
            end
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module TableStructure
         | 
| 4 | 
            +
              module Schema
         | 
| 5 | 
            +
                module ColumnConverter
         | 
| 6 | 
            +
                  class << self
         | 
| 7 | 
            +
                    def create_optional_converters(
         | 
| 8 | 
            +
                      name_prefix: nil,
         | 
| 9 | 
            +
                      name_suffix: nil
         | 
| 10 | 
            +
                    )
         | 
| 11 | 
            +
                      column_converters = {}
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                      if name_prefix
         | 
| 14 | 
            +
                        column_converters[:_name_prepender_] =
         | 
| 15 | 
            +
                          create_prepender(name_prefix, header: true, body: false)
         | 
| 16 | 
            +
                      end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                      if name_suffix
         | 
| 19 | 
            +
                        column_converters[:_name_appender_] =
         | 
| 20 | 
            +
                          create_appender(name_suffix, header: true, body: false)
         | 
| 21 | 
            +
                      end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                      column_converters
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    private
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    def create_prepender(string, **options)
         | 
| 29 | 
            +
                      Definition::ColumnConverter.new(
         | 
| 30 | 
            +
                        lambda { |val, *|
         | 
| 31 | 
            +
                          val.nil? ? val : "#{string}#{val}"
         | 
| 32 | 
            +
                        },
         | 
| 33 | 
            +
                        **options
         | 
| 34 | 
            +
                      )
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                    def create_appender(string, **options)
         | 
| 38 | 
            +
                      Definition::ColumnConverter.new(
         | 
| 39 | 
            +
                        lambda { |val, *|
         | 
| 40 | 
            +
                          val.nil? ? val : "#{val}#{string}"
         | 
| 41 | 
            +
                        },
         | 
| 42 | 
            +
                        **options
         | 
| 43 | 
            +
                      )
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
            end
         | 
| @@ -5,7 +5,8 @@ module TableStructure | |
| 5 5 | 
             
                module Columns
         | 
| 6 6 | 
             
                  class Schema
         | 
| 7 7 | 
             
                    def initialize(schema)
         | 
| 8 | 
            -
                      @ | 
| 8 | 
            +
                      @schema = schema
         | 
| 9 | 
            +
                      @table = ::TableStructure::Table.new(schema)
         | 
| 9 10 | 
             
                    end
         | 
| 10 11 |  | 
| 11 12 | 
             
                    def names(header_context, _table_context)
         | 
| @@ -25,7 +26,7 @@ module TableStructure | |
| 25 26 | 
             
                    end
         | 
| 26 27 |  | 
| 27 28 | 
             
                    def contain_callable?(attribute)
         | 
| 28 | 
            -
                      @ | 
| 29 | 
            +
                      @schema.contain_callable?(attribute)
         | 
| 29 30 | 
             
                    end
         | 
| 30 31 | 
             
                  end
         | 
| 31 32 | 
             
                end
         | 
| @@ -2,13 +2,13 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            module TableStructure
         | 
| 4 4 | 
             
              module Schema
         | 
| 5 | 
            -
                class  | 
| 5 | 
            +
                class KeyConverter
         | 
| 6 6 | 
             
                  def initialize(prefix: nil, suffix: nil)
         | 
| 7 7 | 
             
                    @prefix = prefix
         | 
| 8 8 | 
             
                    @suffix = suffix
         | 
| 9 9 | 
             
                  end
         | 
| 10 10 |  | 
| 11 | 
            -
                  def  | 
| 11 | 
            +
                  def convert(keys)
         | 
| 12 12 | 
             
                    return keys unless has_any_options?
         | 
| 13 13 |  | 
| 14 14 | 
             
                    keys.map do |key|
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module TableStructure
         | 
| 4 | 
            +
              module Schema
         | 
| 5 | 
            +
                module RowBuilder
         | 
| 6 | 
            +
                  DEFAULT_ROW_BUILDERS = {
         | 
| 7 | 
            +
                    _to_hash_: Definition::RowBuilder.new(
         | 
| 8 | 
            +
                      lambda { |values, keys, *|
         | 
| 9 | 
            +
                        keys.map.with_index { |key, i| [key || i, values[i]] }.to_h
         | 
| 10 | 
            +
                      },
         | 
| 11 | 
            +
                      enabled_row_types: [:hash]
         | 
| 12 | 
            +
                    )
         | 
| 13 | 
            +
                  }.freeze
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  class << self
         | 
| 16 | 
            +
                    def prepend_default_builders(builders)
         | 
| 17 | 
            +
                      DEFAULT_ROW_BUILDERS.merge(builders)
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
| @@ -0,0 +1,72 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module TableStructure
         | 
| 4 | 
            +
              class Table
         | 
| 5 | 
            +
                def initialize(schema, row_type: :array)
         | 
| 6 | 
            +
                  @columns = schema.columns
         | 
| 7 | 
            +
                  @context = schema.context
         | 
| 8 | 
            +
                  @key_converter = schema.key_converter
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  ContextBuilder.create_module(
         | 
| 11 | 
            +
                    schema.context_builders,
         | 
| 12 | 
            +
                    apply_to_name: schema.contain_callable?(:name),
         | 
| 13 | 
            +
                    apply_to_value: schema.contain_callable?(:value),
         | 
| 14 | 
            +
                    context: schema.context
         | 
| 15 | 
            +
                  ) { |mod| extend mod }
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  ColumnConverter.create_module(
         | 
| 18 | 
            +
                    schema.column_converters,
         | 
| 19 | 
            +
                    context: schema.context
         | 
| 20 | 
            +
                  ) { |mod| extend mod }
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  RowBuilder.create_module(
         | 
| 23 | 
            +
                    schema.row_builders,
         | 
| 24 | 
            +
                    row_type: row_type,
         | 
| 25 | 
            +
                    keys: keys,
         | 
| 26 | 
            +
                    context: schema.context
         | 
| 27 | 
            +
                  ) { |mod| extend mod }
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  yield self if block_given?
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def header(context: nil)
         | 
| 33 | 
            +
                  row_values(:names, context)
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                def body(items)
         | 
| 37 | 
            +
                  Enumerator.new do |y|
         | 
| 38 | 
            +
                    items.each { |item| y << data(context: item) }
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                def rows(items)
         | 
| 43 | 
            +
                  warn '[TableStructure] `TableStructure::Table#rows(items)` has been deprecated. Use `TableStructure::Table#body(items)` instead.'
         | 
| 44 | 
            +
                  body(items)
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                def row(context: nil)
         | 
| 48 | 
            +
                  warn '[TableStructure] `TableStructure::Table#row(context: ...)` has been deprecated. Use `TableStructure::Table#body(items)` instead.'
         | 
| 49 | 
            +
                  data(context: context)
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                private
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                def data(context: nil)
         | 
| 55 | 
            +
                  row_values(:values, context)
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                def keys
         | 
| 59 | 
            +
                  @keys ||= @key_converter.convert(@columns.map(&:keys).flatten)
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                def size
         | 
| 63 | 
            +
                  @size ||= @columns.map(&:size).reduce(0, &:+)
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                def row_values(method, context)
         | 
| 67 | 
            +
                  @columns
         | 
| 68 | 
            +
                    .map { |column| column.send(method, context, @context) }
         | 
| 69 | 
            +
                    .flatten
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
            end
         | 
| @@ -0,0 +1,46 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module TableStructure
         | 
| 4 | 
            +
              class Table::ColumnConverter
         | 
| 5 | 
            +
                class ColumnConvertible < Module
         | 
| 6 | 
            +
                  def initialize(methods)
         | 
| 7 | 
            +
                    methods.each do |name, method|
         | 
| 8 | 
            +
                      define_method(name, &method)
         | 
| 9 | 
            +
                    end
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                class << self
         | 
| 14 | 
            +
                  def create_module(converters, context:)
         | 
| 15 | 
            +
                    return if converters.empty?
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    header_converters = converters.select { |_k, v| v.applicable_to_header? }
         | 
| 18 | 
            +
                    body_converters = converters.select { |_k, v| v.applicable_to_body? }
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    methods = {}
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    unless header_converters.empty?
         | 
| 23 | 
            +
                      methods[:header] = create_method(header_converters, context)
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    unless body_converters.empty?
         | 
| 27 | 
            +
                      methods[:data] = create_method(body_converters, context)
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    yield ColumnConvertible.new(methods)
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  private
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  def create_method(converters, table_context)
         | 
| 36 | 
            +
                    proc do |context: nil|
         | 
| 37 | 
            +
                      super(context: context).map do |val|
         | 
| 38 | 
            +
                        converters.reduce(val) do |val, (_, converter)|
         | 
| 39 | 
            +
                          converter.call(val, context, table_context)
         | 
| 40 | 
            +
                        end
         | 
| 41 | 
            +
                      end
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
            end
         | 
| @@ -0,0 +1,49 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module TableStructure
         | 
| 4 | 
            +
              class Table::ContextBuilder
         | 
| 5 | 
            +
                class ContextBuildable < Module
         | 
| 6 | 
            +
                  def initialize(methods)
         | 
| 7 | 
            +
                    methods.each do |name, method|
         | 
| 8 | 
            +
                      define_method(name, &method)
         | 
| 9 | 
            +
                    end
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                class << self
         | 
| 14 | 
            +
                  def create_module(
         | 
| 15 | 
            +
                    builders,
         | 
| 16 | 
            +
                    apply_to_name: true,
         | 
| 17 | 
            +
                    apply_to_value: true,
         | 
| 18 | 
            +
                    context:
         | 
| 19 | 
            +
                  )
         | 
| 20 | 
            +
                    return if builders.empty?
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    header_builder = builders[:header] # will remove
         | 
| 23 | 
            +
                    row_builder = builders[:row]
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    methods = {}
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    if apply_to_name && builders.key?(:header)
         | 
| 28 | 
            +
                      methods[:header] = create_method(builders[:header])
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    if apply_to_value && builders.key?(:row)
         | 
| 32 | 
            +
                      methods[:data] = create_method(builders[:row])
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    yield ContextBuildable.new(methods)
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  private
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def create_method(builder)
         | 
| 41 | 
            +
                    return if builder.nil?
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                    proc do |context: nil|
         | 
| 44 | 
            +
                      super(context: builder.call(context))
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
            end
         | 
| @@ -1,23 +1,21 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            module TableStructure
         | 
| 4 | 
            -
               | 
| 5 | 
            -
                 | 
| 6 | 
            -
                   | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
                  end
         | 
| 4 | 
            +
              class Table::Iterator
         | 
| 5 | 
            +
                def initialize(table, header: { context: nil })
         | 
| 6 | 
            +
                  @table = table
         | 
| 7 | 
            +
                  @header_options = header
         | 
| 8 | 
            +
                end
         | 
| 10 9 |  | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
                      end
         | 
| 17 | 
            -
                      @table
         | 
| 18 | 
            -
                        .body(items)
         | 
| 19 | 
            -
                        .each { |row| y << row }
         | 
| 10 | 
            +
                def iterate(items)
         | 
| 11 | 
            +
                  ::Enumerator.new do |y|
         | 
| 12 | 
            +
                    if @header_options
         | 
| 13 | 
            +
                      header_context = @header_options.is_a?(Hash) ? @header_options[:context] : nil
         | 
| 14 | 
            +
                      y << @table.header(context: header_context)
         | 
| 20 15 | 
             
                    end
         | 
| 16 | 
            +
                    @table
         | 
| 17 | 
            +
                      .body(items)
         | 
| 18 | 
            +
                      .each { |row| y << row }
         | 
| 21 19 | 
             
                  end
         | 
| 22 20 | 
             
                end
         | 
| 23 21 | 
             
              end
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module TableStructure
         | 
| 4 | 
            +
              class Table::RowBuilder
         | 
| 5 | 
            +
                class ResultBuildable < Module
         | 
| 6 | 
            +
                  def initialize(methods)
         | 
| 7 | 
            +
                    methods.each do |name, method|
         | 
| 8 | 
            +
                      define_method(name, &method)
         | 
| 9 | 
            +
                    end
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                class << self
         | 
| 14 | 
            +
                  def create_module(builders, row_type:, keys:, context:)
         | 
| 15 | 
            +
                    return if builders.empty?
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    builders = builders.select { |_k, v| v.enabled?(row_type) }
         | 
| 18 | 
            +
                    return if builders.empty?
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    yield ResultBuildable.new(
         | 
| 21 | 
            +
                      header: create_method(builders, keys, context),
         | 
| 22 | 
            +
                      data: create_method(builders, keys, context)
         | 
| 23 | 
            +
                    )
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  private
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def create_method(builders, table_keys, table_context)
         | 
| 29 | 
            +
                    proc do |context: nil|
         | 
| 30 | 
            +
                      builders
         | 
| 31 | 
            +
                        .reduce(super(context: context)) do |vals, (_, builder)|
         | 
| 32 | 
            +
                          builder.call(vals, table_keys, context, table_context)
         | 
| 33 | 
            +
                        end
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            end
         | 
| @@ -46,7 +46,7 @@ module TableStructure | |
| 46 46 |  | 
| 47 47 | 
             
                  if deprecated_options.key?(:header)
         | 
| 48 48 | 
             
                    header = deprecated_options[:header]
         | 
| 49 | 
            -
                    warn '[TableStructure]  | 
| 49 | 
            +
                    warn '[TableStructure] Use :header option on initialize method.'
         | 
| 50 50 | 
             
                  end
         | 
| 51 51 |  | 
| 52 52 | 
             
                  if deprecated_options.key?(:header_omitted)
         | 
| @@ -63,7 +63,7 @@ module TableStructure | |
| 63 63 |  | 
| 64 64 | 
             
                  if deprecated_options.key?(:row_type)
         | 
| 65 65 | 
             
                    row_type = deprecated_options[:row_type]
         | 
| 66 | 
            -
                    warn '[TableStructure]  | 
| 66 | 
            +
                    warn '[TableStructure] Use :row_type option on initialize method.'
         | 
| 67 67 | 
             
                  end
         | 
| 68 68 |  | 
| 69 69 | 
             
                  if deprecated_options.key?(:result_type)
         | 
| @@ -71,28 +71,13 @@ module TableStructure | |
| 71 71 | 
             
                    row_type = deprecated_options[:result_type]
         | 
| 72 72 | 
             
                  end
         | 
| 73 73 |  | 
| 74 | 
            -
                   | 
| 74 | 
            +
                  output = Output.new(to, method: method)
         | 
| 75 75 |  | 
| 76 | 
            -
                   | 
| 77 | 
            -
                     | 
| 76 | 
            +
                  Iterator
         | 
| 77 | 
            +
                    .new(@schema, header: header, row_type: row_type)
         | 
| 78 | 
            +
                    .iterate(items, &block)
         | 
| 79 | 
            +
                    .each { |row| output.write(row) }
         | 
| 78 80 |  | 
| 79 | 
            -
                    enum =
         | 
| 80 | 
            -
                      Table::Iterator
         | 
| 81 | 
            -
                      .new(
         | 
| 82 | 
            -
                        table,
         | 
| 83 | 
            -
                        header: header
         | 
| 84 | 
            -
                      )
         | 
| 85 | 
            -
                      .iterate(items)
         | 
| 86 | 
            -
             | 
| 87 | 
            -
                    if block_given?
         | 
| 88 | 
            -
                      enum =
         | 
| 89 | 
            -
                        enum
         | 
| 90 | 
            -
                        .lazy
         | 
| 91 | 
            -
                        .map { |row| block.call(row) }
         | 
| 92 | 
            -
                    end
         | 
| 93 | 
            -
             | 
| 94 | 
            -
                    enum.each { |row| output.write(row) }
         | 
| 95 | 
            -
                  end
         | 
| 96 81 | 
             
                  nil
         | 
| 97 82 | 
             
                end
         | 
| 98 83 |  | 
| @@ -108,16 +93,5 @@ module TableStructure | |
| 108 93 | 
             
                    @output.send(@method, values)
         | 
| 109 94 | 
             
                  end
         | 
| 110 95 | 
             
                end
         | 
| 111 | 
            -
             | 
| 112 | 
            -
                def enumerize(items)
         | 
| 113 | 
            -
                  if items.respond_to?(:each)
         | 
| 114 | 
            -
                    items
         | 
| 115 | 
            -
                  elsif items.respond_to?(:call)
         | 
| 116 | 
            -
                    warn "[TableStructure] Use `Enumerator` to wrap items instead of `lambda`. The use of `lambda` has been deprecated. #{items}"
         | 
| 117 | 
            -
                    Enumerator.new { |y| items.call(y) }
         | 
| 118 | 
            -
                  else
         | 
| 119 | 
            -
                    raise ::TableStructure::Error, "Must be enumerable. #{items}"
         | 
| 120 | 
            -
                  end
         | 
| 121 | 
            -
                end
         | 
| 122 96 | 
             
              end
         | 
| 123 97 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: table_structure
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.3. | 
| 4 | 
            +
              version: 0.3.21
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - jsmmr
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2020- | 
| 11 | 
            +
            date: 2020-03-18 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -75,10 +75,9 @@ files: | |
| 75 75 | 
             
            - lib/table_structure/iterator.rb
         | 
| 76 76 | 
             
            - lib/table_structure/schema.rb
         | 
| 77 77 | 
             
            - lib/table_structure/schema/class_methods.rb
         | 
| 78 | 
            -
            - lib/table_structure/schema/ | 
| 78 | 
            +
            - lib/table_structure/schema/column_converter.rb
         | 
| 79 79 | 
             
            - lib/table_structure/schema/columns/attributes.rb
         | 
| 80 80 | 
             
            - lib/table_structure/schema/columns/schema.rb
         | 
| 81 | 
            -
            - lib/table_structure/schema/context_builders.rb
         | 
| 82 81 | 
             
            - lib/table_structure/schema/definition/column_converter.rb
         | 
| 83 82 | 
             
            - lib/table_structure/schema/definition/columns/attributes.rb
         | 
| 84 83 | 
             
            - lib/table_structure/schema/definition/columns/compiler.rb
         | 
| @@ -93,11 +92,14 @@ files: | |
| 93 92 | 
             
            - lib/table_structure/schema/dsl/context_builder.rb
         | 
| 94 93 | 
             
            - lib/table_structure/schema/dsl/option.rb
         | 
| 95 94 | 
             
            - lib/table_structure/schema/dsl/row_builder.rb
         | 
| 96 | 
            -
            - lib/table_structure/schema/ | 
| 97 | 
            -
            - lib/table_structure/schema/ | 
| 98 | 
            -
            - lib/table_structure/schema/table.rb
         | 
| 95 | 
            +
            - lib/table_structure/schema/key_converter.rb
         | 
| 96 | 
            +
            - lib/table_structure/schema/row_builder.rb
         | 
| 99 97 | 
             
            - lib/table_structure/schema/utils.rb
         | 
| 98 | 
            +
            - lib/table_structure/table.rb
         | 
| 99 | 
            +
            - lib/table_structure/table/column_converter.rb
         | 
| 100 | 
            +
            - lib/table_structure/table/context_builder.rb
         | 
| 100 101 | 
             
            - lib/table_structure/table/iterator.rb
         | 
| 102 | 
            +
            - lib/table_structure/table/row_builder.rb
         | 
| 101 103 | 
             
            - lib/table_structure/version.rb
         | 
| 102 104 | 
             
            - lib/table_structure/writer.rb
         | 
| 103 105 | 
             
            - table_structure.gemspec
         | 
| @@ -1,83 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module TableStructure
         | 
| 4 | 
            -
              module Schema
         | 
| 5 | 
            -
                class ColumnConverters
         | 
| 6 | 
            -
                  def initialize(converters)
         | 
| 7 | 
            -
                    @header_converters = converters.select { |_k, v| v.applicable_to_header? }
         | 
| 8 | 
            -
                    @body_converterss = converters.select { |_k, v| v.applicable_to_body? }
         | 
| 9 | 
            -
                  end
         | 
| 10 | 
            -
             | 
| 11 | 
            -
                  def extend_methods_for(table, name_prefix:, name_suffix:)
         | 
| 12 | 
            -
                    table_context = table.instance_variable_get(:@context)
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                    header_converters =
         | 
| 15 | 
            -
                      @header_converters
         | 
| 16 | 
            -
                      .merge(
         | 
| 17 | 
            -
                        _prepend_prefix_: create_prepender(name_prefix),
         | 
| 18 | 
            -
                        _append_suffix_: create_appender(name_suffix)
         | 
| 19 | 
            -
                      )
         | 
| 20 | 
            -
                      .reject { |_k, v| v.nil? }
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                    body_converterss = @body_converterss
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                    methods =
         | 
| 25 | 
            -
                      {
         | 
| 26 | 
            -
                        header: create_method(header_converters, table_context),
         | 
| 27 | 
            -
                        data: create_method(body_converterss, table_context)
         | 
| 28 | 
            -
                      }
         | 
| 29 | 
            -
                      .reject { |_k, v| v.nil? }
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                    return if methods.empty?
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                    table.extend ColumnConvertible.new(methods)
         | 
| 34 | 
            -
                  end
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                  private
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                  def create_prepender(prefix)
         | 
| 39 | 
            -
                    return unless prefix
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                    Definition::ColumnConverter.new(
         | 
| 42 | 
            -
                      lambda { |val, *|
         | 
| 43 | 
            -
                        val.nil? ? val : "#{prefix}#{val}"
         | 
| 44 | 
            -
                      },
         | 
| 45 | 
            -
                      header: true,
         | 
| 46 | 
            -
                      body: false
         | 
| 47 | 
            -
                    )
         | 
| 48 | 
            -
                  end
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                  def create_appender(suffix)
         | 
| 51 | 
            -
                    return unless suffix
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                    Definition::ColumnConverter.new(
         | 
| 54 | 
            -
                      lambda { |val, *|
         | 
| 55 | 
            -
                        val.nil? ? val : "#{val}#{suffix}"
         | 
| 56 | 
            -
                      },
         | 
| 57 | 
            -
                      header: true,
         | 
| 58 | 
            -
                      body: false
         | 
| 59 | 
            -
                    )
         | 
| 60 | 
            -
                  end
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                  def create_method(converters, table_context)
         | 
| 63 | 
            -
                    return if converters.empty?
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                    proc do |context: nil|
         | 
| 66 | 
            -
                      super(context: context).map do |val|
         | 
| 67 | 
            -
                        converters.reduce(val) do |val, (_, converter)|
         | 
| 68 | 
            -
                          converter.call(val, context, table_context)
         | 
| 69 | 
            -
                        end
         | 
| 70 | 
            -
                      end
         | 
| 71 | 
            -
                    end
         | 
| 72 | 
            -
                  end
         | 
| 73 | 
            -
                end
         | 
| 74 | 
            -
             | 
| 75 | 
            -
                class ColumnConvertible < Module
         | 
| 76 | 
            -
                  def initialize(methods)
         | 
| 77 | 
            -
                    methods.each do |name, method|
         | 
| 78 | 
            -
                      define_method(name, &method)
         | 
| 79 | 
            -
                    end
         | 
| 80 | 
            -
                  end
         | 
| 81 | 
            -
                end
         | 
| 82 | 
            -
              end
         | 
| 83 | 
            -
            end
         | 
| @@ -1,55 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module TableStructure
         | 
| 4 | 
            -
              module Schema
         | 
| 5 | 
            -
                class ContextBuilders
         | 
| 6 | 
            -
                  def initialize(builders)
         | 
| 7 | 
            -
                    @table_builder = builders[:table]
         | 
| 8 | 
            -
                    @header_builder = builders[:header]
         | 
| 9 | 
            -
                    @row_builder = builders[:row]
         | 
| 10 | 
            -
                  end
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                  def build_for_table(context)
         | 
| 13 | 
            -
                    if @table_builder
         | 
| 14 | 
            -
                      @table_builder.call(context)
         | 
| 15 | 
            -
                    else
         | 
| 16 | 
            -
                      context
         | 
| 17 | 
            -
                    end
         | 
| 18 | 
            -
                  end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                  def extend_methods_for(table)
         | 
| 21 | 
            -
                    methods = {}
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                    if table.send(:contain_callable?, :name)
         | 
| 24 | 
            -
                      methods[:header] = create_method(@header_builder)
         | 
| 25 | 
            -
                    end
         | 
| 26 | 
            -
                    if table.send(:contain_callable?, :value)
         | 
| 27 | 
            -
                      methods[:data] = create_method(@row_builder)
         | 
| 28 | 
            -
                    end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                    methods.reject! { |_k, v| v.nil? }
         | 
| 31 | 
            -
                    return if methods.empty?
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                    table.extend ContextBuildable.new(methods)
         | 
| 34 | 
            -
                  end
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                  private
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                  def create_method(builder)
         | 
| 39 | 
            -
                    return if builder.nil?
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                    proc do |context: nil|
         | 
| 42 | 
            -
                      super(context: builder.call(context))
         | 
| 43 | 
            -
                    end
         | 
| 44 | 
            -
                  end
         | 
| 45 | 
            -
                end
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                class ContextBuildable < Module
         | 
| 48 | 
            -
                  def initialize(methods)
         | 
| 49 | 
            -
                    methods.each do |name, method|
         | 
| 50 | 
            -
                      define_method(name, &method)
         | 
| 51 | 
            -
                    end
         | 
| 52 | 
            -
                  end
         | 
| 53 | 
            -
                end
         | 
| 54 | 
            -
              end
         | 
| 55 | 
            -
            end
         | 
| @@ -1,58 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module TableStructure
         | 
| 4 | 
            -
              module Schema
         | 
| 5 | 
            -
                class RowBuilders
         | 
| 6 | 
            -
                  DEFAULT_BUILDERS = {
         | 
| 7 | 
            -
                    _to_hash_: ::TableStructure::Schema::Definition::RowBuilder.new(
         | 
| 8 | 
            -
                      lambda { |values, keys, *|
         | 
| 9 | 
            -
                        keys.map.with_index { |key, i| [key || i, values[i]] }.to_h
         | 
| 10 | 
            -
                      },
         | 
| 11 | 
            -
                      enabled_row_types: [:hash]
         | 
| 12 | 
            -
                    )
         | 
| 13 | 
            -
                  }.freeze
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                  def initialize(builders)
         | 
| 16 | 
            -
                    @builders = builders
         | 
| 17 | 
            -
                  end
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                  def extend_methods_for(table, row_type: :array)
         | 
| 20 | 
            -
                    builders =
         | 
| 21 | 
            -
                      DEFAULT_BUILDERS
         | 
| 22 | 
            -
                      .merge(@builders)
         | 
| 23 | 
            -
                      .select { |_k, v| v.enabled?(row_type) }
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                    return if builders.empty?
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                    table_context = table.instance_variable_get(:@context)
         | 
| 28 | 
            -
                    table_keys = table.send(:keys)
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                    table.extend ResultBuildable.new(
         | 
| 31 | 
            -
                      header: create_method(builders, table_keys, table_context),
         | 
| 32 | 
            -
                      data: create_method(builders, table_keys, table_context)
         | 
| 33 | 
            -
                    )
         | 
| 34 | 
            -
                  end
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                  private
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                  def create_method(builders, table_keys, table_context)
         | 
| 39 | 
            -
                    return if builders.empty?
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                    proc do |context: nil|
         | 
| 42 | 
            -
                      builders
         | 
| 43 | 
            -
                        .reduce(super(context: context)) do |vals, (_, builder)|
         | 
| 44 | 
            -
                          builder.call(vals, table_keys, context, table_context)
         | 
| 45 | 
            -
                        end
         | 
| 46 | 
            -
                    end
         | 
| 47 | 
            -
                  end
         | 
| 48 | 
            -
                end
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                class ResultBuildable < Module
         | 
| 51 | 
            -
                  def initialize(methods)
         | 
| 52 | 
            -
                    methods.each do |name, method|
         | 
| 53 | 
            -
                      define_method(name, &method)
         | 
| 54 | 
            -
                    end
         | 
| 55 | 
            -
                  end
         | 
| 56 | 
            -
                end
         | 
| 57 | 
            -
              end
         | 
| 58 | 
            -
            end
         | 
| @@ -1,61 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module TableStructure
         | 
| 4 | 
            -
              module Schema
         | 
| 5 | 
            -
                class Table
         | 
| 6 | 
            -
                  def initialize(
         | 
| 7 | 
            -
                    columns:,
         | 
| 8 | 
            -
                    context:,
         | 
| 9 | 
            -
                    keys_generator:
         | 
| 10 | 
            -
                  )
         | 
| 11 | 
            -
                    @columns = columns
         | 
| 12 | 
            -
                    @context = context
         | 
| 13 | 
            -
                    @keys_generator = keys_generator
         | 
| 14 | 
            -
                  end
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                  def header(context: nil)
         | 
| 17 | 
            -
                    row_values(:names, context)
         | 
| 18 | 
            -
                  end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                  def row(context: nil)
         | 
| 21 | 
            -
                    warn '[TableStructure] `TableStructure::Schema::Table#row(context:)` has been deprecated. Use `TableStructure::Schema::Table#body(items)` instead.'
         | 
| 22 | 
            -
                    data(context: context)
         | 
| 23 | 
            -
                  end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                  def body(items)
         | 
| 26 | 
            -
                    Enumerator.new do |y|
         | 
| 27 | 
            -
                      items.each { |item| y << data(context: item) }
         | 
| 28 | 
            -
                    end
         | 
| 29 | 
            -
                  end
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                  def rows(items)
         | 
| 32 | 
            -
                    warn '[TableStructure] `TableStructure::Schema::Table#rows(items)` has been deprecated. Use `TableStructure::Schema::Table#body(items)` instead.'
         | 
| 33 | 
            -
                    body(items)
         | 
| 34 | 
            -
                  end
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                  private
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                  def data(context: nil)
         | 
| 39 | 
            -
                    row_values(:values, context)
         | 
| 40 | 
            -
                  end
         | 
| 41 | 
            -
             | 
| 42 | 
            -
                  def keys
         | 
| 43 | 
            -
                    @keys ||= @keys_generator.generate(@columns.map(&:keys).flatten)
         | 
| 44 | 
            -
                  end
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                  def size
         | 
| 47 | 
            -
                    @size ||= @columns.map(&:size).reduce(0, &:+)
         | 
| 48 | 
            -
                  end
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                  def row_values(method, context)
         | 
| 51 | 
            -
                    @columns
         | 
| 52 | 
            -
                      .map { |column| column.send(method, context, @context) }
         | 
| 53 | 
            -
                      .flatten
         | 
| 54 | 
            -
                  end
         | 
| 55 | 
            -
             | 
| 56 | 
            -
                  def contain_callable?(attribute)
         | 
| 57 | 
            -
                    @columns.any? { |column| column.contain_callable?(attribute) }
         | 
| 58 | 
            -
                  end
         | 
| 59 | 
            -
                end
         | 
| 60 | 
            -
              end
         | 
| 61 | 
            -
            end
         |