Class: DatasetRecordField

Inherits:
ApplicationRecord show all
Includes:
Shared::IsData
Defined in:
app/models/dataset_record_field.rb

Constant Summary collapse

VALUE_INDEX_LIMIT =

Maximum length for value to be searched via index, larger values use other index that require full scan on import dataset

1000
DATASET_RECORD_DESCENDANTS =

Unfortunately DatasetRecord.descendants is empty on ActiveJob context, so have to list classes explicitly

[
  DatasetRecord::DarwinCore::Extension,
  DatasetRecord::DarwinCore::Occurrence,
  DatasetRecord::DarwinCore::Taxon
]
ENCODED_TYPES_LUT =
DatasetRecord.descendants.map(&:name).inject({}) do |lut, type|
  digest = Digest::MD5.hexdigest(type).last(32/4).to_i(16) & (2**31 - 1)
  lut.merge({type => digest, digest => type})
end

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Shared::IsData

#errors_excepting, #full_error_messages_excepting, #identical, #is_community?, #is_destroyable?, #is_editable?, #is_in_use?, #is_in_users_projects?, #metamorphosize, #similar

Methods inherited from ApplicationRecord

transaction_with_retry

Class Method Details

.at(position) ⇒ Object



19
20
21
# File 'app/models/dataset_record_field.rb', line 19

def self.at(position)
  where(position: position)
end

.decode_record_type(encoded_type) ⇒ Object



61
62
63
# File 'app/models/dataset_record_field.rb', line 61

def decode_record_type(encoded_type)
  ENCODED_TYPES_LUT.fetch(encoded_type)
end

.encode_record_type(type) ⇒ Object



57
58
59
# File 'app/models/dataset_record_field.rb', line 57

def encode_record_type(type)
  ENCODED_TYPES_LUT.fetch(type.name)
end

.indexed_column_value(value) ⇒ Object



49
50
51
52
53
54
55
# File 'app/models/dataset_record_field.rb', line 49

def indexed_column_value(value)
  unless value.nil? || value.length > VALUE_INDEX_LIMIT # TODO: Is there a way to still use this with NULL value?
    Arel::Nodes::NamedFunction.new("substr", [arel_table[:value], 1, VALUE_INDEX_LIMIT])
  else
    arel_table[:value]
  end
end

.with_prefix_value(prefix) ⇒ Object



38
39
40
# File 'app/models/dataset_record_field.rb', line 38

def self.with_prefix_value(prefix)
  where(indexed_column_value(prefix).matches("#{sanitize_sql_like(prefix)}%"))
end

.with_record_class(record_class) ⇒ Object



42
43
44
45
46
# File 'app/models/dataset_record_field.rb', line 42

def self.with_record_class(record_class)
  where(
    encoded_dataset_record_type: DatasetRecordField.encode_record_type(record_class)
  )
end

.with_value(value) ⇒ Object



23
24
25
# File 'app/models/dataset_record_field.rb', line 23

def self.with_value(value)
  where(indexed_column_value(value).eq(value))
end

.with_values(values) ⇒ Object

Messy way of passing array of values for indexed_column_value

Parameters:

  • values (Array)


29
30
31
32
33
34
35
36
# File 'app/models/dataset_record_field.rb', line 29

def self.with_values(values)
  if values.all? { |value| !value.nil? && value.length < VALUE_INDEX_LIMIT}
    where(indexed_column_value(values.first).in(values))
  else
    where(value: values)
  end

end

Instance Method Details

#dataset_record_typeObject



11
12
13
# File 'app/models/dataset_record_field.rb', line 11

def dataset_record_type
  DatasetRecordField.decode_record_type(self.encoded_dataset_record_type)
end

#dataset_record_type=(type) ⇒ Object



15
16
17
# File 'app/models/dataset_record_field.rb', line 15

def dataset_record_type=(type)
  self.encoded_dataset_record_type = DatasetRecordField.encode_record_type(type)
end