datashift 0.40.3 → 0.40.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +7 -2
- data/datashift.thor +28 -23
- data/lib/datashift.rb +6 -6
- data/lib/datashift/binder.rb +30 -11
- data/lib/datashift/configuration.rb +10 -2
- data/lib/datashift/core_ext/array.rb +7 -7
- data/lib/datashift/delimiters.rb +1 -1
- data/lib/datashift/doc_context.rb +1 -1
- data/lib/datashift/excel_base.rb +2 -2
- data/lib/datashift/exporters/csv_exporter.rb +0 -1
- data/lib/datashift/exporters/excel_exporter.rb +3 -4
- data/lib/datashift/file_definitions.rb +1 -3
- data/lib/datashift/inbound_data/method_binding.rb +5 -5
- data/lib/datashift/loaders/csv_loader.rb +2 -3
- data/lib/datashift/loaders/excel_loader.rb +8 -4
- data/lib/datashift/loaders/failure_data.rb +1 -3
- data/lib/datashift/loaders/loader_base.rb +2 -8
- data/lib/datashift/loaders/loader_factory.rb +6 -0
- data/lib/datashift/loaders/paperclip/attachment_loader.rb +1 -1
- data/lib/datashift/loaders/paperclip/datashift_paperclip.rb +2 -2
- data/lib/datashift/loaders/paperclip/image_loading.rb +2 -2
- data/lib/datashift/mapping/data_flow_schema.rb +40 -14
- data/lib/datashift/mapping/mapper_utils.rb +3 -3
- data/lib/datashift/model_methods/catalogue.rb +14 -14
- data/lib/datashift/model_methods/model_method.rb +5 -6
- data/lib/datashift/model_methods/operator.rb +1 -1
- data/lib/datashift/node_context.rb +2 -3
- data/lib/datashift/populators/has_many.rb +2 -2
- data/lib/datashift/populators/insistent_assignment.rb +4 -4
- data/lib/datashift/populators/populator.rb +21 -16
- data/lib/datashift/populators/populator_factory.rb +2 -4
- data/lib/datashift/querying.rb +4 -5
- data/lib/datashift/transformation/factory.rb +3 -3
- data/lib/datashift/version.rb +1 -1
- data/lib/generators/datashift/install_generator.rb +3 -3
- data/lib/generators/templates/datashift.rb +0 -4
- data/lib/tasks/config.thor +7 -9
- data/lib/tasks/export.thor +44 -45
- data/lib/tasks/generate.thor +43 -37
- data/lib/tasks/import.thor +20 -14
- data/lib/tasks/paperclip.thor +46 -48
- data/lib/tasks/thor_behaviour.rb +1 -1
- data/lib/tasks/to_convert_to_thor/db_tasks.rake +1 -3
- data/lib/tasks/tools.thor +37 -38
- metadata +45 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d7be9f9beb4237a952c953f59c0e887124a3222a
|
4
|
+
data.tar.gz: e68197e5dd89fa5a21165b9bd8e606e58650dfc7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d888089a643a05aedb27deabb01c814dc27940d1ef96475ebb320f6b71799629ae89797df740217569dc9a86f5abe8010ca4e6f5be5fb077b97594f5d49fed37
|
7
|
+
data.tar.gz: dfc8a6dca16c663df3b0ae8959de6382f0ff10feeadaeaa019e04083d37ccc3512fcedc4deee610f3115ceb43c6d6bef152a80e33f7afac5e76cd38d2b8f4a95
|
data/README.md
CHANGED
@@ -249,9 +249,14 @@ is to run our rail's install generator :
|
|
249
249
|
```ruby
|
250
250
|
rails g datashift:install
|
251
251
|
```
|
252
|
+
|
253
|
+
You can create a model specific file at anytime via
|
254
|
+
```bash
|
255
|
+
thor datashift:config:generate:import
|
256
|
+
```
|
252
257
|
|
253
|
-
To create
|
254
|
-
and see
|
258
|
+
To create a Rails tyle config block manually, create an initialisation file within `config/initializers`,
|
259
|
+
and see [lib/datashift/configuration.rb](lib/datashift/configuration.rb`) for details of all possible options, for example
|
255
260
|
|
256
261
|
```ruby
|
257
262
|
DataShift::Configuration.call do |c|
|
data/datashift.thor
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
# type applications, files and databases.
|
11
11
|
#
|
12
12
|
# Provides support for moving data between .xls (Excel/OpenOffice)
|
13
|
-
# Spreedsheets via Ruby and AR, enabling direct import/export of
|
13
|
+
# Spreedsheets via Ruby and AR, enabling direct import/export of
|
14
14
|
# ActiveRecord models with all their associations from database.
|
15
15
|
#
|
16
16
|
# Provides support for moving data between csv files and AR, enabling direct
|
@@ -18,14 +18,14 @@
|
|
18
18
|
#
|
19
19
|
require 'thor'
|
20
20
|
|
21
|
-
|
21
|
+
$LOAD_PATH.push File.expand_path('lib')
|
22
22
|
|
23
23
|
require 'datashift'
|
24
24
|
require 'factory_bot_rails'
|
25
25
|
require 'database_cleaner'
|
26
26
|
|
27
27
|
require_relative File.join('spec', 'support/sandbox')
|
28
|
-
require_relative File.join('spec'
|
28
|
+
require_relative File.join('spec', 'support/datashift_test_helpers')
|
29
29
|
|
30
30
|
module Datashift
|
31
31
|
|
@@ -33,7 +33,7 @@ module Datashift
|
|
33
33
|
|
34
34
|
include DataShift::TestHelpers
|
35
35
|
|
36
|
-
desc
|
36
|
+
desc 'lint', 'Run in spec - Verify that FactoryBot factories are valid'
|
37
37
|
|
38
38
|
def lint
|
39
39
|
|
@@ -44,7 +44,7 @@ module Datashift
|
|
44
44
|
begin
|
45
45
|
DatabaseCleaner.start
|
46
46
|
|
47
|
-
puts
|
47
|
+
puts 'Running FactoryBot.lint'
|
48
48
|
FactoryBot.lint
|
49
49
|
ensure
|
50
50
|
DatabaseCleaner.clean
|
@@ -52,36 +52,41 @@ module Datashift
|
|
52
52
|
|
53
53
|
end
|
54
54
|
|
55
|
-
|
56
|
-
desc "sandbox", 'Rebuild the dummy rails app in spec - required for testing'
|
55
|
+
desc 'sandbox', 'Rebuild the dummy rails app in spec - required for testing'
|
57
56
|
|
58
57
|
def sandbox
|
59
58
|
# Need an active record DB to test against, so we manage own Rails sandbox
|
60
59
|
DataShift::Sandbox.gen_rails_sandbox( :force )
|
61
60
|
end
|
62
61
|
|
63
|
-
desc
|
62
|
+
desc 'build', 'Build gem and install in one step'
|
64
63
|
|
65
|
-
method_option :bump, :
|
64
|
+
method_option :bump, aliases: '-b', type: :string, desc: 'Bump the version', required: false
|
66
65
|
|
67
|
-
method_option :push, :
|
66
|
+
method_option :push, aliases: '-p', desc: 'Push resulting gem to rubygems.org'
|
68
67
|
|
69
|
-
method_option :install, :
|
70
|
-
|
68
|
+
method_option :install, aliases: '-i',
|
69
|
+
desc: 'Install freshly built gem locally', type: :boolean, default: false
|
71
70
|
|
72
71
|
def build
|
73
72
|
|
74
|
-
|
75
|
-
|
73
|
+
if options[:push] && (options[:bump].blank? || options[:bump] !~ /^(\d+\.)?(\d+\.)?(\*|\d+)$/)
|
74
|
+
puts 'ERROR: Please bump to a new numeric version to push to rubygems'
|
75
|
+
exit(-1)
|
76
|
+
end
|
77
|
+
|
78
|
+
version = options[:bump] || DataShift::VERSION
|
76
79
|
|
77
80
|
# Bump the VERSION file in library
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
81
|
+
if options[:bump].present?
|
82
|
+
File.open( File.join('lib/datashift/version.rb'), 'w') do |f|
|
83
|
+
f << "module DataShift\n"
|
84
|
+
f << " VERSION = '#{version}'.freeze unless defined?(VERSION)\n"
|
85
|
+
f << "end\n"
|
86
|
+
end
|
87
|
+
end
|
83
88
|
|
84
|
-
build_cmd =
|
89
|
+
build_cmd = 'gem build datashift.gemspec'
|
85
90
|
|
86
91
|
puts "\n*** Running build cmd [#{build_cmd}]"
|
87
92
|
|
@@ -111,13 +116,13 @@ module Datashift
|
|
111
116
|
if File.exist?(env)
|
112
117
|
begin
|
113
118
|
require env
|
114
|
-
rescue => e
|
119
|
+
rescue StandardError => e
|
115
120
|
logger.error("Failed to initialise ActiveRecord : #{e.message}")
|
116
|
-
raise ConnectionError
|
121
|
+
raise ConnectionError, "Failed to initialise ActiveRecord : #{e.message}"
|
117
122
|
end
|
118
123
|
|
119
124
|
else
|
120
|
-
raise DataShift::PathError
|
125
|
+
raise DataShift::PathError, 'No config/environment.rb found - cannot initialise ActiveRecord'
|
121
126
|
end
|
122
127
|
end
|
123
128
|
end
|
data/lib/datashift.rb
CHANGED
@@ -47,7 +47,7 @@ module DataShift
|
|
47
47
|
|
48
48
|
def self.require_libraries
|
49
49
|
|
50
|
-
loader_libs = %w
|
50
|
+
loader_libs = %w[lib]
|
51
51
|
|
52
52
|
# Base search paths - these will be searched recursively
|
53
53
|
loader_paths = []
|
@@ -70,11 +70,11 @@ module DataShift
|
|
70
70
|
require_relative 'datashift/loaders/reporters/reporter'
|
71
71
|
require_relative 'datashift/loaders/loader_base'
|
72
72
|
require_relative 'datashift/exporters/exporter_base'
|
73
|
-
rescue => x
|
73
|
+
rescue StandardError => x
|
74
74
|
puts "Problem initializing gem #{x.inspect}"
|
75
75
|
end
|
76
76
|
|
77
|
-
require_libs = %w
|
77
|
+
require_libs = %w[
|
78
78
|
datashift/core_ext
|
79
79
|
datashift
|
80
80
|
datashift/mapping
|
@@ -88,14 +88,14 @@ module DataShift
|
|
88
88
|
datashift/helpers
|
89
89
|
datashift/applications
|
90
90
|
datashift/populators
|
91
|
-
|
91
|
+
]
|
92
92
|
|
93
93
|
require_libs.each do |base|
|
94
94
|
Dir[File.join(library_path, base, '*.rb')].each do |rb|
|
95
95
|
# puts rb
|
96
96
|
begin
|
97
97
|
require_relative rb unless File.directory?(rb)
|
98
|
-
rescue => x
|
98
|
+
rescue StandardError => x
|
99
99
|
puts "WARNING - Problem loading datashift file #{rb} - #{x.inspect}"
|
100
100
|
puts x.backtrace
|
101
101
|
end
|
@@ -128,7 +128,7 @@ module DataShift
|
|
128
128
|
|
129
129
|
Dir["#{base}/*.thor"].each do |f|
|
130
130
|
next unless File.file?(f)
|
131
|
-
|
131
|
+
Thor::Util.load_thorfile(f)
|
132
132
|
end
|
133
133
|
end
|
134
134
|
|
data/lib/datashift/binder.rb
CHANGED
@@ -101,14 +101,16 @@ module DataShift
|
|
101
101
|
|
102
102
|
# If klass not in Dictionary yet, add to dictionary all possible operators on klass
|
103
103
|
# which can be used to map headers and populate an object of type klass
|
104
|
-
|
104
|
+
model_methods_collection = ModelMethods::Manager.catalog_class(klass)
|
105
|
+
|
106
|
+
bound = bindings.map(&:source)
|
105
107
|
|
106
108
|
[*columns].each_with_index do |col_data, col_index|
|
107
109
|
raw_col_data = col_data.to_s.strip
|
108
110
|
|
109
111
|
if raw_col_data.nil? || raw_col_data.empty?
|
110
112
|
logger.warn("Column list contains empty or null header at index #{col_index}")
|
111
|
-
bindings << NoMethodBinding.new(raw_col_data, col_index)
|
113
|
+
bindings << NoMethodBinding.new(raw_col_data, idx: col_index)
|
112
114
|
next
|
113
115
|
end
|
114
116
|
|
@@ -119,25 +121,38 @@ module DataShift
|
|
119
121
|
#
|
120
122
|
raw_col_name, where_field, where_value, *data = raw_col_data.split(column_delim).map(&:strip)
|
121
123
|
|
124
|
+
# Config loaded details trump internal mappings. User may not bother setting index of the column
|
125
|
+
# in config, so attempt now to match it to actual header
|
126
|
+
if bound.include?(raw_col_name)
|
127
|
+
external = bindings.find { |b| b.source == raw_col_name }
|
128
|
+
external.index = col_index if(external && external.index.nil?)
|
129
|
+
next
|
130
|
+
end
|
131
|
+
|
122
132
|
# Find the domain model method details
|
123
|
-
model_method =
|
133
|
+
model_method = model_methods_collection.search(raw_col_name)
|
124
134
|
|
125
|
-
# No such column,
|
135
|
+
# No such column, so check config
|
136
|
+
#
|
137
|
+
# Forced inclusion for example for delegated methods that do not show up in reflection.
|
138
|
+
#
|
139
|
+
# Add as operator type :assignment
|
140
|
+
#
|
126
141
|
if( model_method.nil? && (include_all? || forced?(raw_col_name)) )
|
127
142
|
logger.debug("Operator #{raw_col_name} not found but forced inclusion set - adding as :assignment")
|
128
|
-
model_method =
|
143
|
+
model_method = model_methods_collection.insert(raw_col_name, :assignment)
|
129
144
|
end
|
130
145
|
|
131
146
|
unless model_method
|
132
147
|
Binder.substitutions(raw_col_name).each do |n|
|
133
|
-
model_method =
|
148
|
+
model_method = model_methods_collection.search(n)
|
134
149
|
break if model_method
|
135
150
|
end
|
136
151
|
end
|
137
152
|
|
138
153
|
if(model_method)
|
139
154
|
|
140
|
-
binding = MethodBinding.new(raw_col_name,
|
155
|
+
binding = MethodBinding.new(raw_col_name, model_method, idx: col_index)
|
141
156
|
|
142
157
|
# we slurped up all possible data in split, turn it back into original string
|
143
158
|
binding.add_column_data(data.join(column_delim))
|
@@ -147,7 +162,7 @@ module DataShift
|
|
147
162
|
|
148
163
|
begin
|
149
164
|
binding.add_lookup(model_method, where_field, where_value)
|
150
|
-
rescue => e
|
165
|
+
rescue StandardError => e
|
151
166
|
logger.error(e.message)
|
152
167
|
add_missing(raw_col_data, col_index, "Field [#{where_field}] Not Found for [#{raw_col_name}] (#{model_method.operator})")
|
153
168
|
next
|
@@ -167,8 +182,7 @@ module DataShift
|
|
167
182
|
end
|
168
183
|
|
169
184
|
def add_bindings_from_nodes( nodes )
|
170
|
-
|
171
|
-
nodes.each { |n| bindings << n.method_binding }
|
185
|
+
nodes.each { |n| bindings << n.method_binding unless n.is_a?(NoMethodBinding) }
|
172
186
|
end
|
173
187
|
|
174
188
|
# Essentially we map any string collection of field names, not just headers from files
|
@@ -177,7 +191,7 @@ module DataShift
|
|
177
191
|
def add_missing(col_data, col_index, reason)
|
178
192
|
logger.warn(reason)
|
179
193
|
|
180
|
-
missing = NoMethodBinding.new(col_data,
|
194
|
+
missing = NoMethodBinding.new(col_data, reason: reason, idx: col_index)
|
181
195
|
|
182
196
|
missing_bindings << missing
|
183
197
|
bindings << missing
|
@@ -210,6 +224,11 @@ module DataShift
|
|
210
224
|
bindings.collect( &:operator )
|
211
225
|
end
|
212
226
|
|
227
|
+
# Find a binding, matches raw client supplied names e.g header and has a valid index
|
228
|
+
def find_for_source( name )
|
229
|
+
bindings.find { |b| b.source == name && b.index }
|
230
|
+
end
|
231
|
+
|
213
232
|
end
|
214
233
|
|
215
234
|
end
|
@@ -11,6 +11,14 @@ module DataShift
|
|
11
11
|
|
12
12
|
class Configuration
|
13
13
|
|
14
|
+
|
15
|
+
def self.parse_yaml( yaml_file )
|
16
|
+
bound_template = ERB.new( IO.read(yaml_file)).result
|
17
|
+
|
18
|
+
YAML.safe_load(bound_template, [Date, Time, Symbol] )
|
19
|
+
end
|
20
|
+
|
21
|
+
|
14
22
|
# List of association +TYPES+ to INCLUDE [:assignment, :enum, :belongs_to, :has_one, :has_many, :method]
|
15
23
|
# Defaults to [:assignment, :enum]
|
16
24
|
#
|
@@ -122,11 +130,11 @@ module DataShift
|
|
122
130
|
attr_accessor :image_path_prefix
|
123
131
|
|
124
132
|
def self.rails_columns
|
125
|
-
@rails_standard_columns ||= [
|
133
|
+
@rails_standard_columns ||= %i[id created_at created_on updated_at updated_on]
|
126
134
|
end
|
127
135
|
|
128
136
|
def initialize
|
129
|
-
@with = [
|
137
|
+
@with = %i[assignment enum]
|
130
138
|
@exclude = []
|
131
139
|
@remove_columns = []
|
132
140
|
|
@@ -1,12 +1,12 @@
|
|
1
1
|
Array.class_eval do
|
2
2
|
|
3
|
-
ARRAY_FWDABLE_EXCLUDED_METHODS = [
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
ARRAY_FWDABLE_EXCLUDED_METHODS = %i[
|
4
|
+
class singleton_class clone dup initialize_dup initialize_clone
|
5
|
+
freeze methods singleton_methods protected_methods private_methods public_methods
|
6
|
+
instance_variables instance_variable_get instance_variable_set instance_variable_defined?
|
7
|
+
instance_of? kind_of? is_a? tap send public_send respond_to? respond_to_missing?
|
8
|
+
extend display method public_method define_singleton_method object_id equal?
|
9
|
+
instance_eval instance_exec __send__ __id__
|
10
10
|
].freeze
|
11
11
|
|
12
12
|
def self.delegated_methods_for_fwdable
|
data/lib/datashift/delimiters.rb
CHANGED
@@ -72,7 +72,7 @@ module DataShift
|
|
72
72
|
# Objects can be created with multiple facets in single columns.
|
73
73
|
# In this example a single Product can be configured with a consolidated mime and print types
|
74
74
|
#
|
75
|
-
# mime_type:jpeg,PDF ; print_type:colour
|
75
|
+
# mime_type:jpeg,PDF ; print_type:colour equivalent to
|
76
76
|
#
|
77
77
|
# => mime_type:jpeg;print_type:colour | mime_type:PDF; print_type:colour
|
78
78
|
|
@@ -119,7 +119,7 @@ module DataShift
|
|
119
119
|
logger.debug("SAVING #{load_object.class} : #{load_object.inspect}")
|
120
120
|
begin
|
121
121
|
load_object.save!
|
122
|
-
rescue => e
|
122
|
+
rescue StandardError => e
|
123
123
|
logger.error( "Save Error : #{e.inspect} on #{load_object.class}")
|
124
124
|
logger.error(e.backtrace)
|
125
125
|
false
|
data/lib/datashift/excel_base.rb
CHANGED
@@ -105,7 +105,7 @@ module DataShift
|
|
105
105
|
|
106
106
|
# Pass a set of AR records
|
107
107
|
def ar_to_xls(records, start_row: 1, headers: nil, data_flow_schema: nil)
|
108
|
-
return if
|
108
|
+
return if !exportable?(records.first) || records.empty?
|
109
109
|
|
110
110
|
# assume header row present
|
111
111
|
row_index = start_row
|
@@ -140,7 +140,7 @@ module DataShift
|
|
140
140
|
def ar_to_xls_cell(row_idx, col_idx, record, ar_method)
|
141
141
|
datum = record.send(ar_method)
|
142
142
|
self[row_idx, col_idx] = datum
|
143
|
-
rescue => e
|
143
|
+
rescue StandardError => e
|
144
144
|
logger.error("Failed to export #{datum} from #{ar_method.inspect} to column #{col_idx}")
|
145
145
|
logger.error(e.message)
|
146
146
|
logger.error(e.backtrace)
|
@@ -43,7 +43,7 @@ module DataShift
|
|
43
43
|
def export(file, export_records, options = {})
|
44
44
|
records = [*export_records]
|
45
45
|
|
46
|
-
if
|
46
|
+
if records.blank?
|
47
47
|
logger.warn('Excel Export - No objects supplied for export - no file written')
|
48
48
|
return
|
49
49
|
end
|
@@ -108,7 +108,7 @@ module DataShift
|
|
108
108
|
|
109
109
|
logger.info("Processing [#{records.size}] #{klass} records to Excel")
|
110
110
|
|
111
|
-
# TODO - prepare_data_flow_schema here in middle of export, plus reaching through nodes to klass, does not smell right
|
111
|
+
# TODO: - prepare_data_flow_schema here in middle of export, plus reaching through nodes to klass, does not smell right
|
112
112
|
prepare_data_flow_schema(klass) unless @data_flow_schema && @data_flow_schema.nodes.klass == klass
|
113
113
|
|
114
114
|
export_headers(klass)
|
@@ -136,7 +136,7 @@ module DataShift
|
|
136
136
|
else
|
137
137
|
excel[row, column] = obj.send( model_method.operator )
|
138
138
|
end
|
139
|
-
rescue => x
|
139
|
+
rescue StandardError => x
|
140
140
|
logger.error("Failed to write #{model_method.inspect} to Excel")
|
141
141
|
logger.error(x.inspect)
|
142
142
|
end
|
@@ -149,7 +149,6 @@ module DataShift
|
|
149
149
|
|
150
150
|
logger.info("Writing Excel to file [#{file_name}]")
|
151
151
|
excel.write( file_name )
|
152
|
-
|
153
152
|
ensure
|
154
153
|
DataShift::Configuration.call.with = state
|
155
154
|
|
@@ -136,9 +136,7 @@ module FileDefinitions
|
|
136
136
|
#
|
137
137
|
def create_fixed_definition( field_range_map )
|
138
138
|
|
139
|
-
unless field_range_map.is_a?(Hash)
|
140
|
-
raise ArgumentError, 'Please supply hash to create_fixed_definition'
|
141
|
-
end
|
139
|
+
raise ArgumentError, 'Please supply hash to create_fixed_definition' unless field_range_map.is_a?(Hash)
|
142
140
|
|
143
141
|
keys = field_range_map.keys.collect(&:to_s)
|
144
142
|
string_map = Hash[*keys.zip(field_range_map.values).flatten]
|
@@ -22,7 +22,7 @@ module DataShift
|
|
22
22
|
attr_reader :inbound_column
|
23
23
|
|
24
24
|
delegate :source, to: :inbound_column, allow_nil: true
|
25
|
-
delegate :index, to: :inbound_column, allow_nil: true
|
25
|
+
delegate :index, 'index=', to: :inbound_column, allow_nil: true
|
26
26
|
|
27
27
|
# Is this method detail a valid mapping, aids identifying unmapped/unmappable columns
|
28
28
|
attr_accessor :valid
|
@@ -36,7 +36,7 @@ module DataShift
|
|
36
36
|
#
|
37
37
|
# col_types can typically be derived from klass.columns - set of ActiveRecord::ConnectionAdapters::Column
|
38
38
|
|
39
|
-
def initialize(name,
|
39
|
+
def initialize(name, model_method, idx: nil)
|
40
40
|
@inbound_column = InboundData::Column.new(name, idx)
|
41
41
|
|
42
42
|
@model_method = model_method
|
@@ -130,10 +130,10 @@ module DataShift
|
|
130
130
|
|
131
131
|
attr_accessor :reason
|
132
132
|
|
133
|
-
def initialize(client_name = '',
|
134
|
-
super(client_name,
|
133
|
+
def initialize(client_name = '', reason: nil, idx: 1 )
|
134
|
+
super(client_name, nil, idx: idx)
|
135
135
|
|
136
|
-
@reason =
|
136
|
+
@reason = reason || ''
|
137
137
|
end
|
138
138
|
|
139
139
|
def invalid?
|