Module: SupportTableData

Extended by:
ActiveSupport::Concern
Defined in:
lib/support_table_data.rb,
lib/support_table_data/tasks.rb,
lib/support_table_data/railtie.rb,
lib/support_table_data/tasks/utils.rb,
lib/support_table_data/documentation.rb,
lib/support_table_data/validation_error.rb,
lib/support_table_data/documentation/rbs_doc.rb,
lib/support_table_data/documentation/rbs_file.rb,
lib/support_table_data/documentation/yard_doc.rb,
lib/support_table_data/documentation/source_file.rb,
lib/support_table_data/documentation/type_inference.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

Constant Summary collapse

YARD_DOC_OPTIONS =
[:full, :compact, :none].freeze

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.rbs_signatures_pathString, ...

Override the directory under which generated RBS signature files are written. When nil (the default) signatures go to ‘<project_root>/sig/<model_path>.rbs`, where the project root is the nearest ancestor directory containing a Gemfile or .git directory.

Returns:

  • (String, Pathname, nil)


434
435
436
# File 'lib/support_table_data.rb', line 434

def rbs_signatures_path
  @rbs_signatures_path
end

Class Method Details

.data_directoryObject



418
419
420
# File 'lib/support_table_data.rb', line 418

def data_directory
  @data_directory
end

.data_directory=(value) ⇒ void

This method returns an undefined value.

Set the default directory where data files live.

Parameters:

  • value (String, Pathname, nil)

    The path to the directory.



424
425
426
# File 'lib/support_table_data.rb', line 424

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.

Parameters:

  • extra_classes (Class)

    List of extra classes to include in the return list.

Returns:

  • (Array<Class>)

    List of classes in the order they should be loaded.



470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
# File 'lib/support_table_data.rb', line 470

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, delete_missing: false) ⇒ 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.

Parameters:

  • extra_classes (Class)

    List of classes to force into the detected list of classes to sync.

  • delete_missing (Boolean) (defaults to: false)

    If true, then any records in the database that are not in the data files will be deleted from each table. Use with caution.

Returns:

  • (Hash<Class, Array<Hash>] Hash of classes synced with a list of saved changes.)

    Hash<Class, Array<Hash>] Hash of classes synced with a list of saved changes.



448
449
450
451
452
453
454
# File 'lib/support_table_data.rb', line 448

def sync_all!(*extra_classes, delete_missing: false)
  changes = {}
  support_table_classes(*extra_classes).each do |klass|
    changes[klass] = klass.sync_table_data!(delete_missing: delete_missing)
  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.

Returns:

  • (Boolean)


543
544
545
# File 'lib/support_table_data.rb', line 543

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