csv_row_model 0.4.1 → 1.0.0.beta1
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/README.md +162 -162
- data/csv_row_model.gemspec +2 -1
- data/lib/csv_row_model/concerns/{invalid_options.rb → check_options.rb} +4 -6
- data/lib/csv_row_model/export/attributes.rb +11 -20
- data/lib/csv_row_model/export/base.rb +3 -3
- data/lib/csv_row_model/export/cell.rb +24 -0
- data/lib/csv_row_model/export/dynamic_column_cell.rb +29 -0
- data/lib/csv_row_model/export/dynamic_columns.rb +11 -13
- data/lib/csv_row_model/export/file.rb +7 -7
- data/lib/csv_row_model/export/file_model.rb +2 -2
- data/lib/csv_row_model/export.rb +0 -3
- data/lib/csv_row_model/import/attributes.rb +18 -81
- data/lib/csv_row_model/import/base.rb +26 -69
- data/lib/csv_row_model/import/cell.rb +77 -0
- data/lib/csv_row_model/import/csv.rb +23 -60
- data/lib/csv_row_model/import/csv_string_model.rb +65 -0
- data/lib/csv_row_model/import/dynamic_column_cell.rb +37 -0
- data/lib/csv_row_model/import/dynamic_columns.rb +20 -37
- data/lib/csv_row_model/import/file/validations.rb +5 -1
- data/lib/csv_row_model/import/file.rb +8 -3
- data/lib/csv_row_model/import/file_model.rb +5 -4
- data/lib/csv_row_model/import/representation.rb +60 -0
- data/lib/csv_row_model/import/represents.rb +85 -0
- data/lib/csv_row_model/import.rb +4 -3
- data/lib/csv_row_model/model/base.rb +5 -15
- data/lib/csv_row_model/model/children.rb +2 -1
- data/lib/csv_row_model/model/columns.rb +19 -16
- data/lib/csv_row_model/model/comparison.rb +1 -1
- data/lib/csv_row_model/model/dynamic_column_cell.rb +44 -0
- data/lib/csv_row_model/model/dynamic_columns.rb +26 -11
- data/lib/csv_row_model/model.rb +4 -3
- data/lib/csv_row_model/version.rb +1 -1
- data/lib/csv_row_model.rb +3 -1
- metadata +29 -10
- data/lib/csv_row_model/concerns/inherited_class_var.rb +0 -121
- data/lib/csv_row_model/import/presenter.rb +0 -153
- data/lib/csv_row_model/model/csv_string_model.rb +0 -7
data/lib/csv_row_model.rb
CHANGED
@@ -10,11 +10,13 @@ require 'active_support/all'
|
|
10
10
|
require 'active_warnings'
|
11
11
|
require 'csv'
|
12
12
|
|
13
|
+
require 'inherited_class_var'
|
14
|
+
|
13
15
|
if autoload && defined?(Rails)
|
14
16
|
require 'csv_row_model/engine'
|
15
17
|
else
|
16
18
|
require 'csv_row_model/concerns/inspect'
|
17
|
-
require 'csv_row_model/concerns/
|
19
|
+
require 'csv_row_model/concerns/check_options'
|
18
20
|
|
19
21
|
require 'csv_row_model/validators/validate_attributes'
|
20
22
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: csv_row_model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Chung
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-06-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activemodel
|
@@ -29,16 +29,30 @@ dependencies:
|
|
29
29
|
name: active_warnings
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- - "
|
32
|
+
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: 0.1.2
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- - "
|
39
|
+
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: 0.1.2
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: inherited_class_var
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: 0.2.2
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 0.2.2
|
42
56
|
description:
|
43
57
|
email:
|
44
58
|
- hello@stevenchung.ca
|
@@ -60,32 +74,37 @@ files:
|
|
60
74
|
- bin/setup
|
61
75
|
- csv_row_model.gemspec
|
62
76
|
- lib/csv_row_model.rb
|
63
|
-
- lib/csv_row_model/concerns/
|
77
|
+
- lib/csv_row_model/concerns/check_options.rb
|
64
78
|
- lib/csv_row_model/concerns/inspect.rb
|
65
|
-
- lib/csv_row_model/concerns/invalid_options.rb
|
66
79
|
- lib/csv_row_model/engine.rb
|
67
80
|
- lib/csv_row_model/export.rb
|
68
81
|
- lib/csv_row_model/export/attributes.rb
|
69
82
|
- lib/csv_row_model/export/base.rb
|
83
|
+
- lib/csv_row_model/export/cell.rb
|
84
|
+
- lib/csv_row_model/export/dynamic_column_cell.rb
|
70
85
|
- lib/csv_row_model/export/dynamic_columns.rb
|
71
86
|
- lib/csv_row_model/export/file.rb
|
72
87
|
- lib/csv_row_model/export/file_model.rb
|
73
88
|
- lib/csv_row_model/import.rb
|
74
89
|
- lib/csv_row_model/import/attributes.rb
|
75
90
|
- lib/csv_row_model/import/base.rb
|
91
|
+
- lib/csv_row_model/import/cell.rb
|
76
92
|
- lib/csv_row_model/import/csv.rb
|
93
|
+
- lib/csv_row_model/import/csv_string_model.rb
|
94
|
+
- lib/csv_row_model/import/dynamic_column_cell.rb
|
77
95
|
- lib/csv_row_model/import/dynamic_columns.rb
|
78
96
|
- lib/csv_row_model/import/file.rb
|
79
97
|
- lib/csv_row_model/import/file/callbacks.rb
|
80
98
|
- lib/csv_row_model/import/file/validations.rb
|
81
99
|
- lib/csv_row_model/import/file_model.rb
|
82
|
-
- lib/csv_row_model/import/
|
100
|
+
- lib/csv_row_model/import/representation.rb
|
101
|
+
- lib/csv_row_model/import/represents.rb
|
83
102
|
- lib/csv_row_model/model.rb
|
84
103
|
- lib/csv_row_model/model/base.rb
|
85
104
|
- lib/csv_row_model/model/children.rb
|
86
105
|
- lib/csv_row_model/model/columns.rb
|
87
106
|
- lib/csv_row_model/model/comparison.rb
|
88
|
-
- lib/csv_row_model/model/
|
107
|
+
- lib/csv_row_model/model/dynamic_column_cell.rb
|
89
108
|
- lib/csv_row_model/model/dynamic_columns.rb
|
90
109
|
- lib/csv_row_model/model/file_model.rb
|
91
110
|
- lib/csv_row_model/validators/boolean_format.rb
|
@@ -112,9 +131,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
112
131
|
version: '0'
|
113
132
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
133
|
requirements:
|
115
|
-
- - "
|
134
|
+
- - ">"
|
116
135
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
136
|
+
version: 1.3.1
|
118
137
|
requirements: []
|
119
138
|
rubyforge_project:
|
120
139
|
rubygems_version: 2.5.1
|
@@ -1,121 +0,0 @@
|
|
1
|
-
require 'csv_row_model/concerns/invalid_options'
|
2
|
-
|
3
|
-
module CsvRowModel
|
4
|
-
module Concerns
|
5
|
-
module InheritedClassVar
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
include InvalidOptions
|
8
|
-
|
9
|
-
class_methods do
|
10
|
-
# Clears the cache for a variable
|
11
|
-
# @param variable_name [Symbol] variable_name to cache against
|
12
|
-
def clear_class_cache(variable_name)
|
13
|
-
instance_variable_set inherited_class_variable_name(variable_name), nil
|
14
|
-
end
|
15
|
-
|
16
|
-
protected
|
17
|
-
|
18
|
-
# @param variable_name [Symbol] class variable name
|
19
|
-
def inherited_class_hash(variable_name, options={})
|
20
|
-
options = check_and_merge_options(options, dependencies: [])
|
21
|
-
|
22
|
-
options[:dependencies].each do |dependency_name|
|
23
|
-
define_singleton_method dependency_name do
|
24
|
-
class_cache(hidden_variable_name(dependency_name)) do
|
25
|
-
send("_#{dependency_name}")
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
hidden_variable_name = hidden_variable_name(variable_name)
|
31
|
-
define_singleton_method variable_name do
|
32
|
-
inherited_class_var(hidden_variable_name, {}, :merge)
|
33
|
-
end
|
34
|
-
define_singleton_method "merge_#{variable_name}" do |merge_value|
|
35
|
-
value = instance_variable_get(hidden_variable_name) || instance_variable_set(hidden_variable_name, {})
|
36
|
-
|
37
|
-
deep_clear_class_cache(hidden_variable_name)
|
38
|
-
options[:dependencies].each {|dependency_name| deep_clear_class_cache(hidden_variable_name(dependency_name)) }
|
39
|
-
|
40
|
-
value.merge!(merge_value)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# @param variable_name [Symbol] class variable name based on
|
45
|
-
# @return [Symbol] the hidden variable name for class_cache
|
46
|
-
def hidden_variable_name(variable_name)
|
47
|
-
"@_#{variable_name}".to_sym
|
48
|
-
end
|
49
|
-
|
50
|
-
# @param included_module [Module] module to search for
|
51
|
-
# @return [Array<Module>] inherited_ancestors of included_module (including self)
|
52
|
-
def inherited_ancestors(included_module=CsvRowModel::Concerns::InheritedClassVar)
|
53
|
-
included_model_index = ancestors.index(included_module)
|
54
|
-
included_model_index == 0 ? [included_module] : ancestors[0..(included_model_index - 1)]
|
55
|
-
end
|
56
|
-
|
57
|
-
# @param accessor_method_name [Symbol] method to access the inherited_custom_class
|
58
|
-
# @param base_parent_class [Class] class that the custom class inherits from if there's no parent
|
59
|
-
# @return [Class] a custom class with the inheritance following self. for example:
|
60
|
-
#
|
61
|
-
# grandparent -> parent -> self
|
62
|
-
#
|
63
|
-
# grandparent has inherited_custom_class, but parent, doesn't.
|
64
|
-
#
|
65
|
-
# then: base_parent_class -> grandparent::inherited_custom_class -> self::inherited_custom_class
|
66
|
-
def inherited_custom_class(accessor_method_name, base_parent_class)
|
67
|
-
parent_class = inherited_ancestors[1..-1].find do |klass|
|
68
|
-
klass.respond_to?(accessor_method_name)
|
69
|
-
end.try(accessor_method_name)
|
70
|
-
parent_class ||= base_parent_class
|
71
|
-
|
72
|
-
klass = Class.new(parent_class)
|
73
|
-
# how else can i get the current scopes name...
|
74
|
-
klass.send(:define_singleton_method, :name, &eval("-> { \"#{name}#{base_parent_class.name.demodulize}\" }"))
|
75
|
-
klass
|
76
|
-
end
|
77
|
-
|
78
|
-
# @param variable_name [Symbol] class variable name (recommend :@_variable_name)
|
79
|
-
# @param default_value [Object] default value of the class variable
|
80
|
-
# @param merge_method [Symbol] method to merge values of the class variable
|
81
|
-
# @return [Object] a class variable merged across ancestors until inherited_class_module
|
82
|
-
def inherited_class_var(variable_name, default_value, merge_method)
|
83
|
-
class_cache(variable_name) do
|
84
|
-
value = default_value
|
85
|
-
|
86
|
-
inherited_ancestors.each do |ancestor|
|
87
|
-
ancestor_value = ancestor.instance_variable_get(variable_name)
|
88
|
-
value = ancestor_value.public_send(merge_method, value) if ancestor_value.present?
|
89
|
-
end
|
90
|
-
|
91
|
-
value
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
# @param variable_name [Symbol] variable_name to cache against
|
96
|
-
# @return [String] the cache variable name for the cache
|
97
|
-
def inherited_class_variable_name(variable_name)
|
98
|
-
"#{variable_name}_inherited_class_cache"
|
99
|
-
end
|
100
|
-
|
101
|
-
# Clears the cache for a variable and the same variable for all it's dependant descendants
|
102
|
-
# @param variable_name [Symbol] variable_name to cache against
|
103
|
-
def deep_clear_class_cache(variable_name)
|
104
|
-
([self] + descendants).each do |descendant|
|
105
|
-
descendant.try(:clear_class_cache, variable_name)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
# Memozies a inherited_class_variable_name
|
110
|
-
# @param variable_name [Symbol] variable_name to cache against
|
111
|
-
def class_cache(variable_name)
|
112
|
-
#
|
113
|
-
# equal to: (has @)inherited_class_variable_name ||= yield
|
114
|
-
#
|
115
|
-
cache_variable_name = inherited_class_variable_name(variable_name)
|
116
|
-
instance_variable_get(cache_variable_name) || instance_variable_set(cache_variable_name, yield)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
@@ -1,153 +0,0 @@
|
|
1
|
-
module CsvRowModel
|
2
|
-
module Import
|
3
|
-
class Presenter
|
4
|
-
include Concerns::InheritedClassVar
|
5
|
-
include Concerns::Inspect
|
6
|
-
include ActiveWarnings
|
7
|
-
|
8
|
-
inherited_class_hash :attributes, dependencies: %i[dependencies]
|
9
|
-
|
10
|
-
attr_reader :row_model
|
11
|
-
|
12
|
-
delegate :context, to: :row_model
|
13
|
-
|
14
|
-
def initialize(row_model)
|
15
|
-
@row_model = row_model
|
16
|
-
end
|
17
|
-
|
18
|
-
# Safe to override.
|
19
|
-
#
|
20
|
-
# @return [Boolean] returns true, if this instance should be skipped
|
21
|
-
def skip?
|
22
|
-
!valid?
|
23
|
-
end
|
24
|
-
|
25
|
-
# Safe to override.
|
26
|
-
#
|
27
|
-
# @return [Boolean] returns true, if the entire csv file should stop reading
|
28
|
-
def abort?
|
29
|
-
false
|
30
|
-
end
|
31
|
-
|
32
|
-
def valid?(*args)
|
33
|
-
super
|
34
|
-
filter_errors
|
35
|
-
errors.empty?
|
36
|
-
end
|
37
|
-
|
38
|
-
# @return [Presenter] returns the presenter of the previous row_model
|
39
|
-
def previous
|
40
|
-
row_model.previous.try(:presenter)
|
41
|
-
end
|
42
|
-
|
43
|
-
def attributes
|
44
|
-
self.class.attribute_names
|
45
|
-
.zip(self.class.attribute_names.map { |attribute_name| public_send(attribute_name) })
|
46
|
-
.to_h
|
47
|
-
end
|
48
|
-
|
49
|
-
protected
|
50
|
-
|
51
|
-
# add errors from row_model and remove each dependent attribute from errors if it's row_model_dependencies
|
52
|
-
# are in the errors
|
53
|
-
def filter_errors
|
54
|
-
using_warnings? ? row_model.using_warnings { _filter_errors } : _filter_errors
|
55
|
-
end
|
56
|
-
|
57
|
-
def _filter_errors
|
58
|
-
row_model.valid?
|
59
|
-
self.class.attribute_names.each do |attribute_name|
|
60
|
-
next unless errors.messages[attribute_name] &&
|
61
|
-
row_model.errors.messages.slice(*self.class.options(attribute_name)[:dependencies]).present?
|
62
|
-
errors.delete attribute_name
|
63
|
-
end
|
64
|
-
|
65
|
-
errors.messages.reverse_merge!(row_model.errors.messages)
|
66
|
-
end
|
67
|
-
|
68
|
-
# @param [Array] Array of column_names to check
|
69
|
-
# @return [Boolean] if column_names are present
|
70
|
-
def row_model_present?(*column_names)
|
71
|
-
column_names.each { |column_name| return false if row_model.public_send(column_name).blank? }
|
72
|
-
true
|
73
|
-
end
|
74
|
-
|
75
|
-
# @param [Symbol] attribute_name the attribute to check
|
76
|
-
# @return [Boolean] if the dependencies are valid
|
77
|
-
def valid_dependencies?(attribute_name)
|
78
|
-
row_model_present?(*self.class.options(attribute_name)[:dependencies])
|
79
|
-
end
|
80
|
-
|
81
|
-
# equal to: @method_name ||= yield
|
82
|
-
# @param [Symbol] method_name method_name in description
|
83
|
-
# @return [Object] the memoized result
|
84
|
-
def memoize(method_name)
|
85
|
-
variable_name = "@#{method_name}"
|
86
|
-
instance_variable_get(variable_name) || instance_variable_set(variable_name, yield)
|
87
|
-
end
|
88
|
-
|
89
|
-
class << self
|
90
|
-
# @return [Array<Symbol>] attribute names for the Presenter
|
91
|
-
def attribute_names
|
92
|
-
attributes.keys
|
93
|
-
end
|
94
|
-
|
95
|
-
# @param [Symbol] attribute_name name of attribute to find option
|
96
|
-
# @return [Hash] options for the attribute_name
|
97
|
-
def options(attribute_name)
|
98
|
-
attributes[attribute_name].first
|
99
|
-
end
|
100
|
-
|
101
|
-
# @param [Symbol] attribute_name name of attribute to find block
|
102
|
-
# @return [Proc, Lambda] block called for attribute
|
103
|
-
def block(attribute_name)
|
104
|
-
attributes[attribute_name].last
|
105
|
-
end
|
106
|
-
|
107
|
-
protected
|
108
|
-
# @return [Hash{Symbol => Array}] map of `dependency => [array of presenter attributes dependent on dependency]`
|
109
|
-
def _dependencies
|
110
|
-
dependencies = {}
|
111
|
-
attribute_names.each do |attribute_name|
|
112
|
-
options(attribute_name)[:dependencies].each do |dependency|
|
113
|
-
dependencies[dependency] ||= []
|
114
|
-
dependencies[dependency] << attribute_name
|
115
|
-
end
|
116
|
-
end
|
117
|
-
dependencies
|
118
|
-
end
|
119
|
-
|
120
|
-
def inspect_methods
|
121
|
-
@inspect_methods ||= %i[row_model].freeze
|
122
|
-
end
|
123
|
-
|
124
|
-
# Adds column to the row model
|
125
|
-
#
|
126
|
-
# @param [Symbol] attribute_name name of attribute to add
|
127
|
-
# @param [Proc] block to calculate the attribute
|
128
|
-
# @param options [Hash]
|
129
|
-
# @option options [Hash] :memoize whether to memoize the attribute (default: true)
|
130
|
-
# @option options [Hash] :dependencies the dependcies it has with the underlying row_model (default: [])
|
131
|
-
def attribute(attribute_name, options={}, &block)
|
132
|
-
options = check_and_merge_options(options, memoize: true, dependencies: [])
|
133
|
-
|
134
|
-
merge_attributes(attribute_name.to_sym => [options, block])
|
135
|
-
define_attribute_method(attribute_name)
|
136
|
-
end
|
137
|
-
|
138
|
-
# Define the attribute_method
|
139
|
-
# @param [Symbol] attribute_name name of attribute to add
|
140
|
-
def define_attribute_method(attribute_name)
|
141
|
-
define_method("__#{attribute_name}", &block(attribute_name))
|
142
|
-
|
143
|
-
define_method(attribute_name) do
|
144
|
-
return unless valid_dependencies?(attribute_name)
|
145
|
-
self.class.options(attribute_name)[:memoize] ?
|
146
|
-
memoize(attribute_name) { public_send("__#{attribute_name}") } :
|
147
|
-
public_send("__#{attribute_name}")
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|