dynamic-active-model-rails 0.11.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: ff5e6fd6c5b29afc9e58143d52d5d43b39123423f1356fd4daa60cde68a5a5f1
4
+ data.tar.gz: c3909cdbe0d699072ece815f55372f482c8a10c3c436c44866e1f55c24e52f8d
5
+ SHA512:
6
+ metadata.gz: a27b214728591ccf5fe23094287bb2486d86aace729b4efb330a9d87948d9e5a42eca19966990c1a2afb5076a82282d5a48d475c6a8d90da7bf357db4fc75206
7
+ data.tar.gz: 58590282a387c2fd6c1f10434e30875c43831797567726dfed8526a3c0da7f82d38bcb9a9a4e84f365637999f4bea68f7509c70b554f51536c339833664a0c8f
data/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # dynamic-active-model-rails
2
+
3
+ Rails integration for [dynamic-active-model](https://github.com/dougyouch/dynamic-active-model). Declare your databases in one initializer, and their tables become ActiveRecord models in a `<Name>DB` namespace. Models are built on first use, rebuilt after migrations, and reloaded with the rest of the app in development.
4
+
5
+ Requires Rails 7.1+ and Ruby 3.2+.
6
+
7
+ ## Installation
8
+
9
+ ```ruby
10
+ # Gemfile
11
+ gem 'dynamic-active-model-rails'
12
+ ```
13
+
14
+ `dynamic-active-model-rails` is released in lockstep with `dynamic-active-model` and pins the same version.
15
+
16
+ ## Configuration
17
+
18
+ ```ruby
19
+ # config/initializers/dynamic_active_model.rb
20
+ DynamicActiveModel::Rails.configure do |config|
21
+ # No connection: models subclass ApplicationRecord and share its connection pool
22
+ config.add_database :grant_db do |db|
23
+ db.skip_tables 'versions'
24
+ end
25
+
26
+ # A Symbol names a database.yml entry; a URL string or config hash also works
27
+ config.add_database :cars, :cars do |db|
28
+ db.skip_tables 'legacy_*', /^tmp_/
29
+ db.foreign_key :cars, :owner_id, :owner
30
+ db.table_class_name :status, 'StatusCode'
31
+ end
32
+ end
33
+ ```
34
+
35
+ ```ruby
36
+ GrantDB::User.find(1)
37
+ CarsDB::Car.where(make: 'Honda')
38
+ CarsDB.models # => [CarsDB::Car, CarsDB::Make, ...]
39
+ ```
40
+
41
+ `schema_migrations` and `ar_internal_metadata` are always skipped.
42
+
43
+ ### Naming
44
+
45
+ Namespaces always end in `DB`, so a database's namespace never collides with an application class:
46
+
47
+ | Declaration | Namespace | Folder |
48
+ |---|---|---|
49
+ | `add_database :cars` | `CarsDB` | `app/models/cars_db/` |
50
+ | `add_database :grant_db` | `GrantDB` | `app/models/grant_db/` |
51
+ | `add_database :cars, module_name: 'Inventory'` | `Inventory` | `app/models/inventory/` |
52
+
53
+ The `cars_db` → `CarsDB` mapping is registered with the Rails autoloader only, not with the global inflector, so `'cars_db'.camelize` elsewhere in your app is unaffected.
54
+
55
+ ### Options
56
+
57
+ | Option | Default | Description |
58
+ |---|---|---|
59
+ | `connection` (2nd argument) | `nil` | `nil` shares the parent class's connection. Otherwise it's passed to `establish_connection`: a database.yml entry name (Symbol), URL or hash. |
60
+ | `module_name:` | `"<Name>DB"` | Namespace override. |
61
+ | `parent_class:` | `'ApplicationRecord'` | Superclass of the generated abstract base class, given as a name so it can be reloaded. |
62
+
63
+ ## Extending Models
64
+
65
+ Add one `<table_name>.ext.rb` file per table to the database's folder:
66
+
67
+ ```ruby
68
+ # app/models/cars_db/cars.ext.rb
69
+ update_model do
70
+ scope :by_make, ->(name) { joins(:make).where(makes: { name: name }) }
71
+
72
+ def display_name
73
+ "#{make.name} #{model}"
74
+ end
75
+ end
76
+ ```
77
+
78
+ The autoloader ignores `.ext.rb` files. Other `.rb` files in the folder autoload into the namespace as usual, so you can keep related classes next to the models:
79
+
80
+ ```ruby
81
+ # app/models/cars_db/search.rb
82
+ module CarsDB
83
+ class Search
84
+ def self.for_make(name) = CarsDB::Car.by_make(name)
85
+ end
86
+ end
87
+ ```
88
+
89
+ ## Lifecycle
90
+
91
+ - **Lazy loading.** Nothing touches the database at boot. The first reference to a constant in a namespace builds that database's models. That's why `db:create`, `db:migrate` and `assets:precompile` don't need models to exist.
92
+ - **Eager loading.** With `config.eager_load` (production), every database's models are built at boot, along with the rest of the app.
93
+ - **Migrations.** After migrations run or a schema is loaded (`db:migrate`, `db:rollback`, `db:prepare`, `db:schema:load`, `maintain_test_schema!`), models are reset and rebuild on next use. That means `bin/rails db:prepare` followed by seeding works in one process.
94
+ - **Reloading.** In development, models are rebuilt whenever the app reloads, including after edits to `.ext.rb` files or to anything under `db/`, such as a migration rewriting `db/schema.rb`.
95
+
96
+ ## Migrations
97
+
98
+ Migrations stay standard Rails. The gem reads the schema; it never owns it. For a secondary database, give its database.yml entry a `migrations_paths`:
99
+
100
+ ```yaml
101
+ development:
102
+ primary:
103
+ <<: *default
104
+ database: storage/development.sqlite3
105
+ cars:
106
+ <<: *default
107
+ database: storage/cars.sqlite3
108
+ migrations_paths: db/cars_migrate
109
+ ```
110
+
111
+ ## Development
112
+
113
+ From this directory:
114
+
115
+ ```bash
116
+ bundle install
117
+ bundle exec rspec
118
+ ```
119
+
120
+ The specs boot a small Rails app in `spec/dummy` that has a primary and a `cars` SQLite database.
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicActiveModel
4
+ module Rails
5
+ # Teaches the Rails autoloader about a database's folder: cars_db/ maps to
6
+ # CarsDB (only in Zeitwerk, not the global inflector), and .ext.rb files are
7
+ # left to DynamicActiveModel instead of being autoloaded.
8
+ class AutoloaderSetup
9
+ # @param autoloaders [Rails::Autoloaders]
10
+ # @param definition [DatabaseDefinition]
11
+ # @param root [Pathname, String] Application root
12
+ def initialize(autoloaders, definition, root)
13
+ @autoloaders = autoloaders
14
+ @definition = definition
15
+ @root = root
16
+ end
17
+
18
+ # Must run before the main autoloader is set up, i.e. from an initializer
19
+ # @return [void]
20
+ def apply
21
+ @autoloaders.main.inflector.inflect(@definition.folder => @definition.module_name)
22
+ @autoloaders.main.ignore(extension_glob)
23
+ end
24
+
25
+ private
26
+
27
+ # @return [String] Glob matching the database's extension files
28
+ def extension_glob
29
+ File.join(@definition.extensions_path(@root), '*.ext.rb')
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicActiveModel
4
+ module Rails
5
+ # Collects the databases declared in DynamicActiveModel::Rails.configure
6
+ class Configuration
7
+ # @return [Array<DatabaseDefinition>] Declared databases, in order
8
+ attr_reader :definitions
9
+
10
+ def initialize
11
+ @definitions = []
12
+ end
13
+
14
+ # Declares a database whose tables become models in a <Name>DB namespace
15
+ # @param name [Symbol, String] Database name, e.g. :cars => CarsDB, app/models/cars_db/
16
+ # @param connection [Symbol, String, Hash, nil] database.yml entry name, URL or
17
+ # config hash; nil shares the parent class's connection
18
+ # @param ** [Hash] DatabaseDefinition options (module_name:, parent_class:)
19
+ # @yieldparam definition [DatabaseDefinition] For table-level settings
20
+ # @return [DatabaseDefinition]
21
+ # @raise [ArgumentError] If the namespace is already declared
22
+ def add_database(name, connection = nil, **)
23
+ definition = DatabaseDefinition.new(name, connection, **)
24
+ raise ArgumentError, "#{definition.module_name} is already declared" if declared?(definition.module_name)
25
+
26
+ yield definition if block_given?
27
+ @definitions << definition
28
+ definition
29
+ end
30
+
31
+ private
32
+
33
+ # @param module_name [String]
34
+ # @return [Boolean] Whether a database already uses the namespace
35
+ def declared?(module_name)
36
+ @definitions.any? { |definition| definition.module_name == module_name }
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/string/inflections'
4
+
5
+ module DynamicActiveModel
6
+ module Rails
7
+ # Settings for one declared database: its connection, namespace, folder and
8
+ # table-level options. Names always end in DB so a namespace never collides
9
+ # with an application class: :cars => CarsDB in app/models/cars_db/.
10
+ class DatabaseDefinition
11
+ # @return [Symbol, String, Hash, nil] Connection passed to establish_connection
12
+ attr_reader :connection
13
+
14
+ # @return [String] Name of the namespace module, e.g. "CarsDB"
15
+ attr_reader :module_name
16
+
17
+ # @return [String] Name of the base class's superclass, constantized at load time
18
+ attr_reader :parent_class_name
19
+
20
+ # @return [Array<String, Regexp>] Tables (or patterns) to skip
21
+ attr_reader :skipped_tables
22
+
23
+ # @return [Hash] Custom relationship names by table and foreign key
24
+ attr_reader :relationships
25
+
26
+ # @return [Hash] Custom class names by table name
27
+ attr_reader :table_class_names
28
+
29
+ # @param name [Symbol, String] Database name
30
+ # @param connection [Symbol, String, Hash, nil] See Configuration#add_database
31
+ # @param module_name [String, nil] Namespace override, e.g. "Inventory"
32
+ # @param parent_class [String] Superclass for the generated base class
33
+ def initialize(name, connection = nil, module_name: nil, parent_class: 'ApplicationRecord')
34
+ @connection = connection
35
+ @module_name = module_name || default_module_name(name)
36
+ @parent_class_name = parent_class.to_s
37
+ @skipped_tables = []
38
+ @relationships = {}
39
+ @table_class_names = {}
40
+ end
41
+
42
+ # @return [String] Folder under app/models for extensions, e.g. "cars_db"
43
+ def folder
44
+ module_name.underscore
45
+ end
46
+
47
+ # @param root [Pathname, String] Application root
48
+ # @return [String] Directory holding this database's .ext.rb files
49
+ def extensions_path(root)
50
+ File.join(root.to_s, 'app', 'models', folder)
51
+ end
52
+
53
+ # Skips tables; strings may use * wildcards
54
+ # @param tables [Array<String, Regexp>]
55
+ # @return [void]
56
+ def skip_tables(*tables)
57
+ @skipped_tables.concat(tables.flatten)
58
+ end
59
+
60
+ # Names the relationship for a foreign key column
61
+ # @param table_name [String, Symbol]
62
+ # @param foreign_key [String, Symbol] Column name
63
+ # @param relationship_name [String, Symbol]
64
+ # @return [void]
65
+ def foreign_key(table_name, foreign_key, relationship_name)
66
+ (@relationships[table_name.to_s] ||= {})[foreign_key.to_s] = relationship_name.to_s
67
+ end
68
+
69
+ # Overrides the model class name for a table
70
+ # @param table_name [String, Symbol]
71
+ # @param class_name [String]
72
+ # @return [void]
73
+ def table_class_name(table_name, class_name)
74
+ @table_class_names[table_name.to_s] = class_name.to_s
75
+ end
76
+
77
+ private
78
+
79
+ # :cars => "CarsDB", :grant_db => "GrantDB"
80
+ # @param name [Symbol, String]
81
+ # @return [String]
82
+ def default_module_name(name)
83
+ "#{name.to_s.underscore.delete_suffix('_db').camelize}DB"
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'monitor'
4
+
5
+ module DynamicActiveModel
6
+ module Rails
7
+ # Builds one declared database's models on demand and tears them down again.
8
+ # Loading is synchronized so concurrent first references build only once.
9
+ class DatabaseLoader
10
+ # @return [DatabaseDefinition]
11
+ attr_reader :definition
12
+
13
+ # @param definition [DatabaseDefinition]
14
+ # @param root [Pathname, String] Application root, for the extensions folder
15
+ def initialize(definition, root)
16
+ @definition = definition
17
+ @root = root
18
+ @monitor = Monitor.new
19
+ end
20
+
21
+ # Builds the models unless already built
22
+ # @return [DynamicActiveModel::Database]
23
+ def load!
24
+ @monitor.synchronize { build unless @database }
25
+ @database
26
+ end
27
+
28
+ # @return [Boolean] Whether models are built (or being built)
29
+ def loaded?
30
+ !@database.nil?
31
+ end
32
+
33
+ # Removes the built models so the next #load! rebuilds them
34
+ # @return [void]
35
+ def reset!
36
+ @monitor.synchronize do
37
+ @database&.reset!
38
+ @database = nil
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ # Creates models, relationships and extensions; undoes a partial build on error
45
+ # @return [void]
46
+ def build
47
+ @database = new_database
48
+ @database.create_models!
49
+ Explorer.build_relationships!(@database, definition.relationships)
50
+ load_extensions
51
+ rescue StandardError
52
+ reset!
53
+ raise
54
+ end
55
+
56
+ # @return [DynamicActiveModel::Database] A database configured from the definition
57
+ def new_database
58
+ Database.new(namespace, definition.connection, parent_class: parent_class).tap do |database|
59
+ definition.skipped_tables.each { |table| database.skip_table(Explorer.skip_table_matcher(table)) }
60
+ definition.table_class_names.each { |table, class_name| database.table_class_name(table, class_name) }
61
+ end
62
+ end
63
+
64
+ # Applies the .ext.rb files in the database's models folder
65
+ # @return [void]
66
+ def load_extensions
67
+ path = definition.extensions_path(@root)
68
+ @database.update_all_models(path) if File.directory?(path)
69
+ end
70
+
71
+ # @return [Module] The namespace models are defined in
72
+ def namespace
73
+ Object.const_get(definition.module_name)
74
+ end
75
+
76
+ # @return [Class] The base class's superclass, resolved now so it can be reloaded
77
+ def parent_class
78
+ Object.const_get(definition.parent_class_name)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicActiveModel
4
+ module Rails
5
+ # Extended into a database's namespace module (e.g. CarsDB). The first
6
+ # reference to a missing constant builds the database's models.
7
+ module LazyNamespace
8
+ # @return [DatabaseLoader]
9
+ attr_accessor :dynamic_active_model_loader
10
+
11
+ # Defines (or reuses) a top-level namespace module and makes it lazy
12
+ # @param module_name [String]
13
+ # @param loader [DatabaseLoader]
14
+ # @return [Module]
15
+ def self.define(module_name, loader)
16
+ namespace =
17
+ if Object.const_defined?(module_name, false)
18
+ Object.const_get(module_name, false)
19
+ else
20
+ Object.const_set(module_name, Module.new)
21
+ end
22
+ namespace.extend(self)
23
+ namespace.dynamic_active_model_loader = loader
24
+ namespace
25
+ end
26
+
27
+ # @return [DynamicActiveModel::Database] The built database
28
+ def database
29
+ dynamic_active_model_loader.load!
30
+ end
31
+
32
+ # @return [Array<Class>] Every model in the namespace
33
+ def models
34
+ database.models
35
+ end
36
+
37
+ # Builds the models on first reference, then retries the lookup
38
+ # @param name [Symbol]
39
+ # @return [Object]
40
+ def const_missing(name)
41
+ return super if dynamic_active_model_loader.loaded?
42
+
43
+ dynamic_active_model_loader.load!
44
+ const_defined?(name, false) ? const_get(name, false) : super
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicActiveModel
4
+ module Rails
5
+ # Hooks declared databases into Rails: eager loading, code reloading and
6
+ # schema changes all rebuild models instead of leaving them stale.
7
+ class Railtie < ::Rails::Railtie
8
+ config.eager_load_namespaces << DynamicActiveModel::Rails
9
+
10
+ initializer 'dynamic_active_model.schema_change_hook' do
11
+ ActiveSupport.on_load(:active_record) { DynamicActiveModel::Rails::SchemaChangeHook.install }
12
+ end
13
+
14
+ initializer 'dynamic_active_model.reloader' do |app|
15
+ app.reloader.before_class_unload { DynamicActiveModel::Rails.reset! }
16
+ # a migration rewrites db/schema.rb (or structure.sql); reload so models rebuild
17
+ app.config.watchable_dirs[app.root.join('db').to_s] = %i[rb sql]
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicActiveModel
4
+ module Rails
5
+ # Resets every database's models after migrations run or a schema is loaded,
6
+ # so models referenced later in the same process see the new schema. Covers
7
+ # db:migrate, db:rollback, db:prepare, db:schema:load and maintain_test_schema!.
8
+ module SchemaChangeHook
9
+ # Prepended to ActiveRecord::Migrator
10
+ module Migrator
11
+ def migrate
12
+ super
13
+ ensure
14
+ DynamicActiveModel::Rails.reset!
15
+ end
16
+
17
+ def run
18
+ super
19
+ ensure
20
+ DynamicActiveModel::Rails.reset!
21
+ end
22
+ end
23
+
24
+ # Prepended to ActiveRecord::Tasks::DatabaseTasks' singleton class
25
+ module DatabaseTasks
26
+ def load_schema(...)
27
+ super
28
+ ensure
29
+ DynamicActiveModel::Rails.reset!
30
+ end
31
+ end
32
+
33
+ # @return [void]
34
+ def self.install
35
+ ActiveRecord::Migrator.prepend(Migrator)
36
+ ActiveRecord::Tasks::DatabaseTasks.singleton_class.prepend(DatabaseTasks)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicActiveModel
4
+ # Rails integration for DynamicActiveModel. Declare each database once in an
5
+ # initializer; its models are built lazily on first reference, rebuilt after
6
+ # migrations, and reloaded with the rest of the app in development.
7
+ #
8
+ # @example config/initializers/dynamic_active_model.rb
9
+ # DynamicActiveModel::Rails.configure do |config|
10
+ # config.add_database :grant_db # ApplicationRecord's connection
11
+ # config.add_database :cars, :cars do |db| # "cars" entry in database.yml
12
+ # db.skip_tables 'legacy_*'
13
+ # end
14
+ # end
15
+ #
16
+ # GrantDB::User.first
17
+ # CarsDB::Car.where(make: 'Honda')
18
+ module Rails
19
+ autoload :AutoloaderSetup, 'dynamic-active-model/rails/autoloader_setup'
20
+ autoload :Configuration, 'dynamic-active-model/rails/configuration'
21
+ autoload :DatabaseDefinition, 'dynamic-active-model/rails/database_definition'
22
+ autoload :DatabaseLoader, 'dynamic-active-model/rails/database_loader'
23
+ autoload :LazyNamespace, 'dynamic-active-model/rails/lazy_namespace'
24
+ autoload :SchemaChangeHook, 'dynamic-active-model/rails/schema_change_hook'
25
+
26
+ class << self
27
+ # Declares databases. Each new database gets its namespace module and
28
+ # autoloader settings immediately, so call this from an initializer.
29
+ # @yieldparam config [Configuration]
30
+ # @return [Configuration]
31
+ def configure
32
+ yield configuration
33
+ configuration.definitions.each { |definition| register(definition) }
34
+ configuration
35
+ end
36
+
37
+ # @return [Configuration] The process-wide configuration
38
+ def configuration
39
+ @configuration ||= Configuration.new
40
+ end
41
+
42
+ # @return [Array<DatabaseLoader>] A loader per declared database
43
+ def loaders
44
+ @loaders ||= []
45
+ end
46
+
47
+ # Builds every database's models. Rails calls this when eager loading.
48
+ # @return [void]
49
+ def eager_load!
50
+ loaders.each(&:load!)
51
+ end
52
+
53
+ # Forgets every database's models so they rebuild on next reference
54
+ # @return [void]
55
+ def reset!
56
+ loaders.each(&:reset!)
57
+ end
58
+
59
+ private
60
+
61
+ # Sets up the namespace and autoloader for a definition not seen before
62
+ # @param definition [DatabaseDefinition]
63
+ # @return [void]
64
+ def register(definition)
65
+ return if loaders.any? { |loader| loader.definition.equal?(definition) }
66
+
67
+ loader = DatabaseLoader.new(definition, ::Rails.root)
68
+ LazyNamespace.define(definition.module_name, loader)
69
+ AutoloaderSetup.new(::Rails.autoloaders, definition, ::Rails.root).apply
70
+ loaders << loader
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails'
4
+ require 'dynamic-active-model'
5
+ require 'dynamic-active-model/rails'
6
+ require 'dynamic-active-model/rails/railtie'
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dynamic-active-model-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.11.0
5
+ platform: ruby
6
+ authors:
7
+ - Doug Youch
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: activerecord
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '7.1'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '7.1'
26
+ - !ruby/object:Gem::Dependency
27
+ name: dynamic-active-model
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - '='
31
+ - !ruby/object:Gem::Version
32
+ version: 0.11.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - '='
38
+ - !ruby/object:Gem::Version
39
+ version: 0.11.0
40
+ - !ruby/object:Gem::Dependency
41
+ name: railties
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '7.1'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '7.1'
54
+ description: 'Railtie for dynamic-active-model: declare databases in one initializer
55
+ and get lazily built, reloadable models in CarsDB-style namespaces, with extension
56
+ files in app/models/cars_db/ and automatic rebuilds after migrations.'
57
+ email: dougyouch@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - README.md
63
+ - lib/dynamic-active-model-rails.rb
64
+ - lib/dynamic-active-model/rails.rb
65
+ - lib/dynamic-active-model/rails/autoloader_setup.rb
66
+ - lib/dynamic-active-model/rails/configuration.rb
67
+ - lib/dynamic-active-model/rails/database_definition.rb
68
+ - lib/dynamic-active-model/rails/database_loader.rb
69
+ - lib/dynamic-active-model/rails/lazy_namespace.rb
70
+ - lib/dynamic-active-model/rails/railtie.rb
71
+ - lib/dynamic-active-model/rails/schema_change_hook.rb
72
+ homepage: https://github.com/dougyouch/dynamic-active-model/tree/master/dynamic-active-model-rails
73
+ licenses:
74
+ - MIT
75
+ metadata:
76
+ rubygems_mfa_required: 'true'
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '3.2'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubygems_version: 4.0.20
92
+ specification_version: 4
93
+ summary: Rails integration for dynamic-active-model
94
+ test_files: []