csv_row_model 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5498738789715db182f898e6d048cf27368bc5b9
4
- data.tar.gz: f70ad9d361f804afd025e3c5214dc63c2734f603
3
+ metadata.gz: 1875456398a0d03c7704e622ef2fb992c628d436
4
+ data.tar.gz: 8da58e2819b99eb9be2caa92e319ec505fa7f6b5
5
5
  SHA512:
6
- metadata.gz: 60d6189fe5d90a7efb8e5630080f8b2d259fcef21beab143d54781b695c512b567c5f1bef27d11a329de9ba83145a03e5684208d7dde30c55639b09c1bbb55b6
7
- data.tar.gz: 266ba89a88b2df74e1fa75f33bd9651fb27bb012d5707ac41567fbcbc3cded3cd97e4536d45170c1140ddef0ea9bd35ad2a4d1d05f15e83f22c0d4abf8f4620c
6
+ metadata.gz: be79b067b838f8541dc176f82ba86dab9d4719354d8c500ed93f50bafc14e0eeeb9564e528c85fa619116d1b2274de0c217d7ab4ae81d2e6a9549f3eea3ead6c
7
+ data.tar.gz: 09c668f2d08663000b284c91d1b1c77fea8109fc84b392143035fb39f9cca3f9ed6707084a8d0b3308d133384dfa7fc3fc517dc39d928b77f03d727599b2fccc
data/README.md CHANGED
@@ -124,7 +124,7 @@ def original_attribute(column_name)
124
124
  value = mapped_row[column_name]
125
125
 
126
126
  # 2. Clean or format each cell
127
- value = self.class.format_cell(value)
127
+ value = self.class.format_cell(cell, column_name, column_index)
128
128
 
129
129
  if value.present?
130
130
  # 3a. Parse the cell value (which does nothing if no parsing is specified)
@@ -428,4 +428,82 @@ class ImportFile < CsvRowModel::Import::File
428
428
  ...
429
429
  end
430
430
  end
431
+ ```
432
+
433
+ ## Dynamic columns
434
+ Dynamic columns are columns that can expand to many columns. Currently, we can only one dynamic column after all other standard columns.
435
+ The following:
436
+
437
+ ```ruby
438
+ class DynamicColumnModel
439
+ include CsvRowModel::Model
440
+
441
+ column :first_name
442
+ column :last_name
443
+ dynamic_column :skills
444
+ end
445
+ ```
446
+
447
+ represents this table:
448
+
449
+ | first_name | last_name | skill1 | skill2 |
450
+ | ---------- |----------- | ------ | ------ |
451
+ | John | Doe | No | Yes |
452
+ | Mario | Super | Yes | No |
453
+ | Mike | Jackson | Yes | Yes |
454
+
455
+
456
+ ### Export
457
+ Dynamic column attributes are arrays, but each item in the array is defined via singular attribute method like
458
+ normal columns:
459
+
460
+ ```ruby
461
+ class DynamicColumnExportModel < DynamicColumnModel
462
+ include CsvRowModel::Export
463
+
464
+ def skill(skill_name)
465
+ # below is an override, this is the default implementation: skill_name # => "skill1", then "skill2"
466
+ source_model.skills.include?(skill_name) ? "Yes" : "No"
467
+ end
468
+
469
+ class << self
470
+ # this is an override with the default implementation
471
+ def skill_header(skill_name)
472
+ skill_name
473
+ end
474
+ end
475
+ end
476
+
477
+ # the `skills` context is mapped to generate an array
478
+ export_file = CsvRowModel::Export::File.new(DynamicColumnExportModel, { skills: Skill.all })
479
+ export_file.generate do |csv|
480
+ User.all.each { |user| csv << user }
481
+ end
482
+ ```
483
+
484
+ ### Import
485
+ Like Export above, each item of the array is defined via singular attribute method like
486
+ normal columns:
487
+
488
+ ```ruby
489
+ class DynamicColumnImportModel < DynamicColumnModel
490
+ include CsvRowModel::Import
491
+
492
+ # this is an override with the default implementation (override highly recommended)
493
+ def skill(value, skill_name)
494
+ value
495
+ end
496
+
497
+ class << self
498
+ # Clean/format every dynamic_column attribute array
499
+ #
500
+ # this is an override with the default implementation
501
+ def format_dynamic_column_cells(cells, column_name)
502
+ cells
503
+ end
504
+ end
505
+ end
506
+ row_model = CsvRowModel::Import::File.new(file_path, DynamicColumnImportModel).next
507
+ row_model.attributes # => { first_name: "John", last_name: "Doe", skills: ['No', 'Yes'] }
508
+ row_model.skills # => ['No', 'Yes']
431
509
  ```
@@ -14,7 +14,7 @@ module CsvRowModel
14
14
 
15
15
  # @param included_module [Module] module to search for
16
16
  # @return [Array<Module>] inherited_ancestors of included_module (including self)
17
- def inherited_ancestors(included_module=deep_class_module)
17
+ def inherited_ancestors(included_module=inherited_class_module)
18
18
  included_model_index = ancestors.index(included_module)
19
19
  included_model_index == 0 ? [included_module] : ancestors[0..(included_model_index - 1)]
20
20
  end
@@ -43,7 +43,7 @@ module CsvRowModel
43
43
  # @param variable_name [Symbol] class variable name (recommend :@_variable_name)
44
44
  # @param default_value [Object] default value of the class variable
45
45
  # @param merge_method [Symbol] method to merge values of the class variable
46
- # @return [Object] a class variable merged across ancestors until deep_class_module
46
+ # @return [Object] a class variable merged across ancestors until inherited_class_module
47
47
  def inherited_class_var(variable_name, default_value, merge_method)
48
48
  class_cache(variable_name) do
49
49
  value = default_value
@@ -1,21 +1,15 @@
1
+ require 'csv_row_model/export/dynamic_columns'
2
+
1
3
  module CsvRowModel
2
4
  # Include this to with {Model} to have a RowModel for exporting to CSVs.
3
5
  module Export
4
6
  extend ActiveSupport::Concern
5
7
 
6
8
  included do
9
+ include DynamicColumns
7
10
  attr_reader :source_model, :context
8
11
 
9
- self.column_names.each do |column_name|
10
-
11
- # Safe to override
12
- #
13
- #
14
- # @return [String] a string of public_send(column_name) of the CSV model
15
- define_method(column_name) do
16
- source_model.public_send(column_name)
17
- end
18
- end
12
+ self.column_names.each { |*args| define_attribute_method(*args) }
19
13
 
20
14
  validates :source_model, presence: true
21
15
  end
@@ -24,7 +18,7 @@ module CsvRowModel
24
18
  # @param [Hash] context
25
19
  def initialize(source_model, context={})
26
20
  @source_model = source_model
27
- @context = OpenStruct.new(context)
21
+ @context = OpenStruct.new(context)
28
22
  end
29
23
 
30
24
  def to_rows
@@ -37,8 +31,29 @@ module CsvRowModel
37
31
  end
38
32
 
39
33
  class_methods do
40
- def setup(csv, with_headers: true)
41
- csv << headers if with_headers
34
+ def setup(csv, context={}, with_headers: true)
35
+ csv << headers(context) if with_headers
36
+ end
37
+
38
+ # See {Model#column}
39
+ def column(column_name, options={})
40
+ super
41
+ define_attribute_method(column_name)
42
+ end
43
+
44
+ # Define default attribute method for a column
45
+ # @param column_name [Symbol] the cell's column_name
46
+ def define_attribute_method(column_name)
47
+ define_method(column_name) do
48
+ self.class.format_cell(source_model.public_send(column_name), column_name, self.class.index(column_name))
49
+ end
50
+ end
51
+
52
+ # Safe to override. Method applied to each cell by default
53
+ #
54
+ # @param cell [Object] the cell's value
55
+ def format_cell(cell, column_name, column_index)
56
+ cell
42
57
  end
43
58
  end
44
59
  end
@@ -0,0 +1,42 @@
1
+ module CsvRowModel
2
+ module Export
3
+ module DynamicColumns
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ self.dynamic_column_names.each { |*args| define_dynamic_attribute_method(*args) }
8
+ end
9
+
10
+ # @return [Array] an array of public_send(column_name) of the CSV model
11
+ def to_row
12
+ super.flatten
13
+ end
14
+
15
+ class_methods do
16
+ protected
17
+
18
+ # See {Model::DynamicColumns#dynamic_column}
19
+ def dynamic_column(column_name, options={})
20
+ super
21
+ define_dynamic_attribute_method(column_name)
22
+ end
23
+
24
+ # Define default attribute method for a dynamic_column
25
+ # @param column_name [Symbol] the cell's column_name
26
+ def define_dynamic_attribute_method(column_name)
27
+ define_method(column_name) do
28
+ context.public_send(column_name).map do |header_model|
29
+ self.class.format_cell(
30
+ public_send(self.class.singular_dynamic_attribute_method_name(column_name), header_model),
31
+ column_name,
32
+ self.class.dynamic_index(column_name)
33
+ )
34
+ end
35
+ end
36
+
37
+ define_method(singular_dynamic_attribute_method_name(column_name)) { |header_model| header_model }
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -34,7 +34,7 @@ module CsvRowModel
34
34
  @file = Tempfile.new([export_model_class.name, ".csv"])
35
35
  CSV.open(file.path, "wb") do |csv|
36
36
  @csv = csv
37
- export_model_class.setup(csv, with_headers: with_headers)
37
+ export_model_class.setup(csv, context, with_headers: with_headers)
38
38
  yield self
39
39
  end
40
40
  ensure
@@ -31,7 +31,7 @@ module CsvRowModel
31
31
  end
32
32
 
33
33
  class_methods do
34
- def setup(csv, with_headers: true); end
34
+ def setup(csv, context, with_headers: true); end
35
35
  end
36
36
  end
37
37
  end
@@ -1,5 +1,6 @@
1
1
  require 'csv_row_model/import/attributes'
2
2
  require 'csv_row_model/import/presenter'
3
+ require 'csv_row_model/import/dynamic_columns'
3
4
 
4
5
  module CsvRowModel
5
6
  # Include this to with {Model} to have a RowModel for importing csvs.
@@ -9,6 +10,7 @@ module CsvRowModel
9
10
  included do
10
11
  include Concerns::Inspect
11
12
  include Attributes
13
+ include DynamicColumns
12
14
 
13
15
  attr_reader :attr_reader, :source_header, :source_row, :context, :index, :previous
14
16
 
@@ -54,12 +56,15 @@ module CsvRowModel
54
56
  @csv_string_model ||= begin
55
57
  if source_row
56
58
  column_names = self.class.column_names
57
- hash = column_names.zip(column_names.map.with_index do |column_name, index|
58
- self.class.format_cell(source_row[index], column_name, index)
59
- end).to_h
59
+ hash = column_names.zip(
60
+ column_names.map.with_index do |column_name, index|
61
+ self.class.format_cell(source_row[index], column_name, index)
62
+ end
63
+ ).to_h
60
64
  else
61
65
  hash = {}
62
66
  end
67
+
63
68
  self.class.csv_string_model_class.new(hash)
64
69
  end
65
70
  end
@@ -88,7 +93,7 @@ module CsvRowModel
88
93
  end
89
94
 
90
95
  if using_warnings?
91
- csv_string_model.using_warnings &proc
96
+ csv_string_model.using_warnings(&proc)
92
97
  else
93
98
  proc.call
94
99
  end
@@ -105,13 +110,17 @@ module CsvRowModel
105
110
  # @param [Hash] context extra data you want to work with the model
106
111
  # @param [Import] prevuous the previous row model
107
112
  # @return [Import] the next model instance from the csv
108
- def next(csv, context={}, previous=nil)
113
+ def next(csv, source_header, context={}, previous=nil)
109
114
  csv.skip_header
110
115
  row_model = nil
111
116
 
112
117
  loop do # loop until the next parent or end_of_file? (need to read children rows)
113
118
  csv.read_row
114
- row_model ||= new(csv.current_row, index: csv.index, context: context, previous: previous)
119
+ row_model ||= new(csv.current_row,
120
+ index: csv.index,
121
+ source_header: source_header,
122
+ context: context,
123
+ previous: previous)
115
124
 
116
125
  return row_model if csv.end_of_file?
117
126
 
@@ -132,7 +141,7 @@ module CsvRowModel
132
141
 
133
142
  # Call to define the presenter
134
143
  def presenter(&block)
135
- presenter_class.class_eval &block
144
+ presenter_class.class_eval(&block)
136
145
  end
137
146
  end
138
147
  end
@@ -26,10 +26,7 @@ module CsvRowModel
26
26
 
27
27
  # @return [Object] the column's attribute before override
28
28
  def original_attribute(column_name)
29
- @original_attributes ||= {}
30
- @default_changes ||= {}
31
-
32
- return @original_attributes[column_name] if @original_attributes.has_key? column_name
29
+ return @original_attributes[column_name] if original_attribute_memoized? column_name
33
30
 
34
31
  csv_string_model.valid?
35
32
  return nil unless csv_string_model.errors[column_name].blank?
@@ -51,6 +48,13 @@ module CsvRowModel
51
48
  @default_changes
52
49
  end
53
50
 
51
+ protected
52
+ def original_attribute_memoized?(column_name)
53
+ @original_attributes ||= {}
54
+ @default_changes ||= {}
55
+ @original_attributes.has_key? column_name
56
+ end
57
+
54
58
  class_methods do
55
59
  # Safe to override. Method applied to each cell by default
56
60
  #
@@ -103,4 +107,4 @@ module CsvRowModel
103
107
  end
104
108
  end
105
109
  end
106
- end
110
+ end
@@ -0,0 +1,71 @@
1
+ module CsvRowModel
2
+ module Import
3
+ module DynamicColumns
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ self.dynamic_column_names.each { |*args| define_dynamic_attribute_method(*args) }
8
+ end
9
+
10
+ # @return [Array] dynamic_column headers
11
+ def dynamic_source_headers
12
+ source_header[self.class.columns.size..-1]
13
+ end
14
+
15
+ # @return [Array] dynamic_column row data
16
+ def dynamic_source_row
17
+ source_row[self.class.columns.size..-1]
18
+ end
19
+
20
+ # @return [Hash] a map of `column_name => original_attribute(column_name)`
21
+ def original_attributes
22
+ super
23
+ self.class.dynamic_column_names.each { |column_name| original_attribute(column_name) }
24
+ @original_attributes
25
+ end
26
+
27
+ # @return [Object] the column's attribute before override
28
+ def original_attribute(column_name)
29
+ return super if self.class.column_names.include? column_name
30
+ return unless self.class.dynamic_column_names.include? column_name
31
+ return @original_attributes[column_name] if original_attribute_memoized? column_name
32
+
33
+ values = dynamic_source_headers.map.with_index do |source_header, index|
34
+ value = self.class.format_cell(
35
+ dynamic_source_row[index],
36
+ source_header,
37
+ self.class.dynamic_index(column_name)
38
+ )
39
+ public_send(self.class.singular_dynamic_attribute_method_name(column_name), value, source_header)
40
+ end
41
+
42
+ @original_attributes[column_name] = self.class.format_dynamic_column_cells(values, column_name)
43
+ end
44
+
45
+ class_methods do
46
+ # Safe to override. Method applied to each dynamic_column attribute
47
+ #
48
+ # @param cells [Array] Array of values
49
+ # @param column_name [Symbol] Dynamic column name
50
+ def format_dynamic_column_cells(cells, column_name)
51
+ cells
52
+ end
53
+
54
+ protected
55
+
56
+ # See {Model#dynamic_column}
57
+ def dynamic_column(column_name, options={})
58
+ super
59
+ define_dynamic_attribute_method(column_name)
60
+ end
61
+
62
+ # Define default attribute method for a column
63
+ # @param column_name [Symbol] the cell's column_name
64
+ def define_dynamic_attribute_method(column_name)
65
+ define_method(column_name) { original_attribute(column_name) }
66
+ define_method(singular_dynamic_attribute_method_name(column_name)) { |value, source_header| value }
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -47,7 +47,7 @@ module CsvRowModel
47
47
  run_callbacks :next do
48
48
  context = context.to_h.reverse_merge(self.context)
49
49
  @previous_row_model = current_row_model
50
- @current_row_model = row_model_class.next(csv, context, previous_row_model)
50
+ @current_row_model = row_model_class.next(csv, header, context, previous_row_model)
51
51
  @index += 1
52
52
  @current_row_model = @index = nil if end_of_file?
53
53
  end
@@ -28,7 +28,7 @@ module CsvRowModel
28
28
  end
29
29
  end
30
30
 
31
- def next(csv, context={}, previous=nil)
31
+ def next(csv, source_header, context={}, previous=nil)
32
32
  return csv.read_row unless csv.next_row
33
33
 
34
34
  source_row = Array.new(header_matchers.size)
@@ -44,7 +44,7 @@ module CsvRowModel
44
44
  end
45
45
  end
46
46
 
47
- new(source_row, context: context, previous: previous)
47
+ new(source_row, source_header: source_header, context: context, previous: previous)
48
48
  end
49
49
  end
50
50
  end
@@ -63,10 +63,16 @@ module CsvRowModel
63
63
  errors.messages.reverse_merge!(row_model.errors.messages)
64
64
  end
65
65
 
66
+ # @param [Array] Array of column_names to check
67
+ # @return [Boolean] if column_names are valid
68
+ def row_model_valid?(*column_names)
69
+ row_model.valid? || (row_model.errors.keys & column_names).empty?
70
+ end
71
+
66
72
  # @param [Symbol] attribute_name the attribute to check
67
73
  # @return [Boolean] if the dependencies are valid
68
74
  def valid_dependencies?(attribute_name)
69
- row_model.valid? || (row_model.errors.keys & self.class.options(attribute_name)[:dependencies]).empty?
75
+ row_model_valid?(*self.class.options(attribute_name)[:dependencies])
70
76
  end
71
77
 
72
78
  # equal to: @method_name ||= yield
@@ -78,7 +84,7 @@ module CsvRowModel
78
84
  end
79
85
 
80
86
  class << self
81
- def deep_class_module
87
+ def inherited_class_module
82
88
  Presenter
83
89
  end
84
90
 
@@ -163,4 +169,4 @@ module CsvRowModel
163
169
  end
164
170
  end
165
171
  end
166
- end
172
+ end
@@ -2,6 +2,7 @@ require 'csv_row_model/model/csv_string_model'
2
2
 
3
3
  require 'csv_row_model/model/columns'
4
4
  require 'csv_row_model/model/children'
5
+ require 'csv_row_model/model/dynamic_columns'
5
6
 
6
7
  module CsvRowModel
7
8
  # Base module for representing a RowModel---a model that represents row(s).
@@ -16,6 +17,7 @@ module CsvRowModel
16
17
 
17
18
  include Columns
18
19
  include Children
20
+ include DynamicColumns
19
21
 
20
22
  # @return [Model] return the parent, if this instance is a child
21
23
  attr_reader :parent
@@ -57,10 +59,10 @@ module CsvRowModel
57
59
  protected
58
60
  # Called to add validations to the csv_string_model_class
59
61
  def csv_string_model(&block)
60
- csv_string_model_class.class_eval &block
62
+ csv_string_model_class.class_eval(&block)
61
63
  end
62
64
 
63
- def deep_class_module
65
+ def inherited_class_module
64
66
  Model
65
67
  end
66
68
  end
@@ -5,15 +5,24 @@ module CsvRowModel
5
5
 
6
6
  # @return [Hash] a map of `column_name => public_send(column_name)`
7
7
  def attributes
8
- self.class.column_names
9
- .zip(self.class.column_names.map { |column_name| public_send(column_name) })
10
- .to_h
8
+ attributes_from_column_names self.class.column_names
11
9
  end
12
10
 
13
11
  def to_json
14
12
  attributes.to_json
15
13
  end
16
14
 
15
+ def headers
16
+ self.class.headers(context)
17
+ end
18
+
19
+ protected
20
+ def attributes_from_column_names(column_names)
21
+ column_names
22
+ .zip(column_names.map { |column_name| public_send(column_name) })
23
+ .to_h
24
+ end
25
+
17
26
  class_methods do
18
27
  # @return [Array<Symbol>] column names for the row model
19
28
  def column_names
@@ -43,14 +52,10 @@ module CsvRowModel
43
52
  column_name.is_a?(Symbol) && index(column_name)
44
53
  end
45
54
 
46
-
55
+ # @param [Hash, OpenStruct] context name of column to check
47
56
  # @return [Array] column headers for the row model
48
- def headers
49
- @headers ||= begin
50
- columns.map do |name, options|
51
- options[:header] || format_header(name)
52
- end
53
- end
57
+ def headers(context={})
58
+ @headers ||= columns.map { |name, options| options[:header] || format_header(name) }
54
59
  end
55
60
 
56
61
  # Safe to override
@@ -93,4 +98,4 @@ module CsvRowModel
93
98
  end
94
99
  end
95
100
  end
96
- end
101
+ end
@@ -0,0 +1,74 @@
1
+ module CsvRowModel
2
+ module Model
3
+ module DynamicColumns
4
+ extend ActiveSupport::Concern
5
+
6
+ # See Model::Columns#attributes
7
+ def attributes
8
+ super.merge(attributes_from_column_names(self.class.dynamic_column_names))
9
+ end
10
+
11
+ class_methods do
12
+ # See Model::Columns::headers
13
+ def headers(context={})
14
+ @headers ||= super + dynamic_column_names.map do |column_name|
15
+ OpenStruct.new(context).public_send(column_name).each do |header_model|
16
+ public_send(header_method_name(column_name), header_model)
17
+ end
18
+ end.flatten
19
+ end
20
+
21
+ # @return [Integer] index of dynamic_column of all columns
22
+ def dynamic_index(column_name)
23
+ offset = dynamic_column_names.index(column_name)
24
+ offset ? columns.size + offset : nil
25
+ end
26
+
27
+ # @return [Array<Symbol>] column names for the row model
28
+ def dynamic_column_names
29
+ dynamic_columns.keys
30
+ end
31
+
32
+ # @return [Hash] column names mapped to their options
33
+ def dynamic_columns
34
+ inherited_class_var(:@_dynamic_columns, {}, :merge)
35
+ end
36
+
37
+ def header_method_name(column_name)
38
+ "#{column_name.to_s.singularize}_header"
39
+ end
40
+ def singular_dynamic_attribute_method_name(column_name)
41
+ column_name.to_s.singularize
42
+ end
43
+
44
+ protected
45
+
46
+ def merge_dynamic_columns(column_hash)
47
+ @_dynamic_columns ||= {}
48
+ deep_clear_class_cache(:@_dynamic_columns)
49
+ @_dynamic_columns.merge!(column_hash)
50
+ end
51
+
52
+ VALID_OPTIONS_KEYS = [].freeze
53
+
54
+ # define a dynamic_column, must be after all normal columns
55
+ #
56
+ # options to be implemented later
57
+ #
58
+ # @param column_name [Symbol] column_name
59
+ def dynamic_column(column_name, options={})
60
+ extra_keys = options.keys - VALID_OPTIONS_KEYS
61
+ raise ArgumentError.new("invalid options #{extra_keys}") unless extra_keys.empty?
62
+
63
+ define_header_method(column_name)
64
+
65
+ merge_dynamic_columns(column_name.to_sym => options)
66
+ end
67
+
68
+ def define_header_method(column_name)
69
+ define_singleton_method(header_method_name(column_name)) { |header_model| header_model }
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -1,3 +1,3 @@
1
1
  module CsvRowModel
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: csv_row_model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Chung
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-10-20 00:00:00.000000000 Z
11
+ date: 2015-10-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -64,12 +64,14 @@ files:
64
64
  - lib/csv_row_model/concerns/inspect.rb
65
65
  - lib/csv_row_model/engine.rb
66
66
  - lib/csv_row_model/export.rb
67
+ - lib/csv_row_model/export/dynamic_columns.rb
67
68
  - lib/csv_row_model/export/file.rb
68
69
  - lib/csv_row_model/export/file_model.rb
69
70
  - lib/csv_row_model/import.rb
70
71
  - lib/csv_row_model/import/attributes.rb
71
72
  - lib/csv_row_model/import/csv.rb
72
73
  - lib/csv_row_model/import/csv/row.rb
74
+ - lib/csv_row_model/import/dynamic_columns.rb
73
75
  - lib/csv_row_model/import/file.rb
74
76
  - lib/csv_row_model/import/file/callbacks.rb
75
77
  - lib/csv_row_model/import/file/validations.rb
@@ -79,6 +81,7 @@ files:
79
81
  - lib/csv_row_model/model/children.rb
80
82
  - lib/csv_row_model/model/columns.rb
81
83
  - lib/csv_row_model/model/csv_string_model.rb
84
+ - lib/csv_row_model/model/dynamic_columns.rb
82
85
  - lib/csv_row_model/model/file_model.rb
83
86
  - lib/csv_row_model/validators/boolean_format.rb
84
87
  - lib/csv_row_model/validators/date_format.rb
@@ -108,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
111
  version: '0'
109
112
  requirements: []
110
113
  rubyforge_project:
111
- rubygems_version: 2.4.5
114
+ rubygems_version: 2.4.6
112
115
  signing_key:
113
116
  specification_version: 4
114
117
  summary: Import and export your custom CSVs with a intuitive shared Ruby interface.