Class: DataMiner::Attribute

Inherits:
Object
  • Object
show all
Defined in:
lib/data_miner/attribute.rb

Overview

A mapping between a local model column and a remote data source column.

Constant Summary collapse

VALID_OPTIONS =
[
  'static',
  'dictionary',
  'field_name',
  'delimiter',
  'split',
  'sprintf',
  'upcase',
  'field_number',
  'chars',
  'date_format',
  'ignore_error',
]
DEFAULT_SPLIT_PATTERN =
/\s+/
DEFAULT_SPLIT_KEEP =
0
DEFAULT_DELIMITER =
', '
DEFAULT_UPCASE =
false
DEFAULT_IGNORE_ERROR =
false
TRUE_VALUES =

activerecord-3.2.6/lib/active_record/connection_adapters/column.rb

[true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON', 'yes', 'YES', 'y', 'Y']
FALSE_VALUES =
[false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF', 'no', 'NO', 'n', 'N']
SINGLE_SPACE =
' '

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#charsRange (readonly)

Which characters in a field to keep. Zero-based.

Returns:

  • (Range)


75
76
77
# File 'lib/data_miner/attribute.rb', line 75

def chars
  @chars
end

#date_formatString (readonly)

Date format to pass to Date.strptime

Returns:

  • (String)


99
100
101
# File 'lib/data_miner/attribute.rb', line 99

def date_format
  @date_format
end

#delimiterString (readonly)

A delimiter to be used when joining fields together into a single final value. Used when :field_number is a Range. Defaults to DEFAULT_DELIMITER.

Returns:

  • (String)


71
72
73
# File 'lib/data_miner/attribute.rb', line 71

def delimiter
  @delimiter
end

#dictionary#[] (readonly)

Dictionary for translating.

You pass a Hash or something that responds to []

Returns:

  • (#[])


110
111
112
# File 'lib/data_miner/attribute.rb', line 110

def dictionary
  @dictionary
end

#field_numberInteger, Range (readonly)

Index of where to find the data in the row, starting from zero.

If you pass a Range, then multiple fields will be joined together.

Returns:

  • (Integer, Range)


67
68
69
# File 'lib/data_miner/attribute.rb', line 67

def field_number
  @field_number
end

#ignore_errorTrueClass, FalseClass (readonly)

Ignore value conversion errors - value will be nil.

Returns:

  • (TrueClass, FalseClass)


103
104
105
# File 'lib/data_miner/attribute.rb', line 103

def ignore_error
  @ignore_error
end

#nameString (readonly)

Local column name.

Returns:

  • (String)


51
52
53
# File 'lib/data_miner/attribute.rb', line 51

def name
  @name
end

#splitHash (readonly)

How to split a field. You specify two options:

:pattern: what to split on. Defaults to DEFAULT_SPLIT_PATTERN. :keep: which of elements resulting from the split to keep. Defaults to DEFAULT_SPLIT_KEEP.

Returns:

  • (Hash)


83
84
85
# File 'lib/data_miner/attribute.rb', line 83

def split
  @split
end

#sprintfString (readonly)

A sprintf-style format to apply.

Returns:

  • (String)


87
88
89
# File 'lib/data_miner/attribute.rb', line 87

def sprintf
  @sprintf
end

#staticString, ... (readonly)

A static value to be used.

Returns:

  • (String, Numeric, TrueClass, FalseClass, Object)


91
92
93
# File 'lib/data_miner/attribute.rb', line 91

def static
  @static
end

#synthesizeProc (readonly)

The block passed to a store argument. Synthesize a value by passing a proc that will receive row and should return a final value.

Unlike past versions of DataMiner, you pass this as a block, not with the :synthesize option.

row will be a Hash with string keys or (less often) an Array

Returns:

  • (Proc)


60
61
62
# File 'lib/data_miner/attribute.rb', line 60

def synthesize
  @synthesize
end

#upcaseTrueClass, FalseClass (readonly)

Whether to upcase value. Defaults to DEFAULT_UPCASE.

Returns:

  • (TrueClass, FalseClass)


95
96
97
# File 'lib/data_miner/attribute.rb', line 95

def upcase
  @upcase
end

Instance Method Details

#field_nameArray<String>

Where to find the data in the row. If more than one field name, values are joined with a space.

Returns:

  • (Array<String>)


152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/data_miner/attribute.rb', line 152

def field_name
  return @field_name if defined?(@field_name)
  @field_name = if @field_name_settings.is_a?(::Array)
    @field_name_settings.map(&:to_s)
  elsif @field_name_settings.is_a?(::String) or @field_name_settings.is_a?(::Symbol)
    [ @field_name_settings.to_s ]
  elsif hstore?
    [ hstore_key ]
  else
    [ name ]
  end
end

#hstore?Boolean

Returns:

  • (Boolean)


271
272
273
274
# File 'lib/data_miner/attribute.rb', line 271

def hstore?
  return @hstore_boolean if defined?(@hstore_boolean)
  @hstore_boolean = name.include?('.')
end

#read(row) ⇒ Object



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/data_miner/attribute.rb', line 188

def read(row)
  if not column_exists?
    raise RuntimeError, "[data_miner] Table #{model.table_name} does not have column #{(hstore? ? hstore_column : name).inspect}"
  end
  value = if static?
    static
  elsif synthesize
    synthesize.call(row)
  elsif field_number
    if field_number.is_a?(::Range)
      field_number.map { |n| row[n] }.join(delimiter)
    else
      row[field_number]
    end
  elsif field_name == ROW_HASH_FIELD_NAME
    row.row_hash
  elsif row.is_a?(::Hash) or row.is_a?(::ActiveSupport::OrderedHash)
    field_name.length > 1 ? row.values_at(*field_name).join(SINGLE_SPACE) : row[field_name[0]]
  end
  if value.nil?
    return
  end
  if value.is_a? ::ActiveRecord::Base
    return value
  end
  value = value.to_s
  if boolean_column?
    if TRUE_VALUES.include?(value)
      return true
    elsif FALSE_VALUES.include?(value)
      return false
    else
      return
    end
  end
  if number_column?
    period_position = value.rindex '.'
    comma_position = value.rindex ','
    # assume that ',' is a thousands separator and '.' is a decimal point unless we have evidence to the contrary
    if period_position and comma_position and comma_position > period_position
      # uncommon euro style 1.000,53
      value = value.delete('.').gsub(',', '.')
    elsif comma_position and comma_position > (value.length - 4)
      # uncommon euro style 1000,53
      value = value.gsub(',', '.')
    elsif comma_position
      # more common 1,000[.00] style - still don't want commas
      value = value.delete(',')
    end
  end
  if chars
    value = value[chars]
  end
  if split
    pattern = split.fetch 'pattern', DEFAULT_SPLIT_PATTERN
    keep = split.fetch 'keep', DEFAULT_SPLIT_KEEP
    value = value.to_s.split(pattern)[keep].to_s
  end
  if value.blank? # TODO false is "blank"
    return
  end
  value = DataMiner.compress_whitespace value
  if upcase
    value = DataMiner.upcase value
  end
  if sprintf
    value = sprintf % value.to_f
  end
  if date_format
    value = Date.strptime value.to_s, date_format
  end
  if dictionary
    value = dictionary[value]
  end
  value
rescue
  if ignore_error
    DataMiner.logger.debug { "Error in #{name}: #{$!.message}" }
  else
    raise $!
  end
end

#set_from_row(local_record, remote_row) ⇒ Object

# @private



166
167
168
169
170
171
172
173
# File 'lib/data_miner/attribute.rb', line 166

def set_from_row(local_record, remote_row)
  new_value = read remote_row
  if hstore?
    local_record.send(hstore_column)[hstore_key] = new_value
  else
    local_record.send("#{name}=", new_value)
  end
end