support_table_data 1.5.1 → 1.6.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +54 -1
- data/VERSION +1 -1
- data/lib/support_table_data/documentation/rbs_doc.rb +52 -0
- data/lib/support_table_data/documentation/rbs_file.rb +104 -0
- data/lib/support_table_data/documentation/source_file.rb +7 -1
- data/lib/support_table_data/documentation/type_inference.rb +57 -0
- data/lib/support_table_data/documentation/yard_doc.rb +99 -8
- data/lib/support_table_data/documentation.rb +5 -3
- data/lib/{tasks → support_table_data/tasks}/utils.rb +12 -1
- data/lib/support_table_data/tasks.rb +7 -0
- data/lib/support_table_data.rb +67 -7
- data/lib/tasks/support_table_data.rake +51 -12
- data/support_table_data.gemspec +1 -0
- metadata +7 -26
- data/test_app/.gitignore +0 -4
- data/test_app/Gemfile +0 -7
- data/test_app/Rakefile +0 -6
- data/test_app/app/models/application_record.rb +0 -5
- data/test_app/app/models/secondary_application_record.rb +0 -7
- data/test_app/app/models/status.rb +0 -120
- data/test_app/app/models/thing.rb +0 -10
- data/test_app/bin/rails +0 -4
- data/test_app/config/application.rb +0 -42
- data/test_app/config/boot.rb +0 -3
- data/test_app/config/database.yml +0 -17
- data/test_app/config/environment.rb +0 -5
- data/test_app/config/environments/development.rb +0 -11
- data/test_app/config/environments/test.rb +0 -11
- data/test_app/config.ru +0 -6
- data/test_app/db/migrate/20260103060951_create_status.rb +0 -8
- data/test_app/db/schema.rb +0 -20
- data/test_app/db/secondary_migrate/20260104000001_create_things.rb +0 -7
- data/test_app/db/secondary_schema.rb +0 -25
- data/test_app/db/support_tables/statuses.yml +0 -19
- data/test_app/db/support_tables/things.yml +0 -5
- data/test_app/lib/tasks/database.rake +0 -11
- data/test_app/log/.keep +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6aa6d124e04e60a539f6a56207da866bb6aa0d277484104f6685d9499b41d504
|
|
4
|
+
data.tar.gz: f3c9791bf9e6b2a46416cca2a154abdb1fe18e108f3e386670818939cabac1a2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cec5bdca6906dac42489e2f43798bf647eebaf6fd1df1d314bb259cf46170c6f7833aeccd7f7d59917ea0406699f6cc99905afc5977bd907c1e19f750dc0b3e5
|
|
7
|
+
data.tar.gz: eb748280d59753b9bde5618900d0f25ae8e01c3ace0a37cdb5021cad1f1751832b14cc6e4bd624b200398178cd8bd3636e5d8d128c829180fe3c547d67ac88db
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## 1.6.0
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Added `delete_missing` option to `sync_table_data!` and `sync_all!`. When set to `true`, any records in the database that are not defined in the data files will be deleted. This option defaults to `false` to preserve backward compatibility.
|
|
12
|
+
- Each model can now choose how its YARD docs are generated by setting `self.support_table_yard_docs` to `:full` (the default — verbose comment block per method), `:compact` (shared `@!macro` definitions plus a short `@!method`/`@!macro` pair per method, dramatically reducing comment-block size on tables with many named instances), or `:none` (skip generation entirely; previously generated docs are stripped on the next run). IDEs and `yard doc` resolve the compact form into the same per-method documentation as the verbose form.
|
|
13
|
+
- Attribute helper return types in the generated YARD and RBS docs are now inferred per method by inspecting the value the helper actually returns (`String`, `Integer`, `Boolean`, etc.) instead of the generic `Object`/`untyped`. Because the helpers return frozen literals from the parsed data file, the documentation tasks no longer require a database connection.
|
|
14
|
+
- Added opt-in RBS signature generation. The new tasks `support_table_data:rbs`, `support_table_data:rbs:verify`, and `support_table_data:rbs:remove` write/check/delete `sig/<model_path>.rbs` files so the named instance helpers are visible to Ruby LSP, Steep, RubyMine, and other RBS-aware tools without polluting the model source files. The output directory can be overridden with `SupportTableData.rbs_signatures_path`.
|
|
15
|
+
|
|
16
|
+
## 1.5.2
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- Added `rubocop:disable all` around generated YARD documentation to prevent RuboCop offenses in the generated code. This ensures that the generated documentation does not cause any issues with RuboCop linting in the project.
|
|
21
|
+
|
|
7
22
|
## 1.5.1
|
|
8
23
|
|
|
9
24
|
### Added
|
data/README.md
CHANGED
|
@@ -189,7 +189,7 @@ completed:
|
|
|
189
189
|
|
|
190
190
|
In a Rails application, you can add YARD documentation for the named instance helpers by running the rake task `support_table_data:yard_docs`. This will add YARD comments to your model classes for each of the named instance helper methods defined on the model. Adding this documentation will help IDEs provide better code completion and inline documentation for the helper methods and expose the methods to AI agents.
|
|
191
191
|
|
|
192
|
-
To update a single model file, pass an optional file path argument, for example: `bundle exec rake "support_table_data:yard_docs[app/models/status.rb]"`.
|
|
192
|
+
To update a single model file, use the `add` task and pass an optional file path argument, for example: `bundle exec rake "support_table_data:yard_docs:add[app/models/status.rb]"`.
|
|
193
193
|
|
|
194
194
|
The default behavior is to add the documentation comments at the end of the model class by reopening the class definition. If you prefer to have the documentation comments appear elsewhere in the file, you can add the following markers to your model class and the YARD documentation will be inserted between these markers.
|
|
195
195
|
|
|
@@ -200,6 +200,30 @@ The default behavior is to add the documentation comments at the end of the mode
|
|
|
200
200
|
|
|
201
201
|
A good practice is to add a check to your CI pipeline to ensure the documentation is always up to date. You can run the rake task `support_table_data:yard_docs:verify` to do this. It will exit with an error if any models do not have up to date documentation.
|
|
202
202
|
|
|
203
|
+
Each model can choose how its YARD docs are generated by setting `support_table_yard_docs` to one of three values:
|
|
204
|
+
|
|
205
|
+
- `:full` — verbose comment block per generated method (the default)
|
|
206
|
+
- `:compact` — shared `@!macro` definitions at the top of the documentation block plus a short `@!method` / `@!macro` pair per generated method. IDEs and `yard doc` resolve the macros into the same per-method documentation as `:full`. Useful when a model has many named instances and the verbose comment block is too long to be useful inline.
|
|
207
|
+
- `:none` — generate no YARD docs for this model. The rake task will also strip any previously generated YARD docs from the source file.
|
|
208
|
+
|
|
209
|
+
```ruby
|
|
210
|
+
class Feature < ApplicationRecord
|
|
211
|
+
include SupportTableData
|
|
212
|
+
|
|
213
|
+
self.support_table_yard_docs = :compact
|
|
214
|
+
|
|
215
|
+
add_support_table_data "features.yml"
|
|
216
|
+
end
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Attribute helper return types (`String`, `Integer`, `Boolean`, etc.) are inferred per method by inspecting the value the helper actually returns. The values come straight from the parsed data file, so the documentation tasks do not need a database connection to run.
|
|
220
|
+
|
|
221
|
+
#### Generating RBS Signatures
|
|
222
|
+
|
|
223
|
+
In addition to the inline YARD comments, you can generate [RBS](https://github.com/ruby/rbs) type signatures for the named instance helpers by running `bundle exec rake support_table_data:rbs`. This writes one `sig/<model_path>.rbs` file per model — for example a Rails model at `app/models/feature.rb` produces `sig/app/models/feature.rbs`. The signatures are picked up by Ruby LSP, Steep, RubyMine, and any other RBS-aware tool, and they keep the model source files free of generated content.
|
|
224
|
+
|
|
225
|
+
Just like the YARD task, you can target a single file with `bundle exec rake "support_table_data:rbs:add[app/models/feature.rb]"`, verify they are up to date in CI with `support_table_data:rbs:verify`, and remove the generated files with `support_table_data:rbs:remove`. RBS generation is opt-in — running the YARD task alone does not produce RBS output, and vice versa.
|
|
226
|
+
|
|
203
227
|
### Caching
|
|
204
228
|
|
|
205
229
|
You can use the companion [support_table_cache gem](https://github.com/bdurand/support_table_cache) to add caching support to your models. That way your application won't need to constantly query the database for records that will never change.
|
|
@@ -240,6 +264,21 @@ Status.sync_table_data!
|
|
|
240
264
|
|
|
241
265
|
This will add any missing records to the table and update existing records so that the attributes in the table match the values in the data files. Records that do not appear in the data files will not be touched. Any attributes not specified in the data files will not be changed.
|
|
242
266
|
|
|
267
|
+
If you want to remove records from the database that are no longer in the data files, you can pass `delete_missing: true`:
|
|
268
|
+
|
|
269
|
+
```ruby
|
|
270
|
+
Status.sync_table_data!(delete_missing: true)
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
This option can also be passed to `SupportTableData.sync_all!`:
|
|
274
|
+
|
|
275
|
+
```ruby
|
|
276
|
+
SupportTableData.sync_all!(delete_missing: true)
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
> [!CAUTION]
|
|
280
|
+
> Use `delete_missing` with care. It will delete any records in the table that are not defined in the data files, which may include user-created data or fail due to foreign key constraints.
|
|
281
|
+
|
|
243
282
|
The number of records contained in data files should be fairly small (ideally fewer than 100). It is possible to load just a subset of rows in a large table because only the rows listed in the data files will be synced. You can use this feature if your table allows user-entered data, but has a few rows that must exist for the code to work.
|
|
244
283
|
|
|
245
284
|
Loading data is done inside a database transaction. No changes will be persisted to the database unless all rows for a model can be synced.
|
|
@@ -309,6 +348,20 @@ end
|
|
|
309
348
|
|
|
310
349
|
You must also call `SupportTableData.sync_all!` before running your test suite. This method should be called in the test suite setup code after any data in the test database has been purged and before any tests are run.
|
|
311
350
|
|
|
351
|
+
> [!TIP]
|
|
352
|
+
> If you are using a truncation database cleaning strategy exclude the support tables from the tables that get truncated. Syncing data is much faster when the data is already in the database. You should use the `delete_missing` option to remove any records that are not in the data files instead of deleting all records before each test.
|
|
353
|
+
|
|
354
|
+
```ruby
|
|
355
|
+
# Excluding support tables from truncation in DatabaseCleaner configuration.
|
|
356
|
+
RSpec.configure do |config|
|
|
357
|
+
config.before(:suite) do
|
|
358
|
+
support_tables = SupportTableData.support_table_classes.map(&:table_name)
|
|
359
|
+
DatabaseCleaner.clean_with(:truncation, except: support_tables)
|
|
360
|
+
SupportTableData.sync_all!(delete_missing: true)
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
```
|
|
364
|
+
|
|
312
365
|
## Installation
|
|
313
366
|
|
|
314
367
|
Add this line to your application's Gemfile:
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.
|
|
1
|
+
1.6.0
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SupportTableData
|
|
4
|
+
module Documentation
|
|
5
|
+
# Generates RBS type signatures for the dynamically-defined named instance
|
|
6
|
+
# helper methods on a support table model.
|
|
7
|
+
class RbsDoc
|
|
8
|
+
# @param klass [Class] The model class to generate signatures for
|
|
9
|
+
def initialize(klass)
|
|
10
|
+
@klass = klass
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Render the full RBS file content for the model, including the class
|
|
14
|
+
# declaration. Returns nil when the model has no named instances.
|
|
15
|
+
#
|
|
16
|
+
# @return [String, nil]
|
|
17
|
+
def signatures
|
|
18
|
+
instance_names = klass.instance_names
|
|
19
|
+
return nil if instance_names.empty?
|
|
20
|
+
|
|
21
|
+
body_lines = []
|
|
22
|
+
instance_names.sort.each_with_index do |name, idx|
|
|
23
|
+
body_lines << "" unless idx.zero?
|
|
24
|
+
body_lines.concat(instance_signatures(name))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
<<~RBS
|
|
28
|
+
# Generated by support_table_data - do not edit by hand.
|
|
29
|
+
# To update, run `bundle exec rake support_table_data:rbs`.
|
|
30
|
+
class #{klass.name}
|
|
31
|
+
#{body_lines.map { |line| line.empty? ? "" : " #{line}" }.join("\n")}
|
|
32
|
+
end
|
|
33
|
+
RBS
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
attr_reader :klass
|
|
39
|
+
|
|
40
|
+
def instance_signatures(name)
|
|
41
|
+
lines = []
|
|
42
|
+
lines << "def self.#{name}: () -> #{klass.name}"
|
|
43
|
+
lines << "def #{name}?: () -> bool"
|
|
44
|
+
klass.support_table_attribute_helpers.each do |attribute_name|
|
|
45
|
+
return_type = TypeInference.rbs_type(TypeInference.value_type(klass, "#{name}_#{attribute_name}"))
|
|
46
|
+
lines << "def self.#{name}_#{attribute_name}: () -> #{return_type}"
|
|
47
|
+
end
|
|
48
|
+
lines
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "pathname"
|
|
4
|
+
|
|
5
|
+
module SupportTableData
|
|
6
|
+
module Documentation
|
|
7
|
+
# Manages reading/writing the per-model RBS signature file.
|
|
8
|
+
class RbsFile
|
|
9
|
+
attr_reader :klass, :source_path, :path
|
|
10
|
+
|
|
11
|
+
# @param klass [Class] The model class
|
|
12
|
+
# @param source_path [Pathname] The path to the model's source `.rb` file
|
|
13
|
+
def initialize(klass, source_path)
|
|
14
|
+
@klass = klass
|
|
15
|
+
@source_path = Pathname.new(source_path)
|
|
16
|
+
@path = self.class.signatures_path_for(@source_path)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Compute where the RBS signatures should live for a given source file.
|
|
20
|
+
# Defaults to `<project_root>/sig/<source_path_minus_extension>.rbs`.
|
|
21
|
+
# The project root is found by walking upward looking for a `Gemfile` or
|
|
22
|
+
# `.git` directory; if neither is found, the immediate parent of the
|
|
23
|
+
# source file is used.
|
|
24
|
+
#
|
|
25
|
+
# @param source_path [Pathname]
|
|
26
|
+
# @return [Pathname]
|
|
27
|
+
def self.signatures_path_for(source_path)
|
|
28
|
+
if SupportTableData.rbs_signatures_path
|
|
29
|
+
base = Pathname.new(SupportTableData.rbs_signatures_path)
|
|
30
|
+
relative = relative_to_project_root(source_path)
|
|
31
|
+
return base.join("#{relative.to_s.sub(/\.rb\z/, "")}.rbs")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
root = project_root_for(source_path)
|
|
35
|
+
relative = source_path.expand_path.relative_path_from(root)
|
|
36
|
+
root.join("sig", "#{relative.to_s.sub(/\.rb\z/, "")}.rbs")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Project root is the nearest ancestor directory containing a Gemfile or
|
|
40
|
+
# a .git directory. Falls back to the source file's directory.
|
|
41
|
+
def self.project_root_for(source_path)
|
|
42
|
+
current = Pathname.new(source_path).expand_path.parent
|
|
43
|
+
loop do
|
|
44
|
+
return current if current.join("Gemfile").file?
|
|
45
|
+
return current if current.join(".git").exist?
|
|
46
|
+
|
|
47
|
+
parent = current.parent
|
|
48
|
+
return Pathname.new(source_path).expand_path.parent if parent == current
|
|
49
|
+
|
|
50
|
+
current = parent
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.relative_to_project_root(source_path)
|
|
55
|
+
Pathname.new(source_path).expand_path.relative_path_from(project_root_for(source_path))
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Render the desired RBS content for this model, or nil if the model has
|
|
59
|
+
# no named instances (in which case no file should be written).
|
|
60
|
+
#
|
|
61
|
+
# @return [String, nil]
|
|
62
|
+
def signatures_content
|
|
63
|
+
RbsDoc.new(klass).signatures
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Whether the existing on-disk file matches what would be generated.
|
|
67
|
+
#
|
|
68
|
+
# @return [Boolean]
|
|
69
|
+
def up_to_date?
|
|
70
|
+
desired = signatures_content
|
|
71
|
+
if desired.nil?
|
|
72
|
+
!path.file?
|
|
73
|
+
else
|
|
74
|
+
path.file? && path.read == desired
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Write the generated RBS content to disk, creating parent directories as
|
|
79
|
+
# needed. Returns true if the file was written, false if there was nothing
|
|
80
|
+
# to write.
|
|
81
|
+
#
|
|
82
|
+
# @return [Boolean]
|
|
83
|
+
def write!
|
|
84
|
+
content = signatures_content
|
|
85
|
+
return false if content.nil?
|
|
86
|
+
|
|
87
|
+
path.parent.mkpath
|
|
88
|
+
path.write(content)
|
|
89
|
+
true
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Delete the generated RBS file if it exists. Returns true if a file was
|
|
93
|
+
# removed.
|
|
94
|
+
#
|
|
95
|
+
# @return [Boolean]
|
|
96
|
+
def remove!
|
|
97
|
+
return false unless path.file?
|
|
98
|
+
|
|
99
|
+
path.delete
|
|
100
|
+
true
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -44,7 +44,9 @@ module SupportTableData
|
|
|
44
44
|
# @return [String]
|
|
45
45
|
def source_with_yard_docs
|
|
46
46
|
yard_docs = YardDoc.new(klass).named_instance_yard_docs
|
|
47
|
-
|
|
47
|
+
if yard_docs.nil?
|
|
48
|
+
return has_yard_docs? ? source_without_yard_docs : source
|
|
49
|
+
end
|
|
48
50
|
|
|
49
51
|
existing_yard_docs = source.match(YARD_COMMENT_REGEX)
|
|
50
52
|
if existing_yard_docs
|
|
@@ -55,9 +57,11 @@ module SupportTableData
|
|
|
55
57
|
updated_source = source[0, existing_yard_docs.begin(0)]
|
|
56
58
|
updated_source << "#{indent}#{BEGIN_YARD_COMMENT}\n"
|
|
57
59
|
updated_source << "#{indent}#{UPDATE_COMMAND_COMMENT}\n"
|
|
60
|
+
updated_source << "#{indent}# rubocop:disable all\n"
|
|
58
61
|
updated_source << "#{indent}class #{klass.name}\n" if has_class_def
|
|
59
62
|
updated_source << yard_docs
|
|
60
63
|
updated_source << "\n#{indent}end" if has_class_def
|
|
64
|
+
updated_source << "\n#{indent}# rubocop:enable all"
|
|
61
65
|
updated_source << "\n#{indent}#{END_YARD_COMMENT}"
|
|
62
66
|
updated_source << source[existing_yard_docs.end(0)..-1]
|
|
63
67
|
updated_source
|
|
@@ -65,9 +69,11 @@ module SupportTableData
|
|
|
65
69
|
yard_comments = <<~SOURCE.chomp("\n")
|
|
66
70
|
#{BEGIN_YARD_COMMENT}
|
|
67
71
|
#{UPDATE_COMMAND_COMMENT}
|
|
72
|
+
# rubocop:disable all
|
|
68
73
|
class #{klass.name}
|
|
69
74
|
#{yard_docs.lines.map { |line| line.blank? ? "\n" : " #{line}" }.join}
|
|
70
75
|
end
|
|
76
|
+
# rubocop:enable all
|
|
71
77
|
#{END_YARD_COMMENT}
|
|
72
78
|
SOURCE
|
|
73
79
|
"#{source.rstrip}\n\n#{yard_comments}#{trailing_newline}"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SupportTableData
|
|
4
|
+
module Documentation
|
|
5
|
+
# Infers documentation types for the dynamically-defined attribute helpers
|
|
6
|
+
# by calling the generated method and inspecting the class of the value
|
|
7
|
+
# it returns. The values returned by these helpers are frozen literals from
|
|
8
|
+
# the parsed data file, so this does not require a database connection.
|
|
9
|
+
#
|
|
10
|
+
# This module must not be used on finder helpers (e.g. `Color.red`), which
|
|
11
|
+
# call `find_by!` and would hit the database.
|
|
12
|
+
module TypeInference
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
# Determine the documentation type for an attribute helper by calling
|
|
16
|
+
# the method and looking at the class of the returned value. Returns
|
|
17
|
+
# nil when the method is not defined.
|
|
18
|
+
#
|
|
19
|
+
# @param klass [Class] The model class
|
|
20
|
+
# @param method_name [String, Symbol] The class method name to call
|
|
21
|
+
# @return [Class, nil]
|
|
22
|
+
def value_type(klass, method_name)
|
|
23
|
+
return nil unless klass.respond_to?(method_name)
|
|
24
|
+
|
|
25
|
+
klass.public_send(method_name).class
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Map a Ruby value class to a YARD type string.
|
|
29
|
+
def yard_type(value_class)
|
|
30
|
+
case value_class&.name
|
|
31
|
+
when "String" then "String"
|
|
32
|
+
when "Integer" then "Integer"
|
|
33
|
+
when "Float" then "Float"
|
|
34
|
+
when "TrueClass", "FalseClass" then "Boolean"
|
|
35
|
+
when "Array" then "Array"
|
|
36
|
+
when "Hash" then "Hash"
|
|
37
|
+
when "NilClass", nil then "Object"
|
|
38
|
+
else value_class.name
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Map a Ruby value class to an RBS type string.
|
|
43
|
+
def rbs_type(value_class)
|
|
44
|
+
case value_class&.name
|
|
45
|
+
when "String" then "String"
|
|
46
|
+
when "Integer" then "Integer"
|
|
47
|
+
when "Float" then "Float"
|
|
48
|
+
when "TrueClass", "FalseClass" then "bool"
|
|
49
|
+
when "Array" then "Array[untyped]"
|
|
50
|
+
when "Hash" then "Hash[untyped, untyped]"
|
|
51
|
+
when "NilClass", nil then "untyped"
|
|
52
|
+
else value_class.name
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -3,17 +3,38 @@
|
|
|
3
3
|
module SupportTableData
|
|
4
4
|
module Documentation
|
|
5
5
|
class YardDoc
|
|
6
|
+
MACRO_FINDER = "support_table_data_finder"
|
|
7
|
+
MACRO_PREDICATE = "support_table_data_predicate"
|
|
8
|
+
MACRO_ATTRIBUTE = "support_table_data_attribute"
|
|
9
|
+
|
|
6
10
|
# @param klass [Class] The model class to generate documentation for
|
|
7
11
|
def initialize(klass)
|
|
8
12
|
@klass = klass
|
|
9
13
|
end
|
|
10
14
|
|
|
11
|
-
# Generate YARD documentation
|
|
15
|
+
# Generate YARD documentation for the model's helper methods. The format
|
|
16
|
+
# is controlled by the model's `support_table_yard_docs` setting:
|
|
17
|
+
#
|
|
18
|
+
# * `:full` - verbose comment block per method (default)
|
|
19
|
+
# * `:compact` - shared @!macro definitions plus a short @!method/@!macro
|
|
20
|
+
# pair per generated method
|
|
21
|
+
# * `:none` - generate no docs at all
|
|
12
22
|
#
|
|
13
|
-
# @return [String, nil] The YARD documentation
|
|
23
|
+
# @return [String, nil] The YARD documentation, or nil if no docs should
|
|
24
|
+
# be emitted (either because the model has no named instances or because
|
|
25
|
+
# `support_table_yard_docs` is `:none`).
|
|
14
26
|
def named_instance_yard_docs
|
|
27
|
+
return nil if klass.support_table_yard_docs == :none
|
|
28
|
+
|
|
15
29
|
instance_names = klass.instance_names
|
|
16
|
-
|
|
30
|
+
return nil if instance_names.empty?
|
|
31
|
+
|
|
32
|
+
case klass.support_table_yard_docs
|
|
33
|
+
when :compact
|
|
34
|
+
generate_compact_yard_docs(instance_names)
|
|
35
|
+
else
|
|
36
|
+
generate_verbose_yard_docs(instance_names)
|
|
37
|
+
end
|
|
17
38
|
end
|
|
18
39
|
|
|
19
40
|
# Generate YARD documentation comment for named instance singleton method.
|
|
@@ -48,14 +69,16 @@ module SupportTableData
|
|
|
48
69
|
# Generate YARD documentation comment for the attribute method helper for the named instance.
|
|
49
70
|
#
|
|
50
71
|
# @param name [String] The name of the instance method.
|
|
72
|
+
# @param attribute_name [String] The attribute being read.
|
|
51
73
|
# @return [String] The YARD comment text
|
|
52
74
|
def attribute_helper_yard_doc(name, attribute_name)
|
|
75
|
+
return_type = attribute_yard_return_type(name, attribute_name)
|
|
53
76
|
<<~YARD.chomp("\n")
|
|
54
77
|
# Get the #{attribute_name} attribute from the data file
|
|
55
78
|
# for the named instance +#{name}+.
|
|
56
79
|
#
|
|
57
80
|
# @!method self.#{name}_#{attribute_name}
|
|
58
|
-
# @return [
|
|
81
|
+
# @return [#{return_type}]
|
|
59
82
|
# @!visibility public
|
|
60
83
|
YARD
|
|
61
84
|
end
|
|
@@ -64,12 +87,9 @@ module SupportTableData
|
|
|
64
87
|
|
|
65
88
|
attr_reader :klass
|
|
66
89
|
|
|
67
|
-
def
|
|
68
|
-
return nil if instance_names.empty?
|
|
69
|
-
|
|
90
|
+
def generate_verbose_yard_docs(instance_names)
|
|
70
91
|
yard_lines = ["# @!group Named Instances"]
|
|
71
92
|
|
|
72
|
-
# Generate docs for each named instance
|
|
73
93
|
instance_names.sort.each do |name|
|
|
74
94
|
yard_lines << ""
|
|
75
95
|
yard_lines << instance_helper_yard_doc(name)
|
|
@@ -86,6 +106,77 @@ module SupportTableData
|
|
|
86
106
|
|
|
87
107
|
yard_lines.join("\n")
|
|
88
108
|
end
|
|
109
|
+
|
|
110
|
+
def generate_compact_yard_docs(instance_names)
|
|
111
|
+
yard_lines = ["# @!group Named Instances"]
|
|
112
|
+
yard_lines << ""
|
|
113
|
+
yard_lines << compact_preamble
|
|
114
|
+
yard_lines << ""
|
|
115
|
+
yard_lines << compact_macro_definitions
|
|
116
|
+
|
|
117
|
+
instance_names.sort.each do |name|
|
|
118
|
+
yard_lines << ""
|
|
119
|
+
yard_lines << compact_instance_block(name)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
yard_lines << ""
|
|
123
|
+
yard_lines << "# @!endgroup"
|
|
124
|
+
|
|
125
|
+
yard_lines.join("\n")
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def compact_preamble
|
|
129
|
+
<<~YARD.chomp("\n")
|
|
130
|
+
# The methods in this group are dynamically defined by support_table_data
|
|
131
|
+
# for each named instance in the data file. The macros below are the
|
|
132
|
+
# documentation templates; the per-instance @!method lines that follow
|
|
133
|
+
# invoke them with the instance name (and attribute name, where applicable).
|
|
134
|
+
YARD
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def compact_macro_definitions
|
|
138
|
+
attribute_macro = <<~YARD.chomp("\n")
|
|
139
|
+
# @!macro [new] #{MACRO_ATTRIBUTE}
|
|
140
|
+
# Get the +$2+ attribute from the data file for the named instance +$1+.
|
|
141
|
+
# @return [$3]
|
|
142
|
+
# @!visibility public
|
|
143
|
+
YARD
|
|
144
|
+
|
|
145
|
+
finder_macro = <<~YARD.chomp("\n")
|
|
146
|
+
# @!macro [new] #{MACRO_FINDER}
|
|
147
|
+
# Find the named instance +$1+ from the database.
|
|
148
|
+
# @return [#{klass.name}]
|
|
149
|
+
# @raise [ActiveRecord::RecordNotFound] if the record does not exist
|
|
150
|
+
# @!visibility public
|
|
151
|
+
YARD
|
|
152
|
+
|
|
153
|
+
predicate_macro = <<~YARD.chomp("\n")
|
|
154
|
+
# @!macro [new] #{MACRO_PREDICATE}
|
|
155
|
+
# Check if this record is the named instance +$1+.
|
|
156
|
+
# @return [Boolean]
|
|
157
|
+
# @!visibility public
|
|
158
|
+
YARD
|
|
159
|
+
|
|
160
|
+
[finder_macro, "", predicate_macro, "", attribute_macro].join("\n")
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def compact_instance_block(name)
|
|
164
|
+
lines = []
|
|
165
|
+
lines << "# @!method self.#{name}"
|
|
166
|
+
lines << "# @!macro #{MACRO_FINDER} #{name}"
|
|
167
|
+
lines << "# @!method #{name}?"
|
|
168
|
+
lines << "# @!macro #{MACRO_PREDICATE} #{name}"
|
|
169
|
+
klass.support_table_attribute_helpers.each do |attribute_name|
|
|
170
|
+
return_type = attribute_yard_return_type(name, attribute_name)
|
|
171
|
+
lines << "# @!method self.#{name}_#{attribute_name}"
|
|
172
|
+
lines << "# @!macro #{MACRO_ATTRIBUTE} #{name} #{attribute_name} #{return_type}"
|
|
173
|
+
end
|
|
174
|
+
lines.join("\n")
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def attribute_yard_return_type(name, attribute_name)
|
|
178
|
+
TypeInference.yard_type(TypeInference.value_type(klass, "#{name}_#{attribute_name}"))
|
|
179
|
+
end
|
|
89
180
|
end
|
|
90
181
|
end
|
|
91
182
|
end
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
module SupportTableData
|
|
4
4
|
module Documentation
|
|
5
|
+
autoload :TypeInference, File.expand_path("documentation/type_inference", __dir__)
|
|
6
|
+
autoload :SourceFile, File.expand_path("documentation/source_file", __dir__)
|
|
7
|
+
autoload :YardDoc, File.expand_path("documentation/yard_doc", __dir__)
|
|
8
|
+
autoload :RbsDoc, File.expand_path("documentation/rbs_doc", __dir__)
|
|
9
|
+
autoload :RbsFile, File.expand_path("documentation/rbs_file", __dir__)
|
|
5
10
|
end
|
|
6
11
|
end
|
|
7
|
-
|
|
8
|
-
require_relative "documentation/source_file"
|
|
9
|
-
require_relative "documentation/yard_doc"
|
|
@@ -23,7 +23,8 @@ module SupportTableData
|
|
|
23
23
|
# @param file_path [String, Pathname, nil] Optional file path to filter by.
|
|
24
24
|
# @return [Array<SupportTableData::Documentation::SourceFile>]
|
|
25
25
|
def support_table_sources(file_path = nil)
|
|
26
|
-
|
|
26
|
+
file_path = Pathname.new(file_path) if file_path.is_a?(String)
|
|
27
|
+
require file_path.expand_path if file_path
|
|
27
28
|
|
|
28
29
|
sources = []
|
|
29
30
|
|
|
@@ -51,6 +52,16 @@ module SupportTableData
|
|
|
51
52
|
[]
|
|
52
53
|
end
|
|
53
54
|
|
|
55
|
+
# Return RBS file handlers for all support table models.
|
|
56
|
+
#
|
|
57
|
+
# @param file_path [String, Pathname, nil] Optional file path to filter by.
|
|
58
|
+
# @return [Array<SupportTableData::Documentation::RbsFile>]
|
|
59
|
+
def support_table_rbs_files(file_path = nil)
|
|
60
|
+
support_table_sources(file_path).map do |source|
|
|
61
|
+
Documentation::RbsFile.new(source.klass, source.path)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
54
65
|
def model_file_path(klass)
|
|
55
66
|
file_path = "#{klass.name.underscore}.rb"
|
|
56
67
|
model_path = nil
|
data/lib/support_table_data.rb
CHANGED
|
@@ -8,7 +8,14 @@
|
|
|
8
8
|
module SupportTableData
|
|
9
9
|
extend ActiveSupport::Concern
|
|
10
10
|
|
|
11
|
+
autoload :ValidationError, File.expand_path("support_table_data/validation_error", __dir__)
|
|
12
|
+
autoload :Documentation, File.expand_path("support_table_data/documentation", __dir__)
|
|
13
|
+
autoload :Tasks, File.expand_path("support_table_data/tasks", __dir__)
|
|
14
|
+
|
|
15
|
+
YARD_DOC_OPTIONS = [:full, :compact, :none].freeze
|
|
16
|
+
|
|
11
17
|
@data_directory = nil
|
|
18
|
+
@rbs_signatures_path = nil
|
|
12
19
|
|
|
13
20
|
included do
|
|
14
21
|
# Internal variables used for memoization.
|
|
@@ -31,6 +38,15 @@ module SupportTableData
|
|
|
31
38
|
# value set by SupportTableData.data_directory. This is only used if relative paths are passed
|
|
32
39
|
# in to add_support_table_data.
|
|
33
40
|
class_attribute :support_table_data_directory, instance_accessor: false
|
|
41
|
+
|
|
42
|
+
# Private class attribute backing `support_table_yard_docs`. Use the public
|
|
43
|
+
# accessor to read/write.
|
|
44
|
+
# @private
|
|
45
|
+
class_attribute :_support_table_yard_docs, instance_accessor: false, default: :full
|
|
46
|
+
class << self
|
|
47
|
+
private :_support_table_yard_docs=
|
|
48
|
+
private :_support_table_yard_docs
|
|
49
|
+
end
|
|
34
50
|
end
|
|
35
51
|
|
|
36
52
|
class_methods do
|
|
@@ -48,12 +64,39 @@ module SupportTableData
|
|
|
48
64
|
_support_table_key_attribute || "id"
|
|
49
65
|
end
|
|
50
66
|
|
|
67
|
+
# Get the YARD documentation mode for this model. One of:
|
|
68
|
+
#
|
|
69
|
+
# * `:full` - emit a verbose comment block per generated method (default)
|
|
70
|
+
# * `:compact` - emit shared @!macro definitions plus a short
|
|
71
|
+
# @!method/@!macro pair per generated method
|
|
72
|
+
# * `:none` - generate no YARD docs for this model; the rake task will
|
|
73
|
+
# strip any existing generated YARD docs
|
|
74
|
+
#
|
|
75
|
+
# @return [Symbol]
|
|
76
|
+
def support_table_yard_docs
|
|
77
|
+
_support_table_yard_docs
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Set the YARD documentation mode for this model. See `support_table_yard_docs`
|
|
81
|
+
# for the supported values.
|
|
82
|
+
#
|
|
83
|
+
# @param value [Symbol]
|
|
84
|
+
# @return [void]
|
|
85
|
+
def support_table_yard_docs=(value)
|
|
86
|
+
unless SupportTableData::YARD_DOC_OPTIONS.include?(value)
|
|
87
|
+
raise ArgumentError, "support_table_yard_docs must be one of #{SupportTableData::YARD_DOC_OPTIONS.inspect} (got #{value.inspect})"
|
|
88
|
+
end
|
|
89
|
+
self._support_table_yard_docs = value
|
|
90
|
+
end
|
|
91
|
+
|
|
51
92
|
# Synchronize the rows in the table with the values defined in the data files added with
|
|
52
|
-
# `add_support_table_data`.
|
|
53
|
-
#
|
|
93
|
+
# `add_support_table_data`. By default, rows that are no longer present in the data files
|
|
94
|
+
# will not be deleted unless `delete_missing` is enabled.
|
|
54
95
|
#
|
|
96
|
+
# @param delete_missing [Boolean] If true, then any records in the database that are not in the data
|
|
97
|
+
# files will be deleted. Use with caution.
|
|
55
98
|
# @return [Array<Hash>] List of saved changes for each record that was created or modified.
|
|
56
|
-
def sync_table_data!
|
|
99
|
+
def sync_table_data!(delete_missing: false)
|
|
57
100
|
return unless table_exists?
|
|
58
101
|
|
|
59
102
|
canonical_data = support_table_data.each_with_object({}) do |attributes, hash|
|
|
@@ -64,6 +107,8 @@ module SupportTableData
|
|
|
64
107
|
|
|
65
108
|
begin
|
|
66
109
|
ActiveSupport::Notifications.instrument("support_table_data.sync", class: self) do
|
|
110
|
+
synced_ids = []
|
|
111
|
+
|
|
67
112
|
transaction do
|
|
68
113
|
records.each do |record|
|
|
69
114
|
key = record[support_table_key_attribute].to_s
|
|
@@ -75,6 +120,8 @@ module SupportTableData
|
|
|
75
120
|
changes << record.changes
|
|
76
121
|
record.save!
|
|
77
122
|
end
|
|
123
|
+
|
|
124
|
+
synced_ids << record.id if attributes
|
|
78
125
|
end
|
|
79
126
|
|
|
80
127
|
canonical_data.each_value do |attributes|
|
|
@@ -86,6 +133,11 @@ module SupportTableData
|
|
|
86
133
|
end
|
|
87
134
|
changes << record.changes
|
|
88
135
|
record.save!
|
|
136
|
+
synced_ids << record.id
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
if delete_missing
|
|
140
|
+
where.not(primary_key => synced_ids).destroy_all
|
|
89
141
|
end
|
|
90
142
|
end
|
|
91
143
|
end
|
|
@@ -373,6 +425,14 @@ module SupportTableData
|
|
|
373
425
|
@data_directory = value&.to_s
|
|
374
426
|
end
|
|
375
427
|
|
|
428
|
+
# Override the directory under which generated RBS signature files are
|
|
429
|
+
# written. When nil (the default) signatures go to
|
|
430
|
+
# `<project_root>/sig/<model_path>.rbs`, where the project root is the
|
|
431
|
+
# nearest ancestor directory containing a Gemfile or .git directory.
|
|
432
|
+
#
|
|
433
|
+
# @return [String, Pathname, nil]
|
|
434
|
+
attr_accessor :rbs_signatures_path
|
|
435
|
+
|
|
376
436
|
# Sync all support table classes. Classes must already be loaded in order to be synced.
|
|
377
437
|
#
|
|
378
438
|
# You can pass in a list of classes that you want to ensure are synced. This feature
|
|
@@ -382,11 +442,13 @@ module SupportTableData
|
|
|
382
442
|
# when the test suite is initializing.
|
|
383
443
|
#
|
|
384
444
|
# @param extra_classes [Class] List of classes to force into the detected list of classes to sync.
|
|
445
|
+
# @param delete_missing [Boolean] If true, then any records in the database that are not in the data
|
|
446
|
+
# files will be deleted from each table. Use with caution.
|
|
385
447
|
# @return [Hash<Class, Array<Hash>] Hash of classes synced with a list of saved changes.
|
|
386
|
-
def sync_all!(*extra_classes)
|
|
448
|
+
def sync_all!(*extra_classes, delete_missing: false)
|
|
387
449
|
changes = {}
|
|
388
450
|
support_table_classes(*extra_classes).each do |klass|
|
|
389
|
-
changes[klass] = klass.sync_table_data!
|
|
451
|
+
changes[klass] = klass.sync_table_data!(delete_missing: delete_missing)
|
|
390
452
|
end
|
|
391
453
|
changes
|
|
392
454
|
end
|
|
@@ -483,8 +545,6 @@ module SupportTableData
|
|
|
483
545
|
end
|
|
484
546
|
end
|
|
485
547
|
|
|
486
|
-
require_relative "support_table_data/validation_error"
|
|
487
|
-
|
|
488
548
|
if defined?(Rails::Railtie)
|
|
489
549
|
require_relative "support_table_data/railtie"
|
|
490
550
|
end
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
namespace :support_table_data do
|
|
4
|
-
desc "
|
|
4
|
+
desc "Synchronize data for all models that include SupportTableData."
|
|
5
5
|
task sync: :environment do
|
|
6
|
-
require_relative "utils"
|
|
7
|
-
|
|
8
6
|
SupportTableData::Tasks::Utils.eager_load!
|
|
9
7
|
|
|
10
8
|
logger_callback = lambda do |name, started, finished, unique_id, payload|
|
|
@@ -23,14 +21,12 @@ namespace :support_table_data do
|
|
|
23
21
|
end
|
|
24
22
|
end
|
|
25
23
|
|
|
24
|
+
desc "Adds YARD documentation comments to all support table models to document the named instance methods."
|
|
26
25
|
task yard_docs: "yard_docs:add"
|
|
27
26
|
|
|
28
27
|
namespace :yard_docs do
|
|
29
28
|
desc "Adds YARD documentation comments to models to document the named instance methods. Optional arg: file_path"
|
|
30
29
|
task :add, [:file_path] => :environment do |_task, args|
|
|
31
|
-
require_relative "../support_table_data/documentation"
|
|
32
|
-
require_relative "utils"
|
|
33
|
-
|
|
34
30
|
SupportTableData::Tasks::Utils.eager_load!
|
|
35
31
|
SupportTableData::Tasks::Utils.support_table_sources(args[:file_path]).each do |source_file|
|
|
36
32
|
next if source_file.yard_docs_up_to_date?
|
|
@@ -42,9 +38,6 @@ namespace :support_table_data do
|
|
|
42
38
|
|
|
43
39
|
desc "Removes YARD documentation comments added by support_table_data from models. Optional arg: file_path"
|
|
44
40
|
task :remove, [:file_path] => :environment do |_task, args|
|
|
45
|
-
require_relative "../support_table_data/documentation"
|
|
46
|
-
require_relative "utils"
|
|
47
|
-
|
|
48
41
|
SupportTableData::Tasks::Utils.eager_load!
|
|
49
42
|
SupportTableData::Tasks::Utils.support_table_sources(args[:file_path]).each do |source_file|
|
|
50
43
|
next unless source_file.has_yard_docs?
|
|
@@ -56,9 +49,6 @@ namespace :support_table_data do
|
|
|
56
49
|
|
|
57
50
|
desc "Verify that support table models have up to date YARD docs for named instance methods. Optional arg: file_path"
|
|
58
51
|
task :verify, [:file_path] => :environment do |_task, args|
|
|
59
|
-
require_relative "../support_table_data/documentation"
|
|
60
|
-
require_relative "utils"
|
|
61
|
-
|
|
62
52
|
SupportTableData::Tasks::Utils.eager_load!
|
|
63
53
|
|
|
64
54
|
all_up_to_date = true
|
|
@@ -80,4 +70,53 @@ namespace :support_table_data do
|
|
|
80
70
|
end
|
|
81
71
|
end
|
|
82
72
|
end
|
|
73
|
+
|
|
74
|
+
desc "Generates RBS signature files for named instance methods in all support table models."
|
|
75
|
+
task rbs: "rbs:add"
|
|
76
|
+
|
|
77
|
+
namespace :rbs do
|
|
78
|
+
desc "Generates RBS signature files for named instance methods. Optional arg: file_path"
|
|
79
|
+
task :add, [:file_path] => :environment do |_task, args|
|
|
80
|
+
SupportTableData::Tasks::Utils.eager_load!
|
|
81
|
+
SupportTableData::Tasks::Utils.support_table_rbs_files(args[:file_path]).each do |rbs_file|
|
|
82
|
+
next if rbs_file.up_to_date?
|
|
83
|
+
|
|
84
|
+
rbs_file.write!
|
|
85
|
+
puts "Wrote RBS signatures for #{rbs_file.klass.name} to #{rbs_file.path}."
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
desc "Removes generated RBS signature files. Optional arg: file_path"
|
|
90
|
+
task :remove, [:file_path] => :environment do |_task, args|
|
|
91
|
+
SupportTableData::Tasks::Utils.eager_load!
|
|
92
|
+
SupportTableData::Tasks::Utils.support_table_rbs_files(args[:file_path]).each do |rbs_file|
|
|
93
|
+
next unless rbs_file.remove!
|
|
94
|
+
|
|
95
|
+
puts "Removed RBS signatures for #{rbs_file.klass.name} (#{rbs_file.path})."
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
desc "Verify that generated RBS signature files are up to date. Optional arg: file_path"
|
|
100
|
+
task :verify, [:file_path] => :environment do |_task, args|
|
|
101
|
+
SupportTableData::Tasks::Utils.eager_load!
|
|
102
|
+
|
|
103
|
+
all_up_to_date = true
|
|
104
|
+
SupportTableData::Tasks::Utils.support_table_rbs_files(args[:file_path]).each do |rbs_file|
|
|
105
|
+
unless rbs_file.up_to_date?
|
|
106
|
+
puts "RBS signatures are not up to date for #{rbs_file.klass.name} (#{rbs_file.path})."
|
|
107
|
+
all_up_to_date = false
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
if all_up_to_date
|
|
112
|
+
if args[:file_path]
|
|
113
|
+
puts "RBS signatures are up to date for #{args[:file_path]}."
|
|
114
|
+
else
|
|
115
|
+
puts "All support table models have up to date RBS signatures."
|
|
116
|
+
end
|
|
117
|
+
else
|
|
118
|
+
raise "Run bundle exec rake support_table_data:rbs to update the signatures."
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
83
122
|
end
|
data/support_table_data.gemspec
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: support_table_data
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brian Durand
|
|
@@ -50,36 +50,17 @@ files:
|
|
|
50
50
|
- VERSION
|
|
51
51
|
- lib/support_table_data.rb
|
|
52
52
|
- lib/support_table_data/documentation.rb
|
|
53
|
+
- lib/support_table_data/documentation/rbs_doc.rb
|
|
54
|
+
- lib/support_table_data/documentation/rbs_file.rb
|
|
53
55
|
- lib/support_table_data/documentation/source_file.rb
|
|
56
|
+
- lib/support_table_data/documentation/type_inference.rb
|
|
54
57
|
- lib/support_table_data/documentation/yard_doc.rb
|
|
55
58
|
- lib/support_table_data/railtie.rb
|
|
59
|
+
- lib/support_table_data/tasks.rb
|
|
60
|
+
- lib/support_table_data/tasks/utils.rb
|
|
56
61
|
- lib/support_table_data/validation_error.rb
|
|
57
62
|
- lib/tasks/support_table_data.rake
|
|
58
|
-
- lib/tasks/utils.rb
|
|
59
63
|
- support_table_data.gemspec
|
|
60
|
-
- test_app/.gitignore
|
|
61
|
-
- test_app/Gemfile
|
|
62
|
-
- test_app/Rakefile
|
|
63
|
-
- test_app/app/models/application_record.rb
|
|
64
|
-
- test_app/app/models/secondary_application_record.rb
|
|
65
|
-
- test_app/app/models/status.rb
|
|
66
|
-
- test_app/app/models/thing.rb
|
|
67
|
-
- test_app/bin/rails
|
|
68
|
-
- test_app/config.ru
|
|
69
|
-
- test_app/config/application.rb
|
|
70
|
-
- test_app/config/boot.rb
|
|
71
|
-
- test_app/config/database.yml
|
|
72
|
-
- test_app/config/environment.rb
|
|
73
|
-
- test_app/config/environments/development.rb
|
|
74
|
-
- test_app/config/environments/test.rb
|
|
75
|
-
- test_app/db/migrate/20260103060951_create_status.rb
|
|
76
|
-
- test_app/db/schema.rb
|
|
77
|
-
- test_app/db/secondary_migrate/20260104000001_create_things.rb
|
|
78
|
-
- test_app/db/secondary_schema.rb
|
|
79
|
-
- test_app/db/support_tables/statuses.yml
|
|
80
|
-
- test_app/db/support_tables/things.yml
|
|
81
|
-
- test_app/lib/tasks/database.rake
|
|
82
|
-
- test_app/log/.keep
|
|
83
64
|
homepage: https://github.com/bdurand/support_table_data
|
|
84
65
|
licenses:
|
|
85
66
|
- MIT
|
|
@@ -101,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
101
82
|
- !ruby/object:Gem::Version
|
|
102
83
|
version: '0'
|
|
103
84
|
requirements: []
|
|
104
|
-
rubygems_version:
|
|
85
|
+
rubygems_version: 3.6.9
|
|
105
86
|
specification_version: 4
|
|
106
87
|
summary: Extension for ActiveRecord models to manage synchronizing data in support/lookup
|
|
107
88
|
tables across environments. Also provides the ability to directly reference and
|
data/test_app/.gitignore
DELETED
data/test_app/Gemfile
DELETED
data/test_app/Rakefile
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
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
|
|
12
|
-
|
|
13
|
-
# Begin YARD docs for support_table_data
|
|
14
|
-
# To update these docs, run `bundle exec rake support_table_data:yard_docs`
|
|
15
|
-
class Status
|
|
16
|
-
# @!group Named Instances
|
|
17
|
-
|
|
18
|
-
# Find the named instance +active+ from the database.
|
|
19
|
-
#
|
|
20
|
-
# @!method self.active
|
|
21
|
-
# @return [Status]
|
|
22
|
-
# @raise [ActiveRecord::RecordNotFound] if the record does not exist
|
|
23
|
-
# @!visibility public
|
|
24
|
-
|
|
25
|
-
# Check if this record is the named instance +active+.
|
|
26
|
-
#
|
|
27
|
-
# @!method active?
|
|
28
|
-
# @return [Boolean]
|
|
29
|
-
# @!visibility public
|
|
30
|
-
|
|
31
|
-
# Get the name attribute from the data file
|
|
32
|
-
# for the named instance +active+.
|
|
33
|
-
#
|
|
34
|
-
# @!method self.active_name
|
|
35
|
-
# @return [Object]
|
|
36
|
-
# @!visibility public
|
|
37
|
-
|
|
38
|
-
# Find the named instance +canceled+ from the database.
|
|
39
|
-
#
|
|
40
|
-
# @!method self.canceled
|
|
41
|
-
# @return [Status]
|
|
42
|
-
# @raise [ActiveRecord::RecordNotFound] if the record does not exist
|
|
43
|
-
# @!visibility public
|
|
44
|
-
|
|
45
|
-
# Check if this record is the named instance +canceled+.
|
|
46
|
-
#
|
|
47
|
-
# @!method canceled?
|
|
48
|
-
# @return [Boolean]
|
|
49
|
-
# @!visibility public
|
|
50
|
-
|
|
51
|
-
# Get the name attribute from the data file
|
|
52
|
-
# for the named instance +canceled+.
|
|
53
|
-
#
|
|
54
|
-
# @!method self.canceled_name
|
|
55
|
-
# @return [Object]
|
|
56
|
-
# @!visibility public
|
|
57
|
-
|
|
58
|
-
# Find the named instance +completed+ from the database.
|
|
59
|
-
#
|
|
60
|
-
# @!method self.completed
|
|
61
|
-
# @return [Status]
|
|
62
|
-
# @raise [ActiveRecord::RecordNotFound] if the record does not exist
|
|
63
|
-
# @!visibility public
|
|
64
|
-
|
|
65
|
-
# Check if this record is the named instance +completed+.
|
|
66
|
-
#
|
|
67
|
-
# @!method completed?
|
|
68
|
-
# @return [Boolean]
|
|
69
|
-
# @!visibility public
|
|
70
|
-
|
|
71
|
-
# Get the name attribute from the data file
|
|
72
|
-
# for the named instance +completed+.
|
|
73
|
-
#
|
|
74
|
-
# @!method self.completed_name
|
|
75
|
-
# @return [Object]
|
|
76
|
-
# @!visibility public
|
|
77
|
-
|
|
78
|
-
# Find the named instance +failed+ from the database.
|
|
79
|
-
#
|
|
80
|
-
# @!method self.failed
|
|
81
|
-
# @return [Status]
|
|
82
|
-
# @raise [ActiveRecord::RecordNotFound] if the record does not exist
|
|
83
|
-
# @!visibility public
|
|
84
|
-
|
|
85
|
-
# Check if this record is the named instance +failed+.
|
|
86
|
-
#
|
|
87
|
-
# @!method failed?
|
|
88
|
-
# @return [Boolean]
|
|
89
|
-
# @!visibility public
|
|
90
|
-
|
|
91
|
-
# Get the name attribute from the data file
|
|
92
|
-
# for the named instance +failed+.
|
|
93
|
-
#
|
|
94
|
-
# @!method self.failed_name
|
|
95
|
-
# @return [Object]
|
|
96
|
-
# @!visibility public
|
|
97
|
-
|
|
98
|
-
# Find the named instance +pending+ from the database.
|
|
99
|
-
#
|
|
100
|
-
# @!method self.pending
|
|
101
|
-
# @return [Status]
|
|
102
|
-
# @raise [ActiveRecord::RecordNotFound] if the record does not exist
|
|
103
|
-
# @!visibility public
|
|
104
|
-
|
|
105
|
-
# Check if this record is the named instance +pending+.
|
|
106
|
-
#
|
|
107
|
-
# @!method pending?
|
|
108
|
-
# @return [Boolean]
|
|
109
|
-
# @!visibility public
|
|
110
|
-
|
|
111
|
-
# Get the name attribute from the data file
|
|
112
|
-
# for the named instance +pending+.
|
|
113
|
-
#
|
|
114
|
-
# @!method self.pending_name
|
|
115
|
-
# @return [Object]
|
|
116
|
-
# @!visibility public
|
|
117
|
-
|
|
118
|
-
# @!endgroup
|
|
119
|
-
end
|
|
120
|
-
# End YARD docs for support_table_data
|
data/test_app/bin/rails
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
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
|
data/test_app/config/boot.rb
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
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
|
|
@@ -1,11 +0,0 @@
|
|
|
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
|
|
@@ -1,11 +0,0 @@
|
|
|
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
|
data/test_app/config.ru
DELETED
data/test_app/db/schema.rb
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
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
|
|
@@ -1,25 +0,0 @@
|
|
|
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
|
|
@@ -1,11 +0,0 @@
|
|
|
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
|
data/test_app/log/.keep
DELETED
|
File without changes
|