Class: Labimotion::LinkedElement

Inherits:
Object
  • Object
show all
Defined in:
lib/labimotion/libs/linked_element.rb

Overview

Resolves the "inline attributes" of an element linked from a generic drag_element field.

A drag_element link target is identified by the stored value's el_klass:

* a generic element klass name  -> the target is a Labimotion::Element and
its selectable attributes are its own property fields (layer + field);
* a permit-target key (reaction, sample, molecule, wellplate, screen,
research_plan, device_description) -> the target is a standard ELN model
and its selectable attributes are a curated set of database columns.

Used both to list the attributes a user can pick (#available) and to refresh the current values of a previously stored selection (#resolve).

Constant Summary collapse

SOURCE_PROPERTY =
'property'
SOURCE_COLUMN =
'column'
MODELS =

el_klass (permit-target key) => model class name

{
  'reaction' => '::Reaction',
  'sample' => '::Sample',
  'molecule' => '::Molecule',
  'wellplate' => '::Wellplate',
  'screen' => '::Screen',
  'research_plan' => '::ResearchPlan',
  'device_description' => '::DeviceDescription'
}.freeze
COLUMNS =

Curated, scalar columns exposed per type: [column/method, label, unit_column?]

{
  'reaction' => [
    %w[name Name], %w[short_label], ['status', 'Status'], ['role', 'Role'],
    ['rxno', 'Reaction Type'], ['conditions', 'Conditions'],
    ['duration', 'Duration'], %w[solvent Solvent]
  ],
  'sample' => [
    %w[name Name], %w[short_label], ['external_label', 'External Label'],
    ['sum_formula', 'Sum Formula'], ['molecular_mass', 'Molecular Mass'],
    %w[purity Purity], %w[density Density],
    ['real_amount_value', 'Real Amount', 'real_amount_unit'],
    ['target_amount_value', 'Target Amount', 'target_amount_unit'],
    %w[location Location]
  ],
  'molecule' => [
    ['iupac_name', 'IUPAC Name'], ['sum_formular', 'Sum Formula'],
    ['molecular_weight', 'Molecular Weight'],
    ['exact_molecular_weight', 'Exact Molecular Weight'],
    ['cano_smiles', 'Canonical SMILES'], ['melting_point', 'Melting Point'],
    ['boiling_point', 'Boiling Point'], %w[density Density]
  ],
  'wellplate' => [
    %w[name Name], %w[short_label], ['description', 'Description'],
    %w[width Width], %w[height Height]
  ],
  'screen' => [
    %w[name Name], ['description', 'Description'], %w[result Result],
    %w[collaborator Collaborator], ['conditions', 'Conditions'],
    %w[requirements Requirements]
  ],
  'research_plan' => [
    %w[name Name], %w[short_label]
  ],
  'device_description' => [
    %w[name Name], %w[short_label], ['serial_number', 'Serial Number'],
    ['device_class', 'Device Class'], ['operation_mode', 'Operation Mode'],
    ['application_name', 'Application Name'], ['vendor_url', 'Vendor URL'],
    %w[institute Institute], %w[building Building], %w[room Room]
  ]
}.freeze
PROPERTY_TYPES =

Property field types whose value is a scalar worth surfacing inline.

%w[
  text textarea number integer select select-multi checkbox
  datetime system-defined formula-field text-formula ontology-select
].freeze

Instance Method Summary collapse

Constructor Details

#initialize(el_klass, el_id, el_type = nil) ⇒ LinkedElement

Returns a new instance of LinkedElement.



79
80
81
82
83
# File 'lib/labimotion/libs/linked_element.rb', line 79

def initialize(el_klass, el_id, el_type = nil)
  @el_klass = el_klass.to_s
  @el_type = el_type.to_s
  @el_id = el_id
end

Instance Method Details

#availableObject

All attributes the user can pick, each with its current value.



120
121
122
123
124
125
# File 'lib/labimotion/libs/linked_element.rb', line 120

def available
  return generic_attributes if generic?
  return column_attributes if column_based?

  []
end

#column_based?Boolean

Returns:

  • (Boolean)


100
101
102
# File 'lib/labimotion/libs/linked_element.rb', line 100

def column_based?
  MODELS.key?(target_key)
end

#generic?Boolean

Returns:

  • (Boolean)


104
105
106
# File 'lib/labimotion/libs/linked_element.rb', line 104

def generic?
  generic_klass?(target_key)
end

#recordObject



108
109
110
111
112
113
114
115
116
117
# File 'lib/labimotion/libs/linked_element.rb', line 108

def record
  return @record if defined?(@record)

  @record =
    if column_based?
      MODELS[target_key].safe_constantize&.find_by(id: @el_id)
    elsif generic?
      Labimotion::Element.find_by(id: @el_id)
    end
end

#resolve(selected) ⇒ Object

Refresh the values/labels of a previously stored selection. Selections whose source attribute no longer exists are kept but flagged as missing; for an unknown/unsupported el_klass the selection is returned untouched.



130
131
132
133
134
135
136
137
138
139
140
# File 'lib/labimotion/libs/linked_element.rb', line 130

def resolve(selected)
  return selected unless selected.is_a?(Array)
  return selected unless generic? || column_based?

  index = available.index_by { |a| [a['source'], a['key']] }
  selected.map do |attr|
    next attr unless attr.is_a?(Hash)

    index[[attr['source'], attr['key']]] || attr.merge('value' => nil, 'missing' => true)
  end
end

#target_keyObject

drag_element keeps the linked class in el_klass; drag_sample / drag_molecule keep it in el_type (and may omit el_klass). Resolve one effective dispatch key.



87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/labimotion/libs/linked_element.rb', line 87

def target_key
  return @target_key if defined?(@target_key)

  @target_key =
    if MODELS.key?(@el_klass) || generic_klass?(@el_klass)
      @el_klass
    elsif MODELS.key?(@el_type)
      @el_type
    else
      ''
    end
end