support_table 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e6446caaf1ed0561e4fc98214a72e30fae6fc70aa7ef868aa6e6a17f4dc4f621
4
+ data.tar.gz: 9f7739af82443b3279bf74cb1262370284fc0c3554f42a3dc1d5d254c176d4a5
5
+ SHA512:
6
+ metadata.gz: ddb606d4d8674bb335dad19888ee531aafe2d8790396bbfde7ab6ea574fb20b3b01aa0d599ac2f43720d6ecca1709f0318c2ab42f4f9749c259f1b75462ae451
7
+ data.tar.gz: 22cfa034d8062e57d5e7eff49a532f97d293bb2a7847392f57388ebc7e40530df91dfd452be58131e45c3fd6798a39bcb3215a5d8775307e878e0fd19327ac05
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## 1.0.0
8
+
9
+ ### Added
10
+
11
+ - Initial release.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2026 Brian Durand
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,377 @@
1
+ # Support Table
2
+
3
+ [![Continuous Integration](https://github.com/bdurand/support_table/actions/workflows/continuous_integration.yml/badge.svg)](https://github.com/bdurand/support_table/actions/workflows/continuous_integration.yml)
4
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
5
+ [![Gem Version](https://badge.fury.io/rb/support_table.svg)](https://badge.fury.io/rb/support_table)
6
+
7
+ This gem builds on top of the [support_table_data](https://github.com/bdurand/support_table_data) and [support_table_cache](https://github.com/bdurand/support_table_cache) gems to provide a pre-configured, drop-in solution for maintaining and using support tables in a Rails application.
8
+
9
+ Support tables are small database tables that contain static data that rarely changes. They are often used to represent enumerations or lookup values in an application and values are often referenced directly from code.
10
+
11
+ This gem provides a simple DSL for defining your Rails models as support tables. When a model is defined as a support table
12
+
13
+ - the data for the table can be defined in a YAML file and distributed with the code
14
+ - helper methods can be generated to allow code to reference specific rows from the table
15
+ - lookups from the table will use caching to avoid querying the database repeatedly for data that rarely changes
16
+
17
+ If you have more advanced needs, you can use the [support_table_data](https://github.com/bdurand/support_table_data) and [support_table_cache](https://github.com/bdurand/support_table_cache) gems directly or in combination with this gem.
18
+
19
+ ## Table of Contents
20
+
21
+ - [Usage](#usage)
22
+ - [Defining Support Table Data](#defining-support-table-data)
23
+ - [Advanced Data Settings](#advanced-data-settings)
24
+ - [Key Attribute](#key-attribute)
25
+ - [Data File](#data-file)
26
+ - [Additional Helper Methods](#additional-helper-methods)
27
+ - [Documenting Helper Methods](#documenting-helper-methods)
28
+ - [More Data Options](#more-data-options)
29
+ - [Caching](#caching)
30
+ - [Specifying Additional Cache Keys](#specifying-additional-cache-keys)
31
+ - [Changing The Cache Implementation](#changing-the-cache-implementation)
32
+ - [Cache TTL](#cache-ttl)
33
+ - [Belongs To Caching](#belongs-to-caching)
34
+ - [More Cache Options](#more-cache-options)
35
+ - [Full Example](#full-example)
36
+ - [Installation](#installation)
37
+ - [Contributing](#contributing)
38
+ - [License](#license)
39
+
40
+ ## Usage
41
+
42
+ Start by including the `SupportTable` concern in your `ApplicationRecord` base model.
43
+
44
+ ```ruby
45
+ class ApplicationRecord < ActiveRecord::Base
46
+ self.abstract_class = true
47
+
48
+ include SupportTable
49
+ end
50
+ ```
51
+
52
+ This will add DSL methods to your models for defining support tables and associations to them.
53
+
54
+ ```ruby
55
+ class Status < ApplicationRecord
56
+ support_table
57
+ end
58
+
59
+ class Task < ApplicationRecord
60
+ belongs_to_support_table :status
61
+ end
62
+ ```
63
+
64
+ ### Defining Support Table Data
65
+
66
+ You can define the data for your support table in the `db/support_tables` directory in a YAML file. The file name should match the model name in plural form. For the `Status` model, the file would be `db/support_tables/statuses.yml`.
67
+
68
+ > [!NOTE]
69
+ > If the model is in a namespace, the directory structure should reflect that (e.g. `Status::Group` data would be defined in the `db/support_tables/status/groups.yml` file).
70
+
71
+ ```yaml
72
+ draft:
73
+ id: 1
74
+ name: Draft
75
+
76
+ pending:
77
+ id: 2
78
+ name: Pending
79
+
80
+ in_progress:
81
+ id: 3
82
+ name: In Progress
83
+
84
+ completed:
85
+ id: 4
86
+ name: Completed
87
+ ```
88
+
89
+ The keys in the YAML file are named instances of the model. These will dynamically generate helper methods to load the instance and to test if a value is that instance.
90
+
91
+ ```ruby
92
+ Status.draft # returns the Status instance with name "Draft"
93
+
94
+ task.status.draft? # returns true if the task's status is "Draft"
95
+ ```
96
+
97
+ Data will be automatically synced to the database whenever you run any of the following rake tasks:
98
+
99
+ - `db:seed`
100
+ - `db:seed:replant`
101
+ - `db:prepare`
102
+ - `db:test:prepare`
103
+ - `db:fixtures:load`
104
+
105
+ You can also manually trigger synchronization with the `support_table_data:sync` rake task.
106
+
107
+ You **must** popululate the support table data in your test database during your deploy process or test suite setup to ensure that the data is present when your application code runs.
108
+
109
+ > [!TIP]
110
+ > You can also call `SupportTable.sync_all!` in from your application code to synchronize the data.
111
+
112
+ #### Advanced Data Settings
113
+
114
+ You can customize the behavior of the support table data syncing by passing options to the `support_table` method.
115
+
116
+ ##### Key Attribute
117
+
118
+ One of the attributes on the table will be used as the unique identifier for each row in the YAML file. By default, this is will be the primary key on the table. You can set a different attribute by passing the `key_attribute` option.
119
+
120
+ ```ruby
121
+ class Status < ApplicationRecord
122
+ support_table key_attribute: :name
123
+ end
124
+ ```
125
+
126
+ > [!TIP]
127
+ > If you are starting from scratch, the primary key is the best choice for the key attribute. If all of the data in the table will be specified in the YAML file, you should turn off auto incrementing primary keys with `auto_increment: false` on the `create_table` statement.
128
+ >
129
+ > If you are adding support table behavior to an existing table, you may need to use an existing unique attribute instead especially if the primary key is not identical in the existing environments.
130
+ >
131
+ > Make sure that the attribute you choose has a unique index on it to ensure data integrity and that the values will never need to change. Using a display attribute can be problematic if it ever needs to change. It's best to add a new internal identifier attribute if needed (i.e. add a `code` attribute instead of using the `name` attribute if the `name` might ever change).
132
+
133
+ #### Data File
134
+
135
+ You can customize the location of the YAML data file by passing the `data_file` option to the `support_table` method.
136
+
137
+ ```ruby
138
+ class Status < ApplicationRecord
139
+ support_table data_file: "custom/statuses.yml"
140
+ end
141
+ ```
142
+
143
+ You can also change the base directory for all support table data files by setting `SupportTable.data_directory` in your application configuration (e.g., in an initializer).
144
+
145
+ ```ruby
146
+ # config/initializers/support_table.rb
147
+ SupportTable.data_directory = Rails.root.join("db", "support_tables")
148
+ ```
149
+
150
+ #### Additional Helper Methods
151
+
152
+ You can add additional helper methods to your support table models by passing `attribute_helpers` to the `support_table` method.
153
+
154
+ ```ruby
155
+ class Status < ApplicationRecord
156
+ support_table attribute_helpers: [:name]
157
+ end
158
+ ```
159
+
160
+ This will add class methods to the class to reference values directly from the YAML file. You automatically get helper methods for the key attribute defined for the table.
161
+
162
+ ```ruby
163
+ Status.draft_name # returns "Draft"
164
+ Status.pending_name # returns "Pending"
165
+
166
+ Status.draft_id # returns 1
167
+ Status.pending_id # returns 2
168
+ ```
169
+
170
+ These helper methods do not need to hit the database and so can be used in situations where the database is not available (i.e. during application initialization).
171
+
172
+ > [!TIP]
173
+ > You use these methods in lieu of hard coding values in the code or defining constants. This keeps all of the support table data defined in one place (the YAML file) and avoids duplication.
174
+
175
+ #### Documenting Helper Methods
176
+
177
+ You can generate YARD documentation for the dynamically generated helper methods by running the rake task `support_table_data:yard_docs:add`. This will add YARD comments to you support table models for the named instance helper methods (i.e. `Status.draft`, etc.). This exposes these methods in your source code for other developers and AI agents to see.
178
+
179
+ You can also run the `support_table_data:yard_docs:verify` rake task in your CI pipeline to ensure that the documentation is up to date. This task will fail if the documentation is missing or out of date.
180
+
181
+ #### More Data Options
182
+
183
+ See the [support_table_data](https://github.com/bdurand/support_table_data) gem for more details on defining support table data.
184
+
185
+ You can use any of the DSL methods defined in that gem to further customize how data is loaded.
186
+
187
+ ### Caching
188
+
189
+ Support table data is often read frequently but changes rarely. To improve performance, lookups from support tables by the key attribute are cached by default. Any query that queries a record by the key attribute (i.e. `find_by(name: "Draft")` if `name` is the key attribute) will use the cache. The `id` column is also always cacheable so `find(1)` or `find_by(id: 1)` will also use the cache.
190
+
191
+ You can use the `fetch_by` method to better express in your code that the lookup is using a cache. This method is an alias for `find_by` except that it will raise an error if the lookup is not using a cache on that attribute.
192
+
193
+ ```ruby
194
+ # Uses the cache or raise an error if the model does not support caching by `name`.
195
+ Status.fetch_by(name: "Draft")
196
+ ```
197
+
198
+ #### Specifying Additional Cache Keys
199
+
200
+ You can also manually specify the attributes that can be used for caching by passing the `cache_by` option to the `support_table` method.
201
+
202
+ ```ruby
203
+ class Status < ApplicationRecord
204
+ support_table cache_by: :name # uses both id and name for caching
205
+ end
206
+ ```
207
+
208
+ You can even specify composite keys with the `cache_by` method.
209
+
210
+ ```ruby
211
+ create_table :statuses do |t|
212
+ t.string :name, null: false
213
+ t.string :group, null: false
214
+ t.index [:name, :group], unique: true
215
+ end
216
+
217
+ class Status < ApplicationRecord
218
+ support_table
219
+ cache_by [:name, :group]
220
+ end
221
+
222
+ Status.fetch_by(name: "Draft", group: "Non-Live") # Uses the cache
223
+ ```
224
+
225
+ #### Changing The Cache Implementation
226
+
227
+ The default caching implementation uses an in memory cache that stores rows in local memory for the lifetime of the application process. This is the most efficient caching strategy for most use cases. If you need a different caching strategy, you can customize it by passing an implementation of `ActiveSupport::Cache::Store` to the `cache` option of the `support_table` method.
228
+
229
+ ```ruby
230
+ class Status < ApplicationRecord
231
+ # Use the application cache for caching.
232
+ support_table cache: Rails.cache
233
+ end
234
+ ```
235
+
236
+ You can also disable caching entirely by passing `cache: false` or `cache: nil`.
237
+
238
+ ```ruby
239
+ class Status < ApplicationRecord
240
+ # Disable caching.
241
+ support_table cache: false
242
+ end
243
+ ```
244
+
245
+ You can specify the value `:memory` to use an in memory cache. This is the default behavior.
246
+
247
+ ```ruby
248
+ class Status < ApplicationRecord
249
+ # Use an in memory cache.
250
+ support_table cache: :memory
251
+ end
252
+ ```
253
+
254
+ #### Cache TTL
255
+
256
+ By default, cached records are stored indefinitely (until the application process restarts or the cache is cleared). You can set a time-to-live (TTL) for cached records by passing the `ttl` option to the `support_table` method.
257
+
258
+ ```ruby
259
+ class Status < ApplicationRecord
260
+ # Cache records for 1 hour.
261
+ support_table ttl: 1.hour
262
+ end
263
+ ```
264
+
265
+ The TTL value should be a number of seconds or an `ActiveSupport::Duration` object. When a cached record expires, it will be reloaded from the database on the next access.
266
+
267
+ > [!TIP]
268
+ > For most support tables, you don't need to set a TTL since the data rarely changes. An in-memory cache without a TTL is the most performant option. Only set a TTL if you need to ensure the data is refreshed periodically.
269
+
270
+ #### Belongs To Caching
271
+
272
+ When you have another model with a `belongs_to` association to a support table, you can use the `belongs_to_support_table` method to define the association. This will ensure that lookups for the associated support table record will use the cache.
273
+
274
+ ```ruby
275
+ class Task < ApplicationRecord
276
+ belongs_to_support_table :status
277
+ end
278
+ ```
279
+
280
+ This method works exactly like the standard `belongs_to` method except that it ensures that lookups for the associated support table record will use the cache.
281
+
282
+ #### More Cache Options
283
+
284
+ See the [support_table_cache](https://github.com/bdurand/support_table_cache) gem for more details on caching support table data.
285
+
286
+ You can use any of the DSL methods defined in that gem to further customize how models are cached.
287
+
288
+ ### Full Example
289
+
290
+ For this example, we'll start with a simple application for managing a list of tasks. Each task will have a status.
291
+
292
+ First, let's start with the table definitions.
293
+
294
+ ```ruby
295
+ create_table :statuses do |t|
296
+ t.string :name, null: false, index: {unique: true}
297
+ t.timestamps
298
+ end
299
+
300
+ create_table :tasks do |t|
301
+ t.integer :status_id, null: false, index: true
302
+ t.string :description, null: false
303
+ t.timestamps
304
+ end
305
+ ```
306
+
307
+ First, you need to include the `SupportTable` concern in your `ApplicationRecord` so that all models have access to it.
308
+
309
+ ```ruby
310
+ class ApplicationRecord < ActiveRecord::Base
311
+ self.abstract_class = true
312
+
313
+ include SupportTable
314
+ end
315
+ ```
316
+
317
+ This will add DSL methods to your models for defining support tables and associations to them.
318
+
319
+ ```ruby
320
+ class Status < ApplicationRecord
321
+ support_table
322
+ end
323
+
324
+ class Task < ApplicationRecord
325
+ belongs_to_support_table :status
326
+ end
327
+ ```
328
+
329
+ Next add the YAML file at `db/support_tables/statuses.yml` to define the data that should be in the `statuses` table.
330
+
331
+ ```yaml
332
+ draft:
333
+ id: 1
334
+ name: Draft
335
+
336
+ pending:
337
+ id: 2
338
+ name: Pending
339
+
340
+ in_progress:
341
+ id: 3
342
+ name: In Progress
343
+
344
+ finished:
345
+ id: 4
346
+ name: Finished
347
+ ```
348
+
349
+ That's it. Now the `Status` will load data from a YAML file and cache lookups automatically including from the `Task#status` association.
350
+
351
+ ## Installation
352
+
353
+ Add this line to your application's Gemfile:
354
+
355
+ ```ruby
356
+ gem "support_table"
357
+ ```
358
+
359
+ Then execute:
360
+ ```bash
361
+ $ bundle
362
+ ```
363
+
364
+ Or install it yourself as:
365
+ ```bash
366
+ $ gem install support_table
367
+ ```
368
+
369
+ ## Contributing
370
+
371
+ Open a pull request on [GitHub](https://github.com/bdurand/support_table).
372
+
373
+ Please use the [standardrb](https://github.com/testdouble/standard) syntax and lint your code with `standardrb --fix` before submitting.
374
+
375
+ ## License
376
+
377
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SupportTable
4
+ # Module to add support for specifying `belongs_to` associations that
5
+ # reference support tables.
6
+ module BelongsToSupportTable
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ # Define a `belongs_to` association that references a support table. This method takes
11
+ # the same arguments as `belongs_to`. It will add a caching layer to the association
12
+ # to minimize database queries.
13
+ #
14
+ # @param name [Symbol] The name of the association.
15
+ # @param args [Array] Additional arguments to pass to `belongs_to`.
16
+ # @param kwargs [Hash] Additional keyword arguments to pass to `belongs_to`.
17
+ # @return [void]
18
+ def belongs_to_support_table(name, *args, **kwargs)
19
+ unless include?(SupportTableCache::Associations)
20
+ include SupportTableCache::Associations
21
+ end
22
+
23
+ retval = belongs_to name, *args, **kwargs
24
+ cache_belongs_to name
25
+ retval
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_leteral: true
2
+
3
+ module SupportTable
4
+ # Class to define support table behavior on an ActiveRecord class.
5
+ #
6
+ # @api private
7
+ class Definition
8
+ attr_reader :klass
9
+
10
+ def initialize(klass)
11
+ @klass = klass
12
+ end
13
+
14
+ # Setup a class to be a support table.
15
+ #
16
+ # @param data_file [String, Array<String>, nil] Path to data files to load the table from.
17
+ # @param key_attribute [String, Symbol, nil] The name of the attribute in the data file that
18
+ # uniquely identifies each row in the data.
19
+ # @param cache_by [String, Symbol, Array, nil] List of attributes that can be used to uniquely
20
+ # identify a row that can be used for caching records.
21
+ # @param cache [ActiveSupport::Cache::Store, Symbol, Boolean, nil] The caching mechanism to use.
22
+ # @param ttl [Numeric, ActiveSupport::Duration, nil] The time-to-live (in seconds) for cached records.
23
+ # @return [void]
24
+ def support_table(data_file:, key_attribute:, attribute_helpers:, cache_by:, cache:, ttl:)
25
+ include_modules
26
+ set_key_attribute(key_attribute)
27
+ set_attribute_helpers(attribute_helpers)
28
+ set_data_file(data_file)
29
+ setup_caching(cache_by, cache, ttl)
30
+ end
31
+
32
+ private
33
+
34
+ def include_modules
35
+ klass.include SupportTableData unless klass.include?(SupportTableData)
36
+ klass.include SupportTableCache unless klass.include?(SupportTableCache)
37
+ end
38
+
39
+ def set_key_attribute(key_attribute)
40
+ klass.support_table_key_attribute = key_attribute if key_attribute
41
+ end
42
+
43
+ def set_attribute_helpers(attribute_helpers)
44
+ helpers = [klass.support_table_key_attribute]
45
+ helpers.concat(Array(attribute_helpers)) if attribute_helpers
46
+ klass.named_instance_attribute_helpers(*helpers.uniq.compact)
47
+ end
48
+
49
+ def set_data_file(data_file)
50
+ if data_file
51
+ Array(data_file).each do |file|
52
+ klass.add_support_table_data(file)
53
+ end
54
+ elsif data_file.nil?
55
+ data_root_dir = klass.support_table_data_directory || SupportTableData.data_directory || Dir.pwd
56
+ default_data_file = File.join(data_root_dir, "#{klass.name.pluralize.underscore}.yml")
57
+ if File.exist?(default_data_file)
58
+ klass.add_support_table_data(default_data_file)
59
+ end
60
+ end
61
+ end
62
+
63
+ def setup_caching(cache_by, cache, ttl)
64
+ if cache == false
65
+ klass.send(:cache_by, false)
66
+ return
67
+ end
68
+
69
+ cache_keys = [klass.support_table_key_attribute, "id"]
70
+ cache_keys.concat(Array(cache_by)) if cache_by
71
+ cache_keys.uniq! { |key| Array(key).collect(&:to_s) }
72
+
73
+ cache_keys.each do |key|
74
+ klass.send(:cache_by, key)
75
+ end
76
+
77
+ klass.support_table_cache = cache
78
+ klass.support_table_cache_ttl = ttl
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "support_table_cache"
4
+ require "support_table_data"
5
+
6
+ # Include this module to add the ability to define support tables in ActiveRecord models.
7
+ # This will add the `support_table` and `belongs_to_support_table` class methods to the model.
8
+ #
9
+ # A support table is a table that contains a fixed set of data that is used to support
10
+ # the application. This data is typically loaded from a data file (YAML, JSON, or CSV)
11
+ # and is intended to be read-only. Support tables are also usually small and can be
12
+ # cached in memory for fast access.
13
+ #
14
+ # You would normally just include this module in your `ApplicationRecord` class. However,
15
+ # you can also include it in individual models.
16
+ #
17
+ # @example Define a support table
18
+ #
19
+ # class ApplicationRecord < ActiveRecord::Base
20
+ # self.abstract_class = true
21
+ #
22
+ # include SupportTable
23
+ # end
24
+ #
25
+ # class Status < ApplicationRecord
26
+ # support_table
27
+ # end
28
+ #
29
+ # class Task < ApplicationRecord
30
+ # belongs_to_support_table :status
31
+ # end
32
+ module SupportTable
33
+ extend ActiveSupport::Concern
34
+
35
+ VERSION = File.read(File.join(__dir__, "../VERSION")).strip
36
+
37
+ included do
38
+ include BelongsToSupportTable unless include?(BelongsToSupportTable)
39
+ end
40
+
41
+ module ClassMethods
42
+ # Define details about the support table. You only need to call this method if
43
+ # you need to override any of the defaults. See SupportTableData and SupportTableCache
44
+ # for more details.
45
+ #
46
+ # @param data_file [String, Array<String>, nil] Path to the data file to use to load the table. This
47
+ # should be a YAML, JSON, or CSV file that defines the records that should always exist in
48
+ # the table. If no value is specified, then a YAML file in the data directory with the
49
+ # same name as the underscored, pluralized name of the class will be used. For example,
50
+ # if the class name is `Task::Status`, then it will look for the file `task/statuses.yml`
51
+ # in the `db/support_tables` directory.
52
+ #
53
+ # @param key_attribute [String, Symbol, nil] The name of the attribute in the data file that
54
+ # uniquely identifies each row in the data. By default this will be the primary key
55
+ # attribute of the table (usually `id`).
56
+ #
57
+ # @param attribute_helpers [String, Symbol, Array<String, Symbol>, nil] List of attributes
58
+ # which should have helper methods created for them. This generates methods for each named instance
59
+ # to get that attribute directly from the YAML data. For example, adding a helper for `:name`
60
+ # will create a class method `*_name` for each named instance (i.e. Status.draft_name).
61
+ #
62
+ # @param cache_by [String, Symbol, Array, nil] List of attributes that can be used to uniquely
63
+ # identify a row that can be used for caching records. If a unique key is made up of
64
+ # multiple columns, then you will need to set it up with a call to `SupportTableCache.cache_by`
65
+ #
66
+ # @param cache [ActiveSupport::Cache::Store, Symbol, Boolean, nil] The caching mechanism to use.
67
+ # This can be either an instance of `ActiveSupport::Cache::Store` like `Rails.cache`, or
68
+ # the value `:memory` to use an in-memory cache, or `false` to disable caching.
69
+ #
70
+ #
71
+ # @param ttl [Numeric, ActiveSupport::Duration, nil] The time-to-live (in seconds) for cached records. If not specified,
72
+ # @return [void]
73
+ def support_table(data_file: nil, key_attribute: nil, attribute_helpers: nil, cache_by: nil, cache: :memory, ttl: nil)
74
+ SupportTable::Definition.new(self).support_table(
75
+ data_file: data_file,
76
+ key_attribute: key_attribute,
77
+ attribute_helpers: attribute_helpers,
78
+ cache_by: cache_by,
79
+ cache: cache,
80
+ ttl: ttl
81
+ )
82
+ end
83
+ end
84
+
85
+ class << self
86
+ # Set the directory where data files are stored. See SupportTableData for details.
87
+ # This is an alias for `SupportTableData.data_directory=`.
88
+ #
89
+ # @param dir [String] Path to the directory where data files are stored.
90
+ # @return [void]
91
+ def data_directory=(dir)
92
+ SupportTableData.data_directory = dir
93
+ end
94
+
95
+ # Sync all support tables. See SupportTableData for details. This is an alias for
96
+ # `SupportTableData.sync_all!`.
97
+ #
98
+ # @param classes [Array<Class>] List of support table classes to sync. If no classes
99
+ # are specified, then all support tables will be synced.
100
+ # @return [void]
101
+ def sync_all!(*classes)
102
+ SupportTableData.sync_all!(*classes)
103
+ end
104
+
105
+ # Set the cache used on support tables. See SupportTableCache for details. This is an
106
+ # alias for `SupportTableCache.cache=`.
107
+ #
108
+ # @param cache_impl [ActiveSupport::Cache::Store] The cache implementation to use.
109
+ # @return [void]
110
+ def cache=(cache_impl)
111
+ SupportTableCache.cache = cache_impl
112
+ end
113
+ end
114
+ end
115
+
116
+ require_relative "support_table/belongs_to_support_table"
117
+ require_relative "support_table/definition"
@@ -0,0 +1,42 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = "support_table"
3
+ spec.version = File.read(File.expand_path("../VERSION", __FILE__)).strip
4
+ spec.authors = ["Brian Durand"]
5
+ spec.email = ["bbdurand@gmail.com"]
6
+
7
+ spec.summary = "Support tables for ActiveRecord models with YAML-backed data, helper methods, and automatic caching for small tables."
8
+
9
+ spec.homepage = "https://github.com/bdurand/support_table"
10
+ spec.license = "MIT"
11
+
12
+ spec.metadata = {
13
+ "homepage_uri" => spec.homepage,
14
+ "source_code_uri" => spec.homepage,
15
+ "changelog_uri" => "#{spec.homepage}/blob/main/CHANGELOG.md"
16
+ }
17
+
18
+ # Specify which files should be added to the gem when it is released.
19
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
20
+ ignore_files = %w[
21
+ .
22
+ AGENTS.md
23
+ Appraisals
24
+ Gemfile
25
+ Gemfile.lock
26
+ Rakefile
27
+ bin/
28
+ gemfiles/
29
+ spec/
30
+ test_app/
31
+ ]
32
+ spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
33
+ `git ls-files -z`.split("\x0").reject { |f| ignore_files.any? { |path| f.start_with?(path) } }
34
+ end
35
+
36
+ spec.require_paths = ["lib"]
37
+
38
+ spec.add_dependency "support_table_cache", "~> 1.1", ">= 1.1.5"
39
+ spec.add_dependency "support_table_data", "~> 1.5", ">= 1.5.0"
40
+
41
+ spec.add_development_dependency "bundler"
42
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: support_table
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Brian Durand
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: support_table_cache
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.1'
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: 1.1.5
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: '1.1'
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: 1.1.5
32
+ - !ruby/object:Gem::Dependency
33
+ name: support_table_data
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - "~>"
37
+ - !ruby/object:Gem::Version
38
+ version: '1.5'
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: 1.5.0
42
+ type: :runtime
43
+ prerelease: false
44
+ version_requirements: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '1.5'
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: 1.5.0
52
+ - !ruby/object:Gem::Dependency
53
+ name: bundler
54
+ requirement: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ type: :development
60
+ prerelease: false
61
+ version_requirements: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ email:
67
+ - bbdurand@gmail.com
68
+ executables: []
69
+ extensions: []
70
+ extra_rdoc_files: []
71
+ files:
72
+ - CHANGELOG.md
73
+ - MIT-LICENSE
74
+ - README.md
75
+ - VERSION
76
+ - lib/support_table.rb
77
+ - lib/support_table/belongs_to_support_table.rb
78
+ - lib/support_table/definition.rb
79
+ - support_table.gemspec
80
+ homepage: https://github.com/bdurand/support_table
81
+ licenses:
82
+ - MIT
83
+ metadata:
84
+ homepage_uri: https://github.com/bdurand/support_table
85
+ source_code_uri: https://github.com/bdurand/support_table
86
+ changelog_uri: https://github.com/bdurand/support_table/blob/main/CHANGELOG.md
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubygems_version: 4.0.3
102
+ specification_version: 4
103
+ summary: Support tables for ActiveRecord models with YAML-backed data, helper methods,
104
+ and automatic caching for small tables.
105
+ test_files: []