support_table_data 1.3.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/AGENTS.md +140 -0
  3. data/ARCHITECTURE.md +538 -0
  4. data/CHANGELOG.md +23 -0
  5. data/README.md +50 -5
  6. data/VERSION +1 -1
  7. data/lib/support_table_data/documentation/source_file.rb +95 -0
  8. data/lib/support_table_data/documentation/yard_doc.rb +91 -0
  9. data/lib/support_table_data/documentation.rb +9 -0
  10. data/lib/support_table_data/railtie.rb +22 -1
  11. data/lib/support_table_data/validation_error.rb +16 -0
  12. data/lib/support_table_data.rb +71 -51
  13. data/lib/tasks/support_table_data.rake +55 -12
  14. data/lib/tasks/utils.rb +63 -0
  15. data/support_table_data.gemspec +2 -2
  16. data/test_app/.gitignore +4 -0
  17. data/test_app/Gemfile +7 -0
  18. data/test_app/Rakefile +6 -0
  19. data/test_app/app/models/application_record.rb +5 -0
  20. data/test_app/app/models/secondary_application_record.rb +7 -0
  21. data/test_app/app/models/status.rb +11 -0
  22. data/test_app/app/models/thing.rb +10 -0
  23. data/test_app/bin/rails +4 -0
  24. data/test_app/config/application.rb +42 -0
  25. data/test_app/config/boot.rb +3 -0
  26. data/test_app/config/database.yml +17 -0
  27. data/test_app/config/environment.rb +5 -0
  28. data/test_app/config/environments/development.rb +11 -0
  29. data/test_app/config/environments/test.rb +11 -0
  30. data/test_app/config.ru +6 -0
  31. data/test_app/db/migrate/20260103060951_create_status.rb +8 -0
  32. data/test_app/db/schema.rb +20 -0
  33. data/test_app/db/secondary_migrate/20260104000001_create_things.rb +7 -0
  34. data/test_app/db/secondary_schema.rb +25 -0
  35. data/test_app/db/support_tables/statuses.yml +19 -0
  36. data/test_app/db/support_tables/things.yml +5 -0
  37. data/test_app/lib/tasks/database.rake +11 -0
  38. data/test_app/log/.keep +0 -0
  39. metadata +36 -10
@@ -3,18 +3,9 @@
3
3
  namespace :support_table_data do
4
4
  desc "Syncronize data for all models that include SupportTableData."
5
5
  task sync: :environment do
6
- # Eager load models if we are in a Rails enviroment with eager loading turned off.
7
- if defined?(Rails.application)
8
- unless Rails.application.config.eager_load
9
- if defined?(Rails.application.eager_load!)
10
- Rails.application.eager_load!
11
- elsif defined?(Rails.autoloaders.zeitwerk_enabled?) && Rails.autoloaders.zeitwerk_enabled?
12
- Rails.autoloaders.each(&:eager_load)
13
- else
14
- warn "Could not eager load models; some support table data may not load"
15
- end
16
- end
17
- end
6
+ require_relative "utils"
7
+
8
+ SupportTableData::Tasks::Utils.eager_load!
18
9
 
19
10
  logger_callback = lambda do |name, started, finished, unique_id, payload|
20
11
  klass = payload[:class]
@@ -31,4 +22,56 @@ namespace :support_table_data do
31
22
  SupportTableData.sync_all!
32
23
  end
33
24
  end
25
+
26
+ namespace :yard_docs do
27
+ desc "Adds YARD documentation comments to models to document the named instance methods."
28
+ task add: :environment do
29
+ require_relative "../support_table_data/documentation"
30
+ require_relative "utils"
31
+
32
+ SupportTableData::Tasks::Utils.eager_load!
33
+ SupportTableData::Tasks::Utils.support_table_sources.each do |source_file|
34
+ next if source_file.yard_docs_up_to_date?
35
+
36
+ source_file.path.write(source_file.source_with_yard_docs)
37
+ puts "Added YARD documentation to #{source_file.klass.name}."
38
+ end
39
+ end
40
+
41
+ desc "Removes YARD documentation comments added by support_table_data from models."
42
+ task remove: :environment do
43
+ require_relative "../support_table_data/documentation"
44
+ require_relative "utils"
45
+
46
+ SupportTableData::Tasks::Utils.eager_load!
47
+ SupportTableData::Tasks::Utils.support_table_sources.each do |source_file|
48
+ next unless source_file.has_yard_docs?
49
+
50
+ source_file.path.write(source_file.source_without_yard_docs)
51
+ puts "Removed YARD documentation from #{source_file.klass.name}."
52
+ end
53
+ end
54
+
55
+ desc "Verify that all the support table models have up to date YARD documentation for named instance methods."
56
+ task verify: :environment do
57
+ require_relative "../support_table_data/documentation"
58
+ require_relative "utils"
59
+
60
+ SupportTableData::Tasks::Utils.eager_load!
61
+
62
+ all_up_to_date = true
63
+ SupportTableData::Tasks::Utils.support_table_sources.each do |source_file|
64
+ unless source_file.yard_docs_up_to_date?
65
+ puts "YARD documentation is not up to date for #{source_file.klass.name}."
66
+ all_up_to_date = false
67
+ end
68
+ end
69
+
70
+ if all_up_to_date
71
+ puts "All support table models have up to date YARD documentation."
72
+ else
73
+ raise "Run bundle exec rails support_table_data:yard_docs:add to update the documentation."
74
+ end
75
+ end
76
+ end
34
77
  end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SupportTableData
4
+ module Tasks
5
+ module Utils
6
+ class << self
7
+ # Helper for eager loading a Rails application.
8
+ def eager_load!
9
+ return unless defined?(Rails.application.config.eager_load)
10
+ return if Rails.application.config.eager_load
11
+
12
+ if defined?(Rails.application.eager_load!)
13
+ Rails.application.eager_load!
14
+ elsif defined?(Rails.autoloaders.zeitwerk_enabled?) && Rails.autoloaders.zeitwerk_enabled?
15
+ Rails.autoloaders.each(&:eager_load)
16
+ else
17
+ raise "Failed to eager load application."
18
+ end
19
+ end
20
+
21
+ # Return a hash mapping all models that include SupportTableData to their source file paths.
22
+ #
23
+ # @return [Array<SupportTableData::Documentation::SourceFile>]
24
+ def support_table_sources
25
+ sources = []
26
+
27
+ ActiveRecord::Base.descendants.each do |klass|
28
+ next unless klass.included_modules.include?(SupportTableData)
29
+
30
+ begin
31
+ next if klass.instance_names.empty?
32
+ rescue NoMethodError
33
+ # Skip models where instance_names is not properly initialized
34
+ next
35
+ end
36
+
37
+ file_path = SupportTableData::Tasks::Utils.model_file_path(klass)
38
+ next unless file_path&.file? && file_path.readable?
39
+
40
+ sources << Documentation::SourceFile.new(klass, file_path)
41
+ end
42
+
43
+ sources
44
+ end
45
+
46
+ def model_file_path(klass)
47
+ file_path = "#{klass.name.underscore}.rb"
48
+ model_path = nil
49
+
50
+ Rails.application.config.paths["app/models"].each do |path_prefix|
51
+ path = Pathname.new(path_prefix.to_s).join(file_path)
52
+ if path&.file? && path.readable?
53
+ model_path = path
54
+ break
55
+ end
56
+ end
57
+
58
+ model_path
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.metadata = {
13
13
  "homepage_uri" => spec.homepage,
14
14
  "source_code_uri" => spec.homepage,
15
- "changelog_uri" => "#{spec.homepage}/blob/master/CHANGELOG.md"
15
+ "changelog_uri" => "#{spec.homepage}/blob/main/CHANGELOG.md"
16
16
  }
17
17
 
18
18
  # Specify which files should be added to the gem when it is released.
@@ -35,7 +35,7 @@ Gem::Specification.new do |spec|
35
35
 
36
36
  spec.required_ruby_version = ">= 2.5"
37
37
 
38
- spec.add_dependency "activerecord"
38
+ spec.add_dependency "activerecord", ">= 6"
39
39
 
40
40
  spec.add_development_dependency "bundler"
41
41
  end
@@ -0,0 +1,4 @@
1
+ log/*.log
2
+ tmp/
3
+ doc/
4
+ db/*.sqlite3
data/test_app/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rails", "~> 8.1.1"
4
+
5
+ gem "sqlite3", "~> 2.9.0"
6
+
7
+ gem "support_table_data", path: ".."
data/test_app/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require_relative "config/application"
5
+
6
+ Rails.application.load_tasks
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationRecord < ActiveRecord::Base
4
+ self.abstract_class = true
5
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SecondaryApplicationRecord < ApplicationRecord
4
+ self.abstract_class = true
5
+
6
+ connects_to database: {writing: :secondary, reading: :secondary}
7
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Status < ApplicationRecord
4
+ include SupportTableData
5
+
6
+ self.support_table_key_attribute = :code
7
+ add_support_table_data "statuses.yml"
8
+ named_instance_attribute_helpers :name
9
+
10
+ validates :code, presence: true, uniqueness: true
11
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Thing < SecondaryApplicationRecord
4
+ include SupportTableData
5
+
6
+ self.support_table_key_attribute = :id
7
+ add_support_table_data "things.yml"
8
+
9
+ validates :name, presence: true, uniqueness: true
10
+ end
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ APP_PATH = File.expand_path("../config/application", __dir__)
3
+ require_relative "../config/boot"
4
+ require "rails/commands"
@@ -0,0 +1,42 @@
1
+ require_relative "boot"
2
+
3
+ require "rails"
4
+ # Pick the frameworks you want:
5
+ # require "active_model/railtie"
6
+ # require "active_job/railtie"
7
+ require "active_record/railtie"
8
+ # require "active_storage/engine"
9
+ # require "action_controller/railtie"
10
+ # require "action_mailer/railtie"
11
+ # require "action_mailbox/engine"
12
+ # require "action_text/engine"
13
+ # require "action_view/railtie"
14
+ # require "action_cable/engine"
15
+ # require "rails/test_unit/railtie"
16
+
17
+ # Require the gems listed in Gemfile, including any gems
18
+ # you've limited to :test, :development, or :production.
19
+ Bundler.require(*Rails.groups)
20
+
21
+ module TestApp
22
+ class Application < Rails::Application
23
+ # Initialize configuration defaults for originally generated Rails version.
24
+ config.load_defaults 8.1
25
+
26
+ # Please, add to the `ignore` list any other `lib` subdirectories that do
27
+ # not contain `.rb` files, or that should not be reloaded or eager loaded.
28
+ # Common ones are `templates`, `generators`, or `middleware`, for example.
29
+ config.autoload_lib(ignore: %w[assets tasks])
30
+
31
+ # Configuration for the application, engines, and railties goes here.
32
+ #
33
+ # These settings can be overridden in specific environments using the files
34
+ # in config/environments, which are processed later.
35
+ #
36
+ # config.time_zone = "Central Time (US & Canada)"
37
+ config.eager_load_paths << Rails.root.join("app", "configurations")
38
+
39
+ # Don't generate system test files.
40
+ config.generators.system_tests = nil
41
+ end
42
+ end
@@ -0,0 +1,3 @@
1
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
2
+
3
+ require "bundler/setup" # Set up gems listed in the Gemfile.
@@ -0,0 +1,17 @@
1
+ development:
2
+ primary:
3
+ adapter: sqlite3
4
+ database: db/development.sqlite3
5
+ secondary:
6
+ adapter: sqlite3
7
+ database: db/secondary_development.sqlite3
8
+ migrations_paths: db/secondary_migrate
9
+
10
+ test:
11
+ primary:
12
+ adapter: sqlite3
13
+ database: db/test.sqlite3
14
+ secondary:
15
+ adapter: sqlite3
16
+ database: db/secondary_test.sqlite3
17
+ migrations_paths: db/secondary_migrate
@@ -0,0 +1,5 @@
1
+ # Load the Rails application.
2
+ require_relative "application"
3
+
4
+ # Initialize the Rails application.
5
+ Rails.application.initialize!
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.configure do
4
+ # Settings specified here will take precedence over those in config/application.rb.
5
+
6
+ # Make code changes take effect immediately without server restart.
7
+ config.enable_reloading = true
8
+
9
+ # Do not eager load code on boot.
10
+ config.eager_load = false
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.configure do
4
+ # Settings specified here will take precedence over those in config/application.rb.
5
+
6
+ # Make code changes take effect immediately without server restart.
7
+ config.enable_reloading = true
8
+
9
+ # Do not eager load code on boot.
10
+ config.eager_load = false
11
+ end
@@ -0,0 +1,6 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require_relative "config/environment"
4
+
5
+ # run Rails.application
6
+ # Rails.application.load_server
@@ -0,0 +1,8 @@
1
+ class CreateStatus < ActiveRecord::Migration[8.1]
2
+ def change
3
+ create_table :statuses do |t|
4
+ t.string :code, null: false, index: {unique: true}
5
+ t.string :name, null: false, index: {unique: true}
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,20 @@
1
+ # This file is auto-generated from the current state of the database. Instead
2
+ # of editing this file, please use the migrations feature of Active Record to
3
+ # incrementally modify your database, and then regenerate this schema definition.
4
+ #
5
+ # This file is the source Rails uses to define your schema when running `bin/rails
6
+ # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
7
+ # be faster and is potentially less error prone than running all of your
8
+ # migrations from scratch. Old migrations may fail to apply correctly if those
9
+ # migrations use external dependencies or application code.
10
+ #
11
+ # It's strongly recommended that you check this file into your version control system.
12
+
13
+ ActiveRecord::Schema[8.1].define(version: 2026_01_03_060951) do
14
+ create_table "statuses", force: :cascade do |t|
15
+ t.string "code", null: false
16
+ t.string "name", null: false
17
+ t.index ["code"], name: "index_statuses_on_code", unique: true
18
+ t.index ["name"], name: "index_statuses_on_name", unique: true
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ class CreateThings < ActiveRecord::Migration[8.1]
2
+ def change
3
+ create_table :things do |t|
4
+ t.string :name, null: false, index: {unique: true}
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ # This file is auto-generated from the current state of the database. Instead
2
+ # of editing this file, please use the migrations feature of Active Record to
3
+ # incrementally modify your database, and then regenerate this schema definition.
4
+ #
5
+ # This file is the source Rails uses to define your schema when running `bin/rails
6
+ # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
7
+ # be faster and is potentially less error prone than running all of your
8
+ # migrations from scratch. Old migrations may fail to apply correctly if those
9
+ # migrations use external dependencies or application code.
10
+ #
11
+ # It's strongly recommended that you check this file into your version control system.
12
+
13
+ ActiveRecord::Schema[8.1].define(version: 2026_01_04_000001) do
14
+ create_table "statuses", force: :cascade do |t|
15
+ t.string "code", null: false
16
+ t.string "name", null: false
17
+ t.index ["code"], name: "index_statuses_on_code", unique: true
18
+ t.index ["name"], name: "index_statuses_on_name", unique: true
19
+ end
20
+
21
+ create_table "things", force: :cascade do |t|
22
+ t.string "name", null: false
23
+ t.index ["name"], name: "index_things_on_name", unique: true
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ pending:
2
+ code: pending
3
+ name: Pending
4
+
5
+ active:
6
+ code: active
7
+ name: Active
8
+
9
+ completed:
10
+ code: completed
11
+ name: Completed
12
+
13
+ canceled:
14
+ code: canceled
15
+ name: Canceled
16
+
17
+ failed:
18
+ code: failed
19
+ name: Failed
@@ -0,0 +1,5 @@
1
+ - id: 1
2
+ name: Thing One
3
+
4
+ - id: 2
5
+ name: Thing Two
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ if Rake::Task.task_defined?("db:migrate")
4
+ Rake::Task["db:migrate"].enhance do
5
+ # The main database connection may have artifacts from the migration, so re-establish it
6
+ # to get a clean connection before syncing support table data.
7
+ ActiveRecord::Base.establish_connection
8
+
9
+ Rake::Task["support_table_data:sync"].invoke
10
+ end
11
+ end
File without changes
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: support_table_data
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Durand
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-01-30 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activerecord
@@ -16,14 +15,14 @@ dependencies:
16
15
  requirements:
17
16
  - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: '0'
18
+ version: '6'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
- version: '0'
25
+ version: '6'
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: bundler
29
28
  requirement: !ruby/object:Gem::Requirement
@@ -38,29 +37,57 @@ dependencies:
38
37
  - - ">="
39
38
  - !ruby/object:Gem::Version
40
39
  version: '0'
41
- description:
42
40
  email:
43
41
  - bbdurand@gmail.com
44
42
  executables: []
45
43
  extensions: []
46
44
  extra_rdoc_files: []
47
45
  files:
46
+ - AGENTS.md
47
+ - ARCHITECTURE.md
48
48
  - CHANGELOG.md
49
49
  - MIT-LICENSE.txt
50
50
  - README.md
51
51
  - VERSION
52
52
  - lib/support_table_data.rb
53
+ - lib/support_table_data/documentation.rb
54
+ - lib/support_table_data/documentation/source_file.rb
55
+ - lib/support_table_data/documentation/yard_doc.rb
53
56
  - lib/support_table_data/railtie.rb
57
+ - lib/support_table_data/validation_error.rb
54
58
  - lib/tasks/support_table_data.rake
59
+ - lib/tasks/utils.rb
55
60
  - support_table_data.gemspec
61
+ - test_app/.gitignore
62
+ - test_app/Gemfile
63
+ - test_app/Rakefile
64
+ - test_app/app/models/application_record.rb
65
+ - test_app/app/models/secondary_application_record.rb
66
+ - test_app/app/models/status.rb
67
+ - test_app/app/models/thing.rb
68
+ - test_app/bin/rails
69
+ - test_app/config.ru
70
+ - test_app/config/application.rb
71
+ - test_app/config/boot.rb
72
+ - test_app/config/database.yml
73
+ - test_app/config/environment.rb
74
+ - test_app/config/environments/development.rb
75
+ - test_app/config/environments/test.rb
76
+ - test_app/db/migrate/20260103060951_create_status.rb
77
+ - test_app/db/schema.rb
78
+ - test_app/db/secondary_migrate/20260104000001_create_things.rb
79
+ - test_app/db/secondary_schema.rb
80
+ - test_app/db/support_tables/statuses.yml
81
+ - test_app/db/support_tables/things.yml
82
+ - test_app/lib/tasks/database.rake
83
+ - test_app/log/.keep
56
84
  homepage: https://github.com/bdurand/support_table_data
57
85
  licenses:
58
86
  - MIT
59
87
  metadata:
60
88
  homepage_uri: https://github.com/bdurand/support_table_data
61
89
  source_code_uri: https://github.com/bdurand/support_table_data
62
- changelog_uri: https://github.com/bdurand/support_table_data/blob/master/CHANGELOG.md
63
- post_install_message:
90
+ changelog_uri: https://github.com/bdurand/support_table_data/blob/main/CHANGELOG.md
64
91
  rdoc_options: []
65
92
  require_paths:
66
93
  - lib
@@ -75,8 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
75
102
  - !ruby/object:Gem::Version
76
103
  version: '0'
77
104
  requirements: []
78
- rubygems_version: 3.4.10
79
- signing_key:
105
+ rubygems_version: 4.0.3
80
106
  specification_version: 4
81
107
  summary: Extension for ActiveRecord models to manage synchronizing data in support/lookup
82
108
  tables across environments. Also provides the ability to directly reference and