Module: SupportTableData

Extended by:
ActiveSupport::Concern
Defined in:
lib/support_table_data.rb,
lib/tasks/utils.rb,
lib/support_table_data/railtie.rb,
lib/support_table_data/documentation.rb,
lib/support_table_data/validation_error.rb,
lib/support_table_data/documentation/yard_doc.rb,
lib/support_table_data/documentation/source_file.rb

Overview

This concern can be mixed into models that represent static support tables. These are small tables that have a limited number of rows, and have values that are often tied to the logic in the code.

The values that should be in support tables can be defined in YAML, JSON, or CSV files. These values can then be synced to the database and helper methods can be generated from them.

Defined Under Namespace

Modules: Documentation, Tasks Classes: Railtie, ValidationError

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.data_directoryObject



366
367
368
# File 'lib/support_table_data.rb', line 366

def data_directory
  @data_directory
end

.data_directory=(value) ⇒ void

This method returns an undefined value.

Set the default directory where data files live.



372
373
374
# File 'lib/support_table_data.rb', line 372

def data_directory=(value)
  @data_directory = value&.to_s
end

.support_table_classes(*extra_classes) ⇒ Array<Class>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return the list of all support table classes in the order they should be loaded. Note that this method relies on the classes already having been loaded by the application. It can return indeterminate results if eager loading is turned off (i.e. development or test mode in a Rails application).

If any data files exist in the default data directory, any class name that matches the file name will attempt to be loaded (i.e. “task/statuses.yml” will attempt to load the Task::Status class if it exists).

You can also pass in a list of classes that you explicitly want to include in the returned list.



408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
# File 'lib/support_table_data.rb', line 408

def support_table_classes(*extra_classes)
  classes = []
  extra_classes.flatten.each do |klass|
    unless klass.is_a?(Class) && klass.include?(SupportTableData)
      raise ArgumentError.new("#{klass} does not include SupportTableData")
    end
    classes << klass
  end

  # Eager load any classes defined in the default data directory by guessing class names
  # from the file names.
  if SupportTableData.data_directory && File.exist?(SupportTableData.data_directory) && File.directory?(SupportTableData.data_directory)
    Dir.glob(File.join(SupportTableData.data_directory, "**", "*")).sort.each do |file_name|
      file_name = file_name.delete_prefix("#{SupportTableData.data_directory}#{File::SEPARATOR}")
      class_name = file_name.sub(/\.[^.]*/, "").singularize.camelize
      class_name.safe_constantize
    end
  end

  active_record_classes = ActiveRecord::Base.descendants.reject { |klass| klass.name.nil? }
  active_record_classes.sort_by(&:name).each do |klass|
    next unless klass.include?(SupportTableData)
    next unless klass.instance_variable_defined?(:@support_table_data_files) && klass.instance_variable_get(:@support_table_data_files).is_a?(Array)
    next if klass.abstract_class?
    next if classes.include?(klass)
    classes << klass
  end

  levels = [classes]
  checked = Set.new
  loop do
    checked << classes
    dependencies = classes.collect { |klass| support_table_dependencies(klass) }.flatten.uniq.sort_by(&:name)
    break if dependencies.empty? || checked.include?(dependencies)
    levels.unshift(dependencies)
    classes = dependencies
  end

  levels.flatten.uniq
end

.sync_all!(*extra_classes) ⇒ Hash<Class, Array<Hash>] Hash of classes synced with a list of saved changes.

Sync all support table classes. Classes must already be loaded in order to be synced.

You can pass in a list of classes that you want to ensure are synced. This feature can be used to force load classes that are only loaded at runtime. For instance, if eager loading is turned off for the test environment in a Rails application (which is the default), then there is a good chance that support table models won’t be loaded when the test suite is initializing.



386
387
388
389
390
391
392
# File 'lib/support_table_data.rb', line 386

def sync_all!(*extra_classes)
  changes = {}
  support_table_classes(*extra_classes).each do |klass|
    changes[klass] = klass.sync_table_data!
  end
  changes
end

Instance Method Details

#protected_instance?Boolean

Return true if this instance has data being managed from a data file. You can add validation logic using this information if you want to prevent the application from updating protected instances.



481
482
483
# File 'lib/support_table_data.rb', line 481

def protected_instance?
  self.class.protected_instance?(self)
end