Class: Hlsv::ConfigManager

Inherits:
Object
  • Object
show all
Defined in:
lib/hlsv/config_manager.rb

Overview

Centralizes everything related to config.yaml: field definitions, loading, saving, resetting, clearing and validating the configuration.

Having a single FIELDS table avoids the previous situation where the same set of keys was duplicated across three different places (editable fields, required fields, empty-config template).

Constant Summary collapse

FIELDS =

key => { label:, required: } required: false means the field is editable/clearable but not mandatory for processing (e.g. excluded_ds).

{
  'study_name'           => { label: 'Study name',           required: true  },
  'output_directory'     => { label: 'Output directory',     required: true  },
  'data_directory'       => { label: 'Data directory',       required: true  },
  'define_path'          => { label: 'Define.xml path',      required: true  },
  'excluded_ds'          => { label: 'Excluded datasets',    required: false },
  'event_key'            => { label: 'Event key',            required: true  },
  'intervention_key'     => { label: 'Intervention key',     required: true  },
  'finding_key'          => { label: 'Finding key',          required: true  },
  'finding_about_key'    => { label: 'Finding about key',    required: true  },
  'ds_key'               => { label: 'DS key',               required: true  },
  'relrec_key'           => { label: 'RELREC key',           required: true  },
  'CO_key'               => { label: 'CO key',               required: true  },
  'TA_key'               => { label: 'TA key',               required: true  },
  'TE_key'               => { label: 'TE key',               required: true  },
  'TI_key'               => { label: 'TI key',               required: true  },
  'TS_key'               => { label: 'TS key',               required: true  },
  'TV_key'               => { label: 'TV key',               required: true  }
}.freeze
EDITABLE_FIELDS =
FIELDS.keys.freeze
REQUIRED_FIELDS =
FIELDS.select { |_, v| v[:required] }.freeze

Class Method Summary collapse

Class Method Details

.clearObject

Resets all config fields to nil (keeps structure).



91
92
93
94
95
96
97
# File 'lib/hlsv/config_manager.rb', line 91

def clear
  empty_config = EDITABLE_FIELDS.each_with_object({}) { |field, h| h[field] = nil }
  empty_config['output_type'] = 'csv'

  File.write(Hlsv.config_path, empty_config.to_yaml)
  empty_config
end

.loadObject

Loads and returns config.yaml as a Hash. Halts with 500 if file is missing. halt is injected by the caller (Sinatra helper) since this class has no direct access to Sinatra's request context.



48
49
50
51
52
# File 'lib/hlsv/config_manager.rb', line 48

def load
  return YAML.load_file(Hlsv.config_path) || {} if File.exist?(Hlsv.config_path)

  raise "File config.yaml not found"
end

.load_from(path) ⇒ Object

Loads config.yaml from an arbitrary file picked by the user (via the config page's file browser). Same idea as reset above, just sourced from a chosen file instead of config.default.yaml.



80
81
82
83
84
85
86
87
88
# File 'lib/hlsv/config_manager.rb', line 80

def load_from(path)
  raise "File not found: #{path}" unless File.exist?(path)

  external_config = YAML.load_file(path)
  raise "#{path} is not a valid configuration file" unless external_config.is_a?(Hash)

  File.write(Hlsv.config_path, external_config.to_yaml)
  external_config
end

.resetObject

Reloads config.yaml from config.default.yaml.



69
70
71
72
73
74
75
# File 'lib/hlsv/config_manager.rb', line 69

def reset
  raise "File config.default.yaml not found in project root" unless File.exist?(Hlsv.default_config_path)

  config_default = YAML.load_file(Hlsv.default_config_path)
  File.write(Hlsv.config_path, config_default.to_yaml)
  config_default
end

.save(config_params) ⇒ Object

Merges config_params into the existing config.yaml, for editable fields only. output_type is always forced to 'csv'.



56
57
58
59
60
61
62
63
64
65
66
# File 'lib/hlsv/config_manager.rb', line 56

def save(config_params)
  current_config = File.exist?(Hlsv.config_path) ? (YAML.load_file(Hlsv.config_path) || {}) : {}

  EDITABLE_FIELDS.each do |field|
    current_config[field] = config_params[field] if config_params.key?(field)
  end

  current_config['output_type'] = 'csv'
  File.write(Hlsv.config_path, current_config.to_yaml)
  current_config
end

.validate(config) ⇒ Object

Validates the configuration hash. Checks all required fields are present and validates filesystem paths. Returns an array of error messages (empty if config is valid).



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/hlsv/config_manager.rb', line 102

def validate(config)
  errors = []

  REQUIRED_FIELDS.each do |key, meta|
    value = config[key]
    errors << "#{meta[:label]} is empty" if value.nil? || value.to_s.strip.empty?
  end

  if config['data_directory'] && !config['data_directory'].to_s.strip.empty?
    dir = config['data_directory'].gsub('\\', '/')
    errors << "Data directory does not exist: #{dir}"      unless Dir.exist?(dir)
    errors << "Directory is empty, no .xpt files detected" if Dir["#{dir}/*"].none? { |f| File.extname(f) == '.xpt' }
  end

  if config['define_path'] && config['define_path'] != '-'
    errors << "Invalid path: #{config['define_path']}" unless File.exist?(config['define_path'])
  end

  config['output_type'] = 'csv'
  errors
end