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)


687
688
689
# File 'lib/support_table_data.rb', line 687

def rbs_signatures_path
  @rbs_signatures_path
end

Class Method Details

.data_directoryObject



671
672
673
# File 'lib/support_table_data.rb', line 671

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.



677
678
679
# File 'lib/support_table_data.rb', line 677

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.



723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
# File 'lib/support_table_data.rb', line 723

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(/\.[^.]*\z/, "").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 of classes synced with a list of saved changes.



701
702
703
704
705
706
707
# File 'lib/support_table_data.rb', line 701

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)


796
797
798
# File 'lib/support_table_data.rb', line 796

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