dynamic-active-model-rails 0.12.0 → 0.13.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aade59eb21651ddf7c6c7f50de964e3d3e1e6809e82e9d832cb05cfe6917df65
4
- data.tar.gz: a0a3e87f460a462d3096193fdb4b2c405799903bf347c74944ce83b258c76afb
3
+ metadata.gz: a8515d28d9394768614fb8cd2f4cf49173ab1d5f97c905debbf3f9dc85d21f21
4
+ data.tar.gz: 33388b8956cc6106da4d6d94d0255a15b66d6156be30a49cfa9c941f31f3ed4e
5
5
  SHA512:
6
- metadata.gz: 562618b697479ecfcd9aff7cd04c8e9e40488064925dba63d76828ea5255c337355d0272d8e666d2f69b2b8e22f0fc5a67ffee86153075501ee34aab18b52de1
7
- data.tar.gz: eb5fe6bbd793f081d53f2dfd5826226ffc10806a3e6afb922e9eeffc49f1f391b2009246049f72506b27d38b3982ebbb79ab4d193be0567958c42738e1b5a91f
6
+ metadata.gz: ed7b1653b8ea5643e50b797a0cad76714958d204052ee97ba44cd10eed2e3f2103e20bcad4c16ee7277a12886ef85cceb6421a8ca41c485dec72dbac67b89fc4
7
+ data.tar.gz: 42a9e8a11125f32d8e9ea403662e232d602595c776c7829a05f7759fd14f4c9fa88822100fd92dd52c2e2188fb39c1d95082eb62c0bef16f6f5c2c17ba13beed
data/README.md CHANGED
@@ -26,6 +26,7 @@ DynamicActiveModel::Rails.configure do |config|
26
26
  # A Symbol names a database.yml entry; a URL string or config hash also works
27
27
  config.add_database :cars, :cars do |db|
28
28
  db.skip_tables 'legacy_*', /^tmp_/
29
+ db.include_tables 'cars', 'makes', 'owner*' # whitelist; default is every table
29
30
  db.foreign_key :cars, :owner_id, :owner
30
31
  db.table_class_name :status, 'StatusCode'
31
32
  end
@@ -48,6 +49,7 @@ Namespaces always end in `DB`, so a database's namespace never collides with an
48
49
  |---|---|---|
49
50
  | `add_database :cars` | `CarsDB` | `app/models/cars_db/` |
50
51
  | `add_database :grant_db` | `GrantDB` | `app/models/grant_db/` |
52
+ | `add_database :db` | `DB` | `app/models/db/` |
51
53
  | `add_database :cars, module_name: 'Inventory'` | `Inventory` | `app/models/inventory/` |
52
54
 
53
55
  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.
@@ -59,6 +61,8 @@ The `cars_db` → `CarsDB` mapping is registered with the Rails autoloader only,
59
61
  | `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
62
  | `module_name:` | `"<Name>DB"` | Namespace override. |
61
63
  | `parent_class:` | `'ApplicationRecord'` | Superclass of the generated abstract base class, given as a name so it can be reloaded. |
64
+ | `extensions_path:` | `app/models/<folder>` | Directory of extension files, absolute or relative to `Rails.root`. The default folder may be absent; a configured path must exist. |
65
+ | `extensions_suffix:` | `'.ext.rb'` | Suffix of extension files. The autoloader ignores files with this suffix. |
62
66
 
63
67
  ## Extending Models
64
68
 
@@ -121,6 +125,37 @@ development:
121
125
  migrations_paths: db/cars_migrate
122
126
  ```
123
127
 
128
+ ## Migrating from the Setup DSL
129
+
130
+ If your app followed the core gem's [manual setup](../docs/manual-rails-setup.md):
131
+
132
+ 1. Replace `gem 'dynamic-active-model'` with `gem 'dynamic-active-model-rails'`.
133
+ 2. Delete `app/models/db.rb`. Move its settings into an initializer:
134
+
135
+ ```ruby
136
+ # config/initializers/dynamic_active_model.rb
137
+ DynamicActiveModel::Rails.configure do |config|
138
+ config.add_database :db do |db| # DB, app/models/db/
139
+ db.skip_tables 'versions'
140
+ end
141
+ end
142
+ ```
143
+
144
+ | Setup DSL | Rails gem |
145
+ |---|---|
146
+ | `parent_class ApplicationRecord` | default (omit) |
147
+ | `connection_options 'secondary'` | `add_database :db, :secondary` |
148
+ | `extensions_path '...'` | default for `app/models/db/`; otherwise `extensions_path:` |
149
+ | `extensions_suffix '.x.rb'` | `extensions_suffix:` |
150
+ | `skip_tables [...]` / `skip_table` | `db.skip_tables` |
151
+ | `foreign_key t, col, name` | `db.foreign_key t, col, name` |
152
+ | `table_class_name t, name` | `db.table_class_name t, name` |
153
+
154
+ 3. Remove the `DB` inflection and the `app/models/db` ignore from `config/application.rb`. The gem registers both.
155
+ 4. Move setup that ran after `create_models!` into `ActiveSupport.on_load(:db) { ... }`.
156
+
157
+ `.ext.rb` files stay where they are.
158
+
124
159
  ## Development
125
160
 
126
161
  From this directory:
@@ -3,8 +3,8 @@
3
3
  module DynamicActiveModel
4
4
  module Rails
5
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.
6
+ # CarsDB (only in Zeitwerk, not the global inflector), and extension files
7
+ # (*.ext.rb by default) are left to DynamicActiveModel instead of being autoloaded.
8
8
  class AutoloaderSetup
9
9
  # @param autoloaders [Rails::Autoloaders]
10
10
  # @param definition [DatabaseDefinition]
@@ -26,7 +26,7 @@ module DynamicActiveModel
26
26
 
27
27
  # @return [String] Glob matching the database's extension files
28
28
  def extension_glob
29
- File.join(@definition.extensions_path(@root), '*.ext.rb')
29
+ File.join(@definition.extensions_path(@root), "*#{@definition.extensions_suffix}")
30
30
  end
31
31
  end
32
32
  end
@@ -20,6 +20,12 @@ module DynamicActiveModel
20
20
  # @return [Array<String, Regexp>] Tables (or patterns) to skip
21
21
  attr_reader :skipped_tables
22
22
 
23
+ # @return [Array<String, Regexp>] Tables (or patterns) to model; empty means all
24
+ attr_reader :included_tables
25
+
26
+ # @return [String] File suffix of extension files
27
+ attr_reader :extensions_suffix
28
+
23
29
  # @return [Hash] Custom relationship names by table and foreign key
24
30
  attr_reader :relationships
25
31
 
@@ -30,11 +36,18 @@ module DynamicActiveModel
30
36
  # @param connection [Symbol, String, Hash, nil] See Configuration#add_database
31
37
  # @param module_name [String, nil] Namespace override, e.g. "Inventory"
32
38
  # @param parent_class [String] Superclass for the generated base class
33
- def initialize(name, connection = nil, module_name: nil, parent_class: 'ApplicationRecord')
39
+ # @param extensions_path [String, nil] Extensions directory, absolute or relative to
40
+ # the app root; defaults to app/models/<folder>, which may be absent
41
+ # @param extensions_suffix [String] File suffix of extension files
42
+ def initialize(name, connection = nil, module_name: nil, parent_class: 'ApplicationRecord',
43
+ extensions_path: nil, extensions_suffix: '.ext.rb')
34
44
  @connection = connection
35
45
  @module_name = module_name || default_module_name(name)
36
46
  @parent_class_name = parent_class.to_s
47
+ @extensions_path = extensions_path&.to_s
48
+ @extensions_suffix = extensions_suffix
37
49
  @skipped_tables = []
50
+ @included_tables = []
38
51
  @relationships = {}
39
52
  @table_class_names = {}
40
53
  end
@@ -50,9 +63,14 @@ module DynamicActiveModel
50
63
  end
51
64
 
52
65
  # @param root [Pathname, String] Application root
53
- # @return [String] Directory holding this database's .ext.rb files
66
+ # @return [String] Absolute directory holding this database's extension files
54
67
  def extensions_path(root)
55
- File.join(root.to_s, 'app', 'models', folder)
68
+ File.expand_path(@extensions_path || File.join('app', 'models', folder), root.to_s)
69
+ end
70
+
71
+ # @return [Boolean] Whether extensions_path was configured, so it must exist
72
+ def custom_extensions_path?
73
+ !@extensions_path.nil?
56
74
  end
57
75
 
58
76
  # Skips tables; strings may use * wildcards
@@ -62,6 +80,14 @@ module DynamicActiveModel
62
80
  @skipped_tables.concat(tables.flatten)
63
81
  end
64
82
 
83
+ # Models only these tables; strings may use * wildcards. ActiveRecord's
84
+ # internal tables still need their exact name.
85
+ # @param tables [Array<String, Regexp>]
86
+ # @return [void]
87
+ def include_tables(*tables)
88
+ @included_tables.concat(tables.flatten)
89
+ end
90
+
65
91
  # Names the relationship for a foreign key column
66
92
  # @param table_name [String, Symbol]
67
93
  # @param foreign_key [String, Symbol] Column name
@@ -81,11 +107,11 @@ module DynamicActiveModel
81
107
 
82
108
  private
83
109
 
84
- # :cars => "CarsDB", :grant_db => "GrantDB"
110
+ # :cars => "CarsDB", :grant_db => "GrantDB", :db => "DB"
85
111
  # @param name [Symbol, String]
86
112
  # @return [String]
87
113
  def default_module_name(name)
88
- "#{name.to_s.underscore.delete_suffix('_db').camelize}DB"
114
+ "#{name.to_s.underscore.sub(/(?:\A|_)db\z/, '').camelize}DB"
89
115
  end
90
116
  end
91
117
  end
@@ -61,15 +61,22 @@ module DynamicActiveModel
61
61
  def new_database
62
62
  Database.new(namespace, definition.connection, parent_class: parent_class).tap do |database|
63
63
  definition.skipped_tables.each { |table| database.skip_table(Explorer.skip_table_matcher(table)) }
64
+ definition.included_tables.each { |table| database.include_table(Explorer.skip_table_matcher(table)) }
64
65
  definition.table_class_names.each { |table, class_name| database.table_class_name(table, class_name) }
65
66
  end
66
67
  end
67
68
 
68
- # Applies the .ext.rb files in the database's models folder
69
+ # Applies the database's extension files. The default folder is optional;
70
+ # a configured extensions_path must exist.
69
71
  # @return [void]
72
+ # @raise [DynamicActiveModel::Error] If a configured extensions_path is missing
70
73
  def load_extensions
71
74
  path = definition.extensions_path(@root)
72
- @database.update_all_models(path) if File.directory?(path)
75
+ if File.directory?(path)
76
+ @database.update_all_models(path, definition.extensions_suffix)
77
+ elsif definition.custom_extensions_path?
78
+ raise DynamicActiveModel::Error, "extensions_path #{path} for #{definition.module_name} does not exist"
79
+ end
73
80
  end
74
81
 
75
82
  # @return [Module] The namespace models are defined in
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamic-active-model-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Doug Youch
@@ -29,14 +29,14 @@ dependencies:
29
29
  requirements:
30
30
  - - '='
31
31
  - !ruby/object:Gem::Version
32
- version: 0.12.0
32
+ version: 0.13.0
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - '='
38
38
  - !ruby/object:Gem::Version
39
- version: 0.12.0
39
+ version: 0.13.0
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: railties
42
42
  requirement: !ruby/object:Gem::Requirement