thecore_generators 3.0.0 → 3.2.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: 9f829a0f19f22655ce14f10be2c9c748dd67acc8a9432aced696cd9ca3ba7f8a
4
- data.tar.gz: '08b6468f673411496eab954f7d2511c4345242aa5aa1a020d7a3860ad42580bc'
3
+ metadata.gz: 48198bd6f914066ca468eae2e95cb9dba85003d49532b1db28f8620db3c40b21
4
+ data.tar.gz: 7a3e542b82e0ff43691e3a988dad6e42f59fc51da0e460220e5481881eb55ba3
5
5
  SHA512:
6
- metadata.gz: 92ad6a86068b45d71a7a077cee5c083fb893724767314bb49d914a567cd09b4708091c97fa7d5772470e4f37bd068447f63b9b600081807fa73ed842455f9353
7
- data.tar.gz: 1e5430b20ea00057c7dea7b48736c31f2cbc64dc236550fc5957d90874dd3d42b1435968fb996bfcb2022ad9d3b7fe4b4cf79bcf6f4bd5b1fad358a9c0388cfa
6
+ metadata.gz: 82748585f40f3f1e3975a3c1186d4bb98a3d8c4963ebcb495d9ba4c3c86701b2a48e981c28a6bfe220bd20b90fbcdacffa7e332b36edcbba2d4c3ab80e097e0d
7
+ data.tar.gz: ca82db7bdc678f66789b0ed9af24bf28f4f2253e2c025c3972118e602a86e662fc845863b098ba220d3163739c30b73f2588b30eb0aa8384300bc86a25adf013
data/README.md CHANGED
@@ -11,10 +11,98 @@ own `thecore:*`-namespaced generators or an application template. See
11
11
  [`docs/adr/0002-thecore-generators-gem-and-generator-hook-mechanism.md`](https://github.com/gabrieletassoni/thecore/blob/release/3/docs/adr/0002-thecore-generators-gem-and-generator-hook-mechanism.md)
12
12
  in the thecore repo for the full design.
13
13
 
14
- **Status:** bootstrap only. This release makes the gem buildable, testable, and
15
- publishable — it ships no generator behaviour yet. `ThecoreGenerators::Railtie`
16
- (`lib/thecore_generators/railtie.rb`) is a deliberate no-op; the `config.app_generators.orm`
17
- hook lands in a follow-up ticket.
14
+ **Status:** Model + Migration generator hook (Phase 1 of
15
+ [ADR 0002](https://github.com/gabrieletassoni/thecore/blob/release/3/docs/adr/0002-thecore-generators-gem-and-generator-hook-mechanism.md)).
16
+ `ThecoreGenerators::Railtie` registers `config.app_generators.orm :thecore, migration:
17
+ true, timestamps: true`, so plain `rails generate model`/`rails generate migration`
18
+ transparently apply thecore's scaffolding conventions — no new command vocabulary.
19
+
20
+ ### What `rails generate model`/`rails generate migration` do now
21
+
22
+ - **Context-aware placement.** `Thecore::Generators::WorkspaceContext` detects whether
23
+ the invoking process's `Dir.pwd` is inside a host app or an ATOM (`vendor/submodules/<atom>/`,
24
+ by gemspec presence — a Ruby port of `thecore_code_extension`'s `workspaceContext.js`).
25
+ When an ATOM is detected, the model/migration/test files land inside that ATOM's own
26
+ `app/models`/`db/migrate`/`test` instead of the host app's. Pass `--atom=NAME` to
27
+ override detection explicitly (works independent of `cwd`, e.g. from CI or the host-app
28
+ root).
29
+ - **No concern files by default.** `Api::ModelName`/`RailsAdmin::ModelName` concern files
30
+ are **not** generated (per
31
+ [ADR 0001](https://github.com/gabrieletassoni/thecore/blob/release/3/docs/adr/0001-application-record-defaults-over-generated-concerns.md)) —
32
+ the no-customization case relies entirely on the default `json_attrs`/`navigation_label`/
33
+ `navigation_icon` behavior that `model_driven_api` and `thecore_ui_rails_admin` `include`
34
+ into every `ApplicationRecord` subclass automatically
35
+ (`ThecoreBackendCommons::DefaultModuleRegistry`). Pass `--with-api-concern` and/or
36
+ `--with-admin-concern` to scaffold a starter concern file — identical in shape to what
37
+ this generator produced before this default changed — for the case where customization
38
+ is already known to be needed at generation time:
39
+ ```bash
40
+ rails generate model Foo name:string --with-api-concern --with-admin-concern
41
+ ```
42
+ See "Adding a concern by hand" below for the (more common) case of realizing
43
+ customization is needed *after* the model already exists.
44
+ - **No `Endpoints::ModelName` by default** (per ADR 0001) — add one by hand, following the
45
+ `after_initialize` + `class_eval` pattern, only when a real custom action is needed.
46
+ - **Test file generation is never suppressed** — a real Minitest file is generated, same
47
+ as Rails' own `active_record:model` default.
48
+ - **`rails generate active_record:model`/`active_record:migration` still work directly**
49
+ as an escape hatch, entirely unaffected by the hook above.
50
+
51
+ Both `Thecore::Generators::ModelGenerator` and `MigrationGenerator` wrap (not reimplement)
52
+ `ActiveRecord::Generators::ModelGenerator`/`MigrationGenerator` — all attribute parsing and
53
+ template content is inherited as-is; only file placement and the two opt-in concerns are
54
+ added on top.
55
+
56
+ ### Adding a concern by hand
57
+
58
+ The common case is not knowing at `rails generate model` time that a model will need
59
+ custom API serialization or RailsAdmin configuration — that need usually surfaces later.
60
+ Since neither concern is generated by default, add the missing one directly instead of
61
+ regenerating the model:
62
+
63
+ **`Api::ModelName`** (custom `json_attrs`) — create `app/models/concerns/api/model_name.rb`:
64
+ ```ruby
65
+ module Api::ModelName
66
+ extend ActiveSupport::Concern
67
+
68
+ included do
69
+ cattr_accessor :json_attrs
70
+ self.json_attrs = ::ModelDrivenApi.smart_merge(json_attrs || {}), { only: [:id, :name] }
71
+ end
72
+ end
73
+ ```
74
+ then `include Api::ModelName` in the model. Because the default module (`model_driven_api`'s
75
+ `ModelDrivenApiDefaultJsonAttrs`) is already `include`d by the time the model class body
76
+ runs, `::ModelDrivenApi.smart_merge(json_attrs || {}, ...)` composes on top of it rather
77
+ than starting from nothing — the same pattern the opt-in `--with-api-concern` template
78
+ below uses.
79
+
80
+ **`RailsAdmin::ModelName`** (custom admin config) — create
81
+ `app/models/concerns/rails_admin/model_name.rb`:
82
+ ```ruby
83
+ module RailsAdmin::ModelName
84
+ extend ActiveSupport::Concern
85
+
86
+ included do
87
+ rails_admin do
88
+ navigation_label I18n.t('admin.registries.label')
89
+ navigation_icon 'fa fa-file' # see https://fontawesome.com/v5/search
90
+ configure :some_field do
91
+ hide
92
+ end
93
+ end
94
+ end
95
+ end
96
+ ```
97
+ then `include RailsAdmin::ModelName` in the model. RailsAdmin evaluates same-origin
98
+ `rails_admin do ... end` blocks in registration order and later calls win on settings they
99
+ touch (`navigation_label`/`navigation_icon` are last-write-wins setters) — so this explicit
100
+ block, `include`d after the default from the class body, overrides the default's
101
+ `navigation_label`/`navigation_icon` while the default itself keeps applying to every other
102
+ model that has no concern of its own.
103
+
104
+ Either concern can be added independently — a model doesn't need both just because it
105
+ needs one.
18
106
 
19
107
  ## Installation
20
108
 
@@ -28,18 +116,30 @@ gem "thecore_generators", "~> 3.0"
28
116
 
29
117
  Tests use a `Rails::Generators::TestCase`-based harness against the `test/dummy` Rails
30
118
  app included in this repo (needed to exercise generators the way a real host app would).
119
+ `test/dummy` also boots real `model_driven_api`/`thecore_ui_rails_admin` (and their own
120
+ transitive `thecore_backend_commons`/`thecore_auth_commons` dependencies) as temporary
121
+ git-based dependencies — see the Gemfile's comment — purely so
122
+ `test/generators/thecore/model_generator_default_concern_behavior_test.rb` can prove the
123
+ no-concern default actually works at runtime, not just that no file was written.
31
124
 
32
125
  ```bash
33
126
  bundle install
34
127
  bundle exec rake test
35
128
  ```
36
129
 
130
+ If your shell has `DATABASE_URL` set to a PostgreSQL URL (e.g. inside the Thecore
131
+ devcontainer), unset it first — it overrides `test/dummy`'s own SQLite3 test config:
132
+
133
+ ```bash
134
+ env -u DATABASE_URL bundle exec rake test
135
+ ```
136
+
37
137
  `bundle exec rake` alone runs the same suite (`test` is the default Rake task).
38
138
 
39
139
  To run a single test file:
40
140
 
41
141
  ```bash
42
- bundle exec ruby -Itest test/generators/placeholder_generator_test.rb
142
+ bundle exec ruby -Itest test/generators/thecore/model_generator_test.rb
43
143
  ```
44
144
 
45
145
  ## Releasing
@@ -0,0 +1,59 @@
1
+ require "generators/thecore/workspace_context"
2
+
3
+ module Thecore
4
+ module Generators
5
+ # Shared by Thecore::Generators::ModelGenerator and MigrationGenerator:
6
+ # redirects file placement into an ATOM directory when
7
+ # Thecore::Generators::WorkspaceContext detects one (from `Dir.pwd` or an
8
+ # explicit `--atom=NAME`), and otherwise leaves the wrapped ActiveRecord
9
+ # generator's own placement (relative to `destination_root`, already the
10
+ # host app root for a real `rails generate` invocation) untouched.
11
+ #
12
+ # Two distinct placement mechanisms need covering, since ActiveRecord's
13
+ # generators don't derive both from `destination_root`:
14
+ # - Model/module/test files are `template`d at paths relative to
15
+ # `destination_root` — overriding `destination_root` itself (in
16
+ # `initialize`) redirects all of these, including the file the
17
+ # inherited `hook_for :test_framework` generates, since Thor's
18
+ # `_shared_configuration` passes the (already-overridden)
19
+ # `destination_root` on to hooked generators automatically.
20
+ # - The migration file's directory instead comes from
21
+ # `ActiveRecord::Generators::Migration#db_migrate_path`, computed from
22
+ # `Rails.application.config.paths["db/migrate"]` — i.e. always the
23
+ # real app root, regardless of `destination_root`. This must be
24
+ # overridden separately.
25
+ module AtomAware
26
+ def self.included(base)
27
+ base.class_option :atom, type: :string, default: nil,
28
+ desc: "Explicit ATOM name (under vendor/submodules/) to target, overriding cwd-based detection"
29
+ end
30
+
31
+ def initialize(*args)
32
+ super
33
+ self.destination_root = atom_dir if atom_dir
34
+ end
35
+
36
+ # The absolute ATOM directory this generator's files should land in, or
37
+ # nil for plain host-app context. Resolved once, before
38
+ # `destination_root` is (possibly) overridden above, since the
39
+ # pre-override `destination_root` is the correct app-root anchor for
40
+ # resolving an explicit `--atom=NAME`.
41
+ def atom_dir
42
+ return @atom_dir if @atom_dir_resolved
43
+
44
+ @atom_dir_resolved = true
45
+ @atom_dir = Thecore::Generators::WorkspaceContext.atom_dir_for(
46
+ cwd: Dir.pwd,
47
+ app_root: destination_root,
48
+ atom_name: options[:atom]
49
+ )
50
+ end
51
+
52
+ private
53
+
54
+ def db_migrate_path
55
+ atom_dir ? File.join(atom_dir, "db", "migrate") : super
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,25 @@
1
+ require "rails/generators/active_record/migration/migration_generator"
2
+ require "generators/thecore/atom_aware"
3
+
4
+ module Thecore
5
+ module Generators
6
+ # Resolved automatically by plain `rails generate migration` once
7
+ # ThecoreGenerators::Railtie registers `config.app_generators.orm
8
+ # :thecore, ...` (namespace "thecore:migration" — see
9
+ # Thecore::Generators::ModelGenerator for the namespace-resolution
10
+ # mechanism, identical here).
11
+ #
12
+ # A pure wrap: 100% of ActiveRecord::Generators::MigrationGenerator's
13
+ # migration-content logic (add/remove/create-table detection, attribute
14
+ # parsing, templates) is inherited untouched. The only addition is
15
+ # Thecore::Generators::AtomAware, redirecting the migration file into an
16
+ # ATOM's db/migrate when one is detected from `Dir.pwd`/`--atom=NAME`, so
17
+ # `rails generate migration AddBarToFoo bar:string` gets the same
18
+ # context-aware placement standalone, not just via `rails generate model`.
19
+ class MigrationGenerator < ActiveRecord::Generators::MigrationGenerator
20
+ include Thecore::Generators::AtomAware
21
+
22
+ source_root ActiveRecord::Generators::MigrationGenerator.source_root
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,100 @@
1
+ require "rails/generators/active_record/model/model_generator"
2
+ require "generators/thecore/atom_aware"
3
+
4
+ module Thecore
5
+ module Generators
6
+ # Resolved automatically by plain `rails generate model` once
7
+ # ThecoreGenerators::Railtie registers `config.app_generators.orm
8
+ # :thecore, ...` (namespace "thecore:model", derived from this class's
9
+ # own module nesting the same way ActiveRecord::Generators::ModelGenerator
10
+ # resolves to "active_record:model" — see Rails::Generators::Base#namespace).
11
+ #
12
+ # Wraps (does not reimplement) ActiveRecord's own model generator: all
13
+ # attribute parsing, the model/module templates, and migration-content
14
+ # generation are inherited as-is. On top of that:
15
+ # - Thecore::Generators::AtomAware redirects placement into an ATOM's
16
+ # app/models + db/migrate when one is detected (see its own docs).
17
+ # - `Api::ModelName`/`RailsAdmin::ModelName` concern files are NOT
18
+ # generated by default (thecore_generators#4 / ADR 0001 in the
19
+ # thecore repo): the no-customization case now relies entirely on
20
+ # the default `json_attrs`/`navigation_label`/`navigation_icon`
21
+ # modules that `model_driven_api` and `thecore_ui_rails_admin`
22
+ # `include` into every `ApplicationRecord` subclass automatically
23
+ # (`ThecoreBackendCommons::DefaultModuleRegistry`). Pass
24
+ # `--with-api-concern`/`--with-admin-concern` to scaffold a starter
25
+ # concern file — identical in shape to what this generator produced
26
+ # before this ticket — for the case where customization is already
27
+ # known to be needed at generation time. To add one later instead
28
+ # (the common case), see the "Adding a concern by hand" section of
29
+ # this gem's README.
30
+ # - `Endpoints::ModelName` is deliberately NOT generated (ADR 0001: it's
31
+ # never `include`d by default; add it by hand, following the
32
+ # after_initialize + class_eval pattern, only when a real custom
33
+ # action is needed).
34
+ # - Test file generation is never suppressed (no `--skip-test-framework`
35
+ # equivalent) — `hook_for :test_framework` runs exactly as it does for
36
+ # `active_record:model`.
37
+ class ModelGenerator < ActiveRecord::Generators::ModelGenerator
38
+ include Thecore::Generators::AtomAware
39
+
40
+ class_option :with_api_concern, type: :boolean, default: false,
41
+ desc: "Scaffold a starter app/models/concerns/api/<model>.rb, included into the model " \
42
+ "(pre-thecore_generators#4 default behavior). Opt in only when customization is " \
43
+ "already known to be needed at generation time."
44
+ class_option :with_admin_concern, type: :boolean, default: false,
45
+ desc: "Scaffold a starter app/models/concerns/rails_admin/<model>.rb, included into the " \
46
+ "model (pre-thecore_generators#4 default behavior). Opt in only when customization is " \
47
+ "already known to be needed at generation time."
48
+
49
+ # `source_root` (singular) must be set explicitly: Rails::Generators::Base's
50
+ # auto-computed `default_source_root` derives its path from *this*
51
+ # class's own base_name/generator_name ("thecore"/"model"), which
52
+ # doesn't exist on disk — so it silently resolves to nil unless
53
+ # pointed at ActiveRecord's own directory here. Our own
54
+ # api_concern.rb.tt/rails_admin_concern.rb.tt templates live alongside
55
+ # this file and are added to `source_paths` (plural) separately, since
56
+ # `source_root` only holds one path.
57
+ source_paths.unshift(File.expand_path("templates", __dir__))
58
+ source_root ActiveRecord::Generators::ModelGenerator.source_root
59
+
60
+ def create_model_file
61
+ super
62
+ add_opted_in_concerns
63
+ end
64
+
65
+ private
66
+
67
+ # Faithful Ruby port of addModel.js's api_concern.rb/rails_admin_concern.rb
68
+ # templates and its `include Api::X` / `include RailsAdmin::X` model-file
69
+ # rewrite — down to the exact generated content — kept available behind
70
+ # `--with-api-concern`/`--with-admin-concern` for the explicit
71
+ # customization-at-generation-time case (thecore_generators#4).
72
+ def add_opted_in_concerns
73
+ include_lines = +""
74
+
75
+ if options[:with_api_concern]
76
+ template "api_concern.rb", File.join("app/models/concerns/api", class_path, "#{file_name}.rb")
77
+ include_lines << " include Api::#{class_name}\n"
78
+ end
79
+
80
+ if options[:with_admin_concern]
81
+ template "rails_admin_concern.rb", File.join("app/models/concerns/rails_admin", class_path, "#{file_name}.rb")
82
+ include_lines << " include RailsAdmin::#{class_name}\n"
83
+ end
84
+
85
+ include_opted_in_concerns_in_model(include_lines) unless include_lines.empty?
86
+ end
87
+
88
+ def include_opted_in_concerns_in_model(include_lines)
89
+ model_file = File.join("app/models", class_path, "#{file_name}.rb")
90
+ simple_class_name = class_name.split("::").last
91
+
92
+ insert_into_file(
93
+ model_file,
94
+ include_lines,
95
+ after: /class #{Regexp.escape(simple_class_name)} < .*\n/
96
+ )
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,19 @@
1
+ module Api::<%= class_name %>
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ # Use self.json_attrs to drive json rendering for
6
+ # API model responses (index, show and update ones).
7
+ # For reference:
8
+ # https://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html
9
+ # The object passed accepts only these keys:
10
+ # - only: list [] of model fields to be shown in JSON serialization
11
+ # - except: exclude these fields from the JSON serialization, is a list []
12
+ # - methods: include the result of some method defined in the model
13
+ # - include: include associated models, it's an object {} which also accepts the keys described here
14
+ cattr_accessor :json_attrs
15
+ self.json_attrs = ::ModelDrivenApi.smart_merge (json_attrs || {}), {}
16
+
17
+ # Custom action callable by the API must be defined in /app/models/concerns/endpoints/
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ module RailsAdmin::<%= class_name %>
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ rails_admin do
6
+ navigation_label I18n.t('admin.registries.label')
7
+ navigation_icon 'fa fa-file' # TODO: customize icon, see https://fontawesome.com/v5/search
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,107 @@
1
+ require "thor/error"
2
+
3
+ module Thecore
4
+ module Generators
5
+ # Ruby port of thecore_code_extension's libs/workspaceContext.js
6
+ # (specifically its `atomRootOf`/`hasGemspec` gemspec-presence-under-
7
+ # vendor/submodules detection). The extension resolved context from a
8
+ # right-clicked VS Code folder; here we resolve it from the invoking
9
+ # process's `Dir.pwd`, since a terminal has no clicked folder — see
10
+ # docs/adr/0002-thecore-generators-gem-and-generator-hook-mechanism.md in
11
+ # the thecore repo.
12
+ #
13
+ # There is no AppContext/ATOMContext class pair here (unlike the JS
14
+ # original): a generator only ever needs one thing from this module — the
15
+ # absolute ATOM directory to redirect file placement to, or `nil` when
16
+ # `cwd` (and no `--atom` override) resolves to plain host-app context, in
17
+ # which case the generator leaves Rails' own default placement (relative
18
+ # to `destination_root`, already the app root for a real `rails generate`
19
+ # invocation) untouched.
20
+ module WorkspaceContext
21
+ module_function
22
+
23
+ # Returns the absolute ATOM directory for placement, or nil for
24
+ # host-app context.
25
+ #
26
+ # `atom_name`, when present (a generator's `--atom=NAME` option), is an
27
+ # explicit override that skips `cwd`-based detection entirely and is
28
+ # resolved as `<app_root>/vendor/submodules/<atom_name>` instead — this
29
+ # is what lets `--atom=NAME` work "from anywhere", independent of `cwd`.
30
+ # `app_root` is the generator's own (pre-override) `destination_root`:
31
+ # for a real `rails generate` invocation that is already
32
+ # `Rails::Command.root` (see rails/commands/generate/generate_command.rb),
33
+ # and in tests it's whatever `Rails::Generators::TestCase` configured as
34
+ # `destination_root` — either way it's the correct anchor without this
35
+ # module needing its own notion of "the app root".
36
+ def atom_dir_for(cwd:, app_root:, atom_name: nil)
37
+ atom_name = atom_name.to_s.strip
38
+ return resolve_named_atom(app_root, atom_name) unless atom_name.empty?
39
+
40
+ resolve_cwd_atom(cwd)
41
+ end
42
+
43
+ # Walks up from `dir` until the immediate parent directory is
44
+ # `vendor/submodules` — that child is the ATOM root. Mirrors
45
+ # workspaceContext.js's `atomRootOf`. Returns nil if `dir` is not
46
+ # inside a `vendor/submodules/<atom>/` tree at all.
47
+ def atom_root_of(dir)
48
+ current = File.expand_path(dir.to_s)
49
+
50
+ loop do
51
+ parent = File.dirname(current)
52
+ return nil if parent == current # reached the filesystem root
53
+
54
+ if File.basename(parent) == "submodules" && File.basename(File.dirname(parent)) == "vendor"
55
+ return current
56
+ end
57
+
58
+ current = parent
59
+ end
60
+ end
61
+
62
+ # Ported from workspaceContext.js's `hasGemspec`: an ATOM directory is
63
+ # valid when it contains `<dirname>.gemspec` or, since gem names can't
64
+ # contain dashes, the dash-to-underscore variant of it.
65
+ def gemspec_path_for(atom_dir)
66
+ atom_name = File.basename(atom_dir)
67
+
68
+ [atom_name, atom_name.tr("-", "_")].each do |candidate|
69
+ path = File.join(atom_dir, "#{candidate}.gemspec")
70
+ return path if File.exist?(path)
71
+ end
72
+
73
+ nil
74
+ end
75
+
76
+ def valid_atom_dir?(atom_dir)
77
+ File.directory?(atom_dir) && !gemspec_path_for(atom_dir).nil?
78
+ end
79
+
80
+ class << self
81
+ private
82
+
83
+ def resolve_named_atom(app_root, atom_name)
84
+ candidate = File.join(app_root.to_s, "vendor", "submodules", atom_name)
85
+ return candidate if valid_atom_dir?(candidate)
86
+
87
+ raise Thor::Error,
88
+ "No ATOM named '#{atom_name}' found at #{candidate} " \
89
+ "(expected a #{atom_name}.gemspec or #{atom_name.tr('-', '_')}.gemspec inside it)."
90
+ end
91
+
92
+ def resolve_cwd_atom(cwd)
93
+ candidate = atom_root_of(cwd)
94
+ return nil unless candidate
95
+
96
+ unless valid_atom_dir?(candidate)
97
+ raise Thor::Error,
98
+ "#{candidate} is under vendor/submodules/ but has no gemspec - " \
99
+ "not a valid Thecore ATOM."
100
+ end
101
+
102
+ candidate
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -1,13 +1,25 @@
1
+ require "rails/railtie"
2
+
1
3
  module ThecoreGenerators
2
- # Boot-time hook point for this gem. Intentionally empty for now: no
3
- # generator behaviour ships in this release. A future ticket will add
4
+ # Hooks `rails generate model`/`rails generate migration` the same way
5
+ # ActiveRecord's own Railtie does (`config.app_generators.orm :active_record,
6
+ # migration: true, timestamps: true` in active_record/railtie.rb) and Mongoid
7
+ # does for its own ORM. Registering this at the class body level — not inside
8
+ # an `initializer` block — matters: `config.app_generators` is a process-wide
9
+ # singleton (`Rails::Railtie::Configuration#app_generators`) copied into
10
+ # `Rails::Generators.options` early during boot, so this must run at require
11
+ # time, exactly mirroring ActiveRecord's own placement, to reliably win by
12
+ # require order (see docs/adr/0002-thecore-generators-gem-and-generator-hook-mechanism.md
13
+ # in the thecore repo).
4
14
  #
5
- # config.app_generators.orm :thecore, migration: true, timestamps: true
6
- #
7
- # here, following the same mechanism ActiveRecord's own Railtie and
8
- # Mongoid both use to hook `rails generate model`/`migration` (see
9
- # docs/adr/0002-thecore-generators-gem-and-generator-hook-mechanism.md in
10
- # the thecore repo).
15
+ # This makes plain `rails generate model`/`rails generate migration` resolve
16
+ # to Thecore::Generators::ModelGenerator/MigrationGenerator (namespaces
17
+ # "thecore:model"/"thecore:migration") instead of ActiveRecord's own
18
+ # generators, with zero new command vocabulary for developers.
19
+ # `rails generate active_record:model`/`active_record:migration` remain
20
+ # available directly as an escape hatch — Rails only hides the override from
21
+ # `--help`, it never blocks direct namespace invocation.
11
22
  class Railtie < ::Rails::Railtie
23
+ config.app_generators.orm :thecore, migration: true, timestamps: true
12
24
  end
13
25
  end
@@ -1,3 +1,3 @@
1
1
  module ThecoreGenerators
2
- VERSION = "3.0.0"
2
+ VERSION = "3.2.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thecore_generators
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabriele Tassoni
@@ -36,6 +36,12 @@ files:
36
36
  - MIT-LICENSE
37
37
  - README.md
38
38
  - Rakefile
39
+ - lib/generators/thecore/atom_aware.rb
40
+ - lib/generators/thecore/migration/migration_generator.rb
41
+ - lib/generators/thecore/model/model_generator.rb
42
+ - lib/generators/thecore/model/templates/api_concern.rb.tt
43
+ - lib/generators/thecore/model/templates/rails_admin_concern.rb.tt
44
+ - lib/generators/thecore/workspace_context.rb
39
45
  - lib/thecore_generators.rb
40
46
  - lib/thecore_generators/railtie.rb
41
47
  - lib/thecore_generators/version.rb