datashift 0.40.3 → 0.40.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +7 -2
  3. data/datashift.thor +28 -23
  4. data/lib/datashift.rb +6 -6
  5. data/lib/datashift/binder.rb +30 -11
  6. data/lib/datashift/configuration.rb +10 -2
  7. data/lib/datashift/core_ext/array.rb +7 -7
  8. data/lib/datashift/delimiters.rb +1 -1
  9. data/lib/datashift/doc_context.rb +1 -1
  10. data/lib/datashift/excel_base.rb +2 -2
  11. data/lib/datashift/exporters/csv_exporter.rb +0 -1
  12. data/lib/datashift/exporters/excel_exporter.rb +3 -4
  13. data/lib/datashift/file_definitions.rb +1 -3
  14. data/lib/datashift/inbound_data/method_binding.rb +5 -5
  15. data/lib/datashift/loaders/csv_loader.rb +2 -3
  16. data/lib/datashift/loaders/excel_loader.rb +8 -4
  17. data/lib/datashift/loaders/failure_data.rb +1 -3
  18. data/lib/datashift/loaders/loader_base.rb +2 -8
  19. data/lib/datashift/loaders/loader_factory.rb +6 -0
  20. data/lib/datashift/loaders/paperclip/attachment_loader.rb +1 -1
  21. data/lib/datashift/loaders/paperclip/datashift_paperclip.rb +2 -2
  22. data/lib/datashift/loaders/paperclip/image_loading.rb +2 -2
  23. data/lib/datashift/mapping/data_flow_schema.rb +40 -14
  24. data/lib/datashift/mapping/mapper_utils.rb +3 -3
  25. data/lib/datashift/model_methods/catalogue.rb +14 -14
  26. data/lib/datashift/model_methods/model_method.rb +5 -6
  27. data/lib/datashift/model_methods/operator.rb +1 -1
  28. data/lib/datashift/node_context.rb +2 -3
  29. data/lib/datashift/populators/has_many.rb +2 -2
  30. data/lib/datashift/populators/insistent_assignment.rb +4 -4
  31. data/lib/datashift/populators/populator.rb +21 -16
  32. data/lib/datashift/populators/populator_factory.rb +2 -4
  33. data/lib/datashift/querying.rb +4 -5
  34. data/lib/datashift/transformation/factory.rb +3 -3
  35. data/lib/datashift/version.rb +1 -1
  36. data/lib/generators/datashift/install_generator.rb +3 -3
  37. data/lib/generators/templates/datashift.rb +0 -4
  38. data/lib/tasks/config.thor +7 -9
  39. data/lib/tasks/export.thor +44 -45
  40. data/lib/tasks/generate.thor +43 -37
  41. data/lib/tasks/import.thor +20 -14
  42. data/lib/tasks/paperclip.thor +46 -48
  43. data/lib/tasks/thor_behaviour.rb +1 -1
  44. data/lib/tasks/to_convert_to_thor/db_tasks.rake +1 -3
  45. data/lib/tasks/tools.thor +37 -38
  46. metadata +45 -45
@@ -77,7 +77,7 @@ module DataShift
77
77
 
78
78
  begin
79
79
  context.process
80
- rescue => x
80
+ rescue StandardError => x
81
81
  if doc_context.all_or_nothing?
82
82
  logger.error('Complete Row aborted - All or nothing set and Current Column failed.')
83
83
  logger.error(x.backtrace.first.inspect)
@@ -97,8 +97,7 @@ module DataShift
97
97
  raise ActiveRecord::Rollback # Don't actually create/upload to DB if we are doing dummy run
98
98
  end
99
99
  end # TRANSACTION N.B ActiveRecord::Rollback does not propagate outside of the containing transaction block
100
-
101
- rescue => e
100
+ rescue StandardError => e
102
101
  puts "ERROR: CSV loading failed : #{e.inspect}"
103
102
  raise e
104
103
  ensure
@@ -66,13 +66,18 @@ module DataShift
66
66
 
67
67
  @binder.bindings.each do |method_binding|
68
68
 
69
+ # TODO: - how does this get inserted - bind headers ?? ignore if no index
70
+ # #<DataShift::MethodBinding:0x0000000003e26280 @inbound_column=#<DataShift::InboundData::Column:0x0000000003e26258 @header=#<DataShift::Header:0x0000000003e26190 @source="audio", @presentation="audio">, @index=nil,
71
+ next if method_binding.index.nil?
72
+
69
73
  unless method_binding.valid?
70
74
  logger.warn("No binding was found for column (#{current_row_idx})")
71
75
  next
72
76
  end
73
77
 
74
78
  # If binding to a column, get the value from the cell (bindings can be to internal methods)
75
- value = method_binding.index ? row[method_binding.index] : nil
79
+ #
80
+ value = row[method_binding.index]
76
81
 
77
82
  context = doc_context.create_node_context(method_binding, current_row_idx, value)
78
83
 
@@ -82,7 +87,7 @@ module DataShift
82
87
 
83
88
  begin
84
89
  context.process
85
- rescue
90
+ rescue StandardError
86
91
  if doc_context.all_or_nothing?
87
92
  logger.error('All or nothing set and Current Column failed so complete Row aborted')
88
93
  break
@@ -105,8 +110,7 @@ module DataShift
105
110
  raise ActiveRecord::Rollback # Don't actually create/upload to DB if we are doing dummy run
106
111
  end
107
112
  end # TRANSACTION N.B ActiveRecord::Rollback does not propagate outside of the containing transaction block
108
-
109
- rescue => e
113
+ rescue StandardError => e
110
114
  puts "ERROR: Excel loading failed : #{e.inspect}"
111
115
  raise e
112
116
  ensure
@@ -31,9 +31,7 @@ module DataShift
31
31
 
32
32
  def destroy_failed_object
33
33
  if load_object
34
- if load_object.respond_to?('destroy') && !load_object.new_record?
35
- load_object.destroy
36
- end
34
+ load_object.destroy if load_object.respond_to?('destroy') && !load_object.new_record?
37
35
  end
38
36
  end
39
37
 
@@ -89,11 +89,9 @@ module DataShift
89
89
 
90
90
  logger.info("Binding #{headers.size} inbound headers to #{load_object_class.name}")
91
91
 
92
- @binder ||= DataShift::Binder.new
93
-
94
92
  begin
95
93
  binder.map_inbound_headers(load_object_class, headers)
96
- rescue => e
94
+ rescue StandardError => e
97
95
  logger.error("Failed to map header row to set of database operators : #{e.inspect}")
98
96
  logger.error( e.backtrace )
99
97
  raise MappingDefinitionError, 'Failed to map header row to set of database operators'
@@ -141,14 +139,10 @@ module DataShift
141
139
 
142
140
  logger.info("Reading Datashift loader config from: #{yaml_file.inspect}")
143
141
 
144
- data = YAML.load( ERB.new( IO.read(yaml_file) ).result )
142
+ data = Configuration.parse_yaml(yaml_file)
145
143
 
146
144
  logger.info("Read Datashift config: #{data.inspect}")
147
145
 
148
- @config.merge!(data['LoaderBase']) if data['LoaderBase']
149
-
150
- @config.merge!(data[self.class.name]) if data[self.class.name]
151
-
152
146
  @binder ||= DataShift::Binder.new
153
147
 
154
148
  data_flow_schema = DataShift::DataFlowSchema.new
@@ -16,6 +16,12 @@ module DataShift
16
16
 
17
17
  class Factory
18
18
 
19
+ # organizer
20
+
21
+ # include Interactor::Organizer
22
+
23
+ # organize DetermineLoaderKlass, BuildKlassCatalog, LoadConfig, ApplyConfig
24
+
19
25
  # Based on file_name find appropriate Loader
20
26
 
21
27
  # Currently supports :
@@ -80,7 +80,7 @@ module DataShift
80
80
  logger.info("Finding matching field/association [#{attach_to_field}] on class [#{attach_to_klass}]")
81
81
 
82
82
  binder.map_inbound_fields(attach_to_klass, attach_to_field)
83
- rescue => e
83
+ rescue StandardError => e
84
84
  logger.error("Failed to map #{attach_to_field} to database operator : #{e.inspect}")
85
85
  logger.error( e.backtrace )
86
86
  raise MappingDefinitionError, 'Failed to map #{attach_to_field} to database operator'
@@ -40,7 +40,7 @@ module DataShift
40
40
 
41
41
  file = begin
42
42
  File.new(attachment_path, 'rb')
43
- rescue => e
43
+ rescue StandardError => e
44
44
  logger.error(e.inspect)
45
45
  raise PathError, "ERROR : Failed to read image from #{attachment_path}"
46
46
  end
@@ -89,7 +89,7 @@ module DataShift
89
89
  logger.info("Create paperclip attachment on Class #{klass} - #{paperclip_attributes}")
90
90
 
91
91
  @attachment = klass.new(paperclip_attributes)
92
- rescue => e
92
+ rescue StandardError => e
93
93
  logger.error(e.backtrace.first)
94
94
  raise CreateAttachmentFailed, "Failed [#{e.message}] - Creating Attachment [#{attachment_path}] on #{klass}"
95
95
  ensure
@@ -54,7 +54,7 @@ module DataShift
54
54
  # Set of file extensions ImageMagik can process so default glob
55
55
  # we use to find image files within directories
56
56
  def self.image_magik_glob
57
- @im_glob ||= %w(*.3FR *.AAI *.AI *.ART *.ARW *.AVI *.AVS *.BGR *.BGRA
57
+ @im_glob ||= %w[*.3FR *.AAI *.AI *.ART *.ARW *.AVI *.AVS *.BGR *.BGRA
58
58
  *.BIE *.BMP *.BMP2 *.BMP3 *.BRF *.CAL *.CALS *.CANVAS
59
59
  *.CIN *.CIP *.CLIP *.CMYK *.CMYKA *.CR2 *.CRW *.CUR *.CUT *.DCM *.DCR *.DCX
60
60
  *.DDS *.DFONT *.DJVU *.DNG *.DOT *.DPS *.DPX
@@ -70,7 +70,7 @@ module DataShift
70
70
  *.RGBA *.RGBO *.RLA *.RLE *.SCR *.SCT *.SFW *.SGI *.SR2 *.SRF
71
71
  *.SUN *.SVG *.SVGZ *.TGA *.TIFF *.TIFF64 *.TILE *.TIM *.TTC *.TTF *.UBRL *.UIL *.UYVY *.VDA *.VICAR
72
72
  *.VID *.VIFF *.VST *.WBMP *.WEBP *.WMF *.WMV *.WMZ *.WPG *.X3F
73
- *.XBM *.XC *.XCF *.XPM *.XPS *.XV *.XWD *.YCbCr *.YCbCrA *.YUV)
73
+ *.XBM *.XC *.XCF *.XPM *.XPS *.XV *.XWD *.YCbCr *.YCbCrA *.YUV]
74
74
  "{#{@im_glob.join(',')}}"
75
75
  end
76
76
  end
@@ -56,12 +56,12 @@ module DataShift
56
56
  end
57
57
 
58
58
  # @headers=
59
- #<DataShift::Header:0x00000004bc37f8
59
+ # <DataShift::Header:0x00000004bc37f8
60
60
  # @presentation="status_str",
61
61
  # @source="status_str">],
62
62
 
63
63
  def headers
64
- # TODO fix doc context so it can be created 'empty' i.e without AR klass, and always has empty headers
64
+ # TODO: fix doc context so it can be created 'empty' i.e without AR klass, and always has empty headers
65
65
  @nodes.doc_context.try(:headers) || []
66
66
  end
67
67
 
@@ -83,11 +83,11 @@ module DataShift
83
83
  @nodes = create_node_collections(klass, doc_context: doc_context)
84
84
 
85
85
  klass_to_model_methods( klass ).each_with_index do |mm, i|
86
- @nodes.headers.add(mm.operator) # for a class, the header names, default to the operators (methods)
86
+ @nodes.headers.add(mm.operator) # for a class, the header names, default to the operators (methods)
87
87
 
88
- binding = MethodBinding.new(mm.operator, i, mm)
88
+ binding = MethodBinding.new(mm.operator, mm, idx: i)
89
89
 
90
- # TODO - do we really need to pass in the doc context when parent nodes already has it ?
90
+ # TODO: - do we really need to pass in the doc context when parent nodes already has it ?
91
91
  @nodes << DataShift::NodeContext.new(@nodes.doc_context, binding, i, nil)
92
92
  end
93
93
 
@@ -121,17 +121,19 @@ module DataShift
121
121
  #
122
122
  # See Config generation or lib/datashift/templates/import_export_config.erb for full syntax
123
123
  #
124
- def prepare_from_file(file_name, locale_key = 'data_flow_schema')
125
- @raw_data = ERB.new(File.read(file_name)).result
124
+ # Returns DataShift::NodeCollection
125
+ #
126
+ def prepare_from_file(yaml_file, locale_key = 'data_flow_schema')
127
+ @raw_data = ERB.new(File.read(yaml_file)).result
126
128
 
127
- yaml = YAML.load(raw_data)
129
+ yaml = Configuration.parse_yaml(yaml_file)
128
130
 
129
131
  prepare_from_yaml(yaml, locale_key)
130
132
  end
131
133
 
132
134
  def prepare_from_string(text, locale_key = 'data_flow_schema')
133
135
  @raw_data = text
134
- yaml = YAML.load(raw_data)
136
+ yaml = YAML.safe_load(raw_data)
135
137
 
136
138
  prepare_from_yaml(yaml, locale_key)
137
139
  end
@@ -144,6 +146,23 @@ module DataShift
144
146
 
145
147
  locale_section = yaml[locale_key]
146
148
 
149
+ if(locale_section.key?('Global'))
150
+ global_nodes = locale_section.delete('Global')
151
+
152
+ [*global_nodes].each do |c|
153
+
154
+ # TODO: what is c ? a list or hash ?
155
+ # if DataShift::Configuration.call.respond_to #{c}=
156
+ # Set the global value e.g
157
+ # DataShift::Configuration.call.force_inclusion_of_columns = [:audio]
158
+ end
159
+ end
160
+
161
+ unless locale_section.keys.present?
162
+ logger.warn('No class related configuration found in YAML syntax- Nothing to process')
163
+ return DataShift::NodeCollection.new
164
+ end
165
+
147
166
  class_name = locale_section.keys.first
148
167
 
149
168
  klass = MapperUtils.class_from_string_or_raise(class_name)
@@ -189,7 +208,7 @@ module DataShift
189
208
 
190
209
  section = keyed_node.values.first || {}
191
210
 
192
- # TODO - layout with heading is verbose for no benefit - defunct, simply node.source, node.presentation
211
+ # TODO: - layout with heading is verbose for no benefit - defunct, simply node.source, node.presentation
193
212
  source = section.fetch('heading', {}).fetch('source', nil)
194
213
 
195
214
  # Unless a specific source mentioned assume the node is the source
@@ -201,19 +220,26 @@ module DataShift
201
220
 
202
221
  if(section['operator'])
203
222
  # Find the domain model method details
223
+ # byebug
204
224
  model_method = model_method_mgr.search(section['operator'])
205
225
 
206
226
  unless model_method
207
227
  operator_type = section['operator_type'] || :method
208
228
 
209
- # expect one of ModelMethod.supported_types_enum
229
+ # TODO: validate type ? guess we expect one of ModelMethod.supported_types_enum
210
230
  model_method = model_method_mgr.insert(section['operator'], operator_type)
231
+ # TODO: - This index could be hard coded by the user in YAML or we try to derive it from the headers
232
+ # byebug
233
+ method_binding = MethodBinding.new(source, model_method, idx: section['index'])
211
234
  end
212
-
213
- method_binding = InternalMethodBinding.new(model_method)
214
235
  end
215
236
 
216
- method_binding ||= MethodBinding.new(source, i, model_method)
237
+ # Now ensure we bind source/header(and index) to the method tht performs assignment of inbound datum to the model
238
+ #
239
+ # TOFIX - This is a bug waiting to happen right ? i is not coming from the headers
240
+ # so chances are user hasn't made config indexed as per headers
241
+ # index could be hard coded by the user in YAML or we try to derive it from the headers via the binder ???
242
+ method_binding ||= MethodBinding.new(source, model_method, idx: i)
217
243
 
218
244
  node_context = DataShift::NodeContext.new(@nodes.doc_context, method_binding, i, nil)
219
245
 
@@ -46,8 +46,8 @@ module DataShift
46
46
  def self.class_from_string( str )
47
47
 
48
48
  MapperUtils.const_get_from_string(str.to_s) # Kernel.const_get(model)
49
- rescue
50
- return nil
49
+ rescue StandardError
50
+ nil
51
51
 
52
52
  end
53
53
 
@@ -58,7 +58,7 @@ module DataShift
58
58
  begin
59
59
  DataShift::MapperUtils.class_from_string(find_table)
60
60
  rescue LoadError
61
- rescue
61
+ rescue StandardError
62
62
  nil
63
63
  end
64
64
  end
@@ -61,19 +61,17 @@ module DataShift
61
61
 
62
62
  # Find the has_one associations which can be populated via Model.has_one_name = OtherArModelObject
63
63
  if options[:reload] || has_one[klass].nil?
64
- if Module.const_defined?(:Mongoid)
65
- has_one[klass] = klass.reflect_on_all_associations(:embeds_one).map { |i| i.name.to_s }
66
- else
67
- has_one[klass] = klass.reflect_on_all_associations(:has_one).map { |i| i.name.to_s }
68
- end
64
+ has_one[klass] = if Module.const_defined?(:Mongoid)
65
+ klass.reflect_on_all_associations(:embeds_one).map { |i| i.name.to_s }
66
+ else
67
+ klass.reflect_on_all_associations(:has_one).map { |i| i.name.to_s }
68
+ end
69
69
  end
70
70
 
71
71
  # Find the model's column associations which can be populated via xxxxxx= value
72
72
  # Note, not all reflections return method names in same style so we convert all to
73
73
  # the raw form i.e without the '=' for consistency
74
- if options[:reload] || assignments[klass].nil?
75
- build_assignments( klass, options[:instance_methods] )
76
- end
74
+ build_assignments( klass, options[:instance_methods] ) if options[:reload] || assignments[klass].nil?
77
75
  end
78
76
 
79
77
  def self.clear
@@ -155,7 +153,7 @@ module DataShift
155
153
  def build_assignments(klass, include_instance_methods)
156
154
  begin
157
155
  assignments[klass] = Catalogue.column_names(klass)
158
- rescue => x
156
+ rescue StandardError => x
159
157
  raise DataShiftException, "Failed to process column_names for class #{klass} - #{x.message}"
160
158
  end
161
159
 
@@ -172,11 +170,13 @@ module DataShift
172
170
 
173
171
  assignments[klass].uniq!
174
172
 
175
- assignments[klass].each do |assign|
176
- column_types[klass] ||= {}
177
- column_def = klass.columns.find { |col| col.name == assign }
178
- column_types[klass].merge!( assign => column_def) if column_def
179
- end unless (Module.const_defined?(:Mongoid))
173
+ unless Module.const_defined?(:Mongoid)
174
+ assignments[klass].each do |assign|
175
+ column_types[klass] ||= {}
176
+ column_def = klass.columns.find { |col| col.name == assign }
177
+ column_types[klass].merge!( assign => column_def) if column_def
178
+ end
179
+ end
180
180
  end
181
181
 
182
182
  def catalogued
@@ -4,7 +4,7 @@
4
4
  # License:: MIT
5
5
  #
6
6
  # Details:: This class holds info on a single Method callable on a domain Model
7
- # By holding information on the Type inbound data can be manipulated
7
+ # By holding information on the Type, inbound data can be manipulated
8
8
  # into the right format for the style of operator; simple assignment,
9
9
  # appending to an association collection or a method call
10
10
  #
@@ -17,7 +17,7 @@ module DataShift
17
17
  include DataShift::Logging
18
18
 
19
19
  def self.association_types_enum
20
- @assoc_type_enum ||= [:belongs_to, :has_one, :has_many]
20
+ @assoc_type_enum ||= %i[belongs_to has_one has_many]
21
21
  @assoc_type_enum
22
22
  end
23
23
 
@@ -45,7 +45,7 @@ module DataShift
45
45
 
46
46
  # Note : Not all assignments will currently have a column type, for example
47
47
  # those that are derived from a delegate_belongs_to
48
- keys = Module.const_defined?(:Mongoid) ? klass.fields.keys : klass.columns.map(&:name)
48
+ keys = Module.const_defined?(:Mongoid) ? klass.fields.keys : klass.columns.map(&:name)
49
49
  @connection_adapter_column = keys.find { |col| col == operator } if connection_adapter_column.nil?
50
50
 
51
51
  @connection_adapter_column = DataShift::ModelMethods::Catalogue.column_type_for(klass, operator) if connection_adapter_column.nil?
@@ -144,12 +144,11 @@ module DataShift
144
144
 
145
145
  if result.nil?
146
146
  begin
147
-
148
147
  first = klass.to_s.split('::').first
149
148
  logger.debug "Trying to find operator class with Parent Namespace #{first}"
150
149
 
151
150
  result = MapperUtils.const_get_from_string("#{first}::#{operator.classify}")
152
- rescue => e
151
+ rescue StandardError => e
153
152
  logger.error("Failed to derive Class for #{operator} (#{@operator_type} - #{e.inspect}")
154
153
  end
155
154
  end
@@ -159,7 +158,7 @@ module DataShift
159
158
  elsif connection_adapter_column
160
159
  begin
161
160
  Kernel.const_get(connection_adapter_column.type.to_s.classify)
162
- rescue
161
+ rescue StandardError
163
162
  nil
164
163
  end
165
164
  end
@@ -18,7 +18,7 @@ module DataShift
18
18
  # N.B these are in priority order ie. often prefer to process assignments first, then associations
19
19
  #
20
20
  def self.supported_types_enum
21
- @type_enum ||= [:assignment, :enum, :belongs_to, :has_one, :has_many, :method]
21
+ @type_enum ||= %i[assignment enum belongs_to has_one has_many method paperclip]
22
22
  @type_enum
23
23
  end
24
24
 
@@ -44,8 +44,7 @@ module DataShift
44
44
 
45
45
  def process
46
46
  populator.prepare_and_assign(self, doc_context.load_object, data)
47
- rescue => x
48
-
47
+ rescue StandardError => x
49
48
  failed = FailureData.new( doc_context.load_object, self, x.message)
50
49
 
51
50
  failed.error_messages << "Failed to process node : #{method_binding.pp}"
@@ -61,7 +60,7 @@ module DataShift
61
60
  class EmptyContext < NodeContext
62
61
 
63
62
  def initialize
64
- super(NilClass, DataShift::NoMethodBinding.new, -1, [])
63
+ super(NilClass, DataShift::NoMethodBinding.new, [], idx: -1)
65
64
  end
66
65
  end
67
66
 
@@ -80,7 +80,7 @@ module DataShift
80
80
  find_by_values.each do |v|
81
81
  begin
82
82
  found_values << klass.where(field => v).first_or_create
83
- rescue => e
83
+ rescue StandardError => e
84
84
  logger.error(e.inspect)
85
85
  logger.error("Failed to find or create #{klass} where #{field} => #{v}")
86
86
  # TODO: some way to define if this is a fatal error or not ?
@@ -100,7 +100,7 @@ module DataShift
100
100
 
101
101
  begin
102
102
  load_object.send(operator) << found_values
103
- rescue => e
103
+ rescue StandardError => e
104
104
  logger.error e.inspect
105
105
  logger.error "Cannot assign #{found_values.inspect} to has_many [#{operator}] "
106
106
  end
@@ -19,13 +19,13 @@ module DataShift
19
19
  extend DataShift::Logging
20
20
 
21
21
  def self.insistent_method_list
22
- @insistent_method_list ||= [:to_s, :downcase, :to_i, :to_f, :to_b]
22
+ @insistent_method_list ||= %i[to_s downcase to_i to_f to_b]
23
23
  end
24
24
 
25
25
  # When looking up an association, when no field provided, try each of these in turn till a match
26
26
  # i.e find_by_name, find_by_title, find_by_id
27
27
  def self.insistent_find_by_list
28
- @insistent_find_by_list ||= [:name, :title, :id]
28
+ @insistent_find_by_list ||= %i[name title id]
29
29
  end
30
30
 
31
31
  def self.call(record, value, operator)
@@ -49,7 +49,7 @@ module DataShift
49
49
  InsistentAssignment.insistent_method_list.each do |f|
50
50
  begin
51
51
  return if(attempt(record, value.send(f), method))
52
- rescue
52
+ rescue StandardError
53
53
  end
54
54
  end
55
55
  end
@@ -64,7 +64,7 @@ module DataShift
64
64
  def attempt(record, value, operator)
65
65
  begin
66
66
  record.send(operator, value)
67
- rescue
67
+ rescue StandardError
68
68
  logger.debug("Brute forced failed for [#{operator}, #{value}]")
69
69
  return false
70
70
  end