csv_row_model 0.1.1 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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.