thecore_generators 3.6.0 → 3.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 +4 -4
- data/README.md +166 -14
- data/lib/generators/thecore/association_wiring.rb +2 -1
- data/lib/generators/thecore/atom/atom_generator.rb +481 -0
- data/lib/generators/thecore/atom/templates/abilities.rb.tt +16 -0
- data/lib/generators/thecore/atom/templates/seeds.rb.tt +1 -0
- data/lib/generators/thecore/collection_action/collection_action_generator.rb +64 -0
- data/lib/generators/thecore/collection_action/templates/action.html.erb.tt +13 -0
- data/lib/generators/thecore/collection_action/templates/action.js.tt +42 -0
- data/lib/generators/thecore/collection_action/templates/action.rb.tt +33 -0
- data/lib/generators/thecore/collection_action/templates/action.scss.tt +38 -0
- data/lib/generators/thecore/sample_fetcher.rb +68 -0
- data/lib/generators/thecore/tty_detection.rb +19 -0
- data/lib/templates/app_template.rb +220 -0
- data/lib/thecore_generators/check_practices.rb +20 -14
- data/lib/thecore_generators/version.rb +1 -1
- metadata +12 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Spinner
|
|
2
|
+
.loader {
|
|
3
|
+
width: 40px;
|
|
4
|
+
height: 40px;
|
|
5
|
+
position: relative;
|
|
6
|
+
margin: 0 auto;
|
|
7
|
+
}
|
|
8
|
+
.double-bounce1,
|
|
9
|
+
.double-bounce2 {
|
|
10
|
+
width: 100%;
|
|
11
|
+
height: 100%;
|
|
12
|
+
border-radius: 50%;
|
|
13
|
+
background-color: #333;
|
|
14
|
+
opacity: 0.6;
|
|
15
|
+
position: absolute;
|
|
16
|
+
top: 0;
|
|
17
|
+
left: 0;
|
|
18
|
+
animation: sk-bounce 2.0s infinite ease-in-out;
|
|
19
|
+
}
|
|
20
|
+
.double-bounce2 {
|
|
21
|
+
animation-delay: -1.0s;
|
|
22
|
+
}
|
|
23
|
+
@keyframes sk-bounce {
|
|
24
|
+
0%,
|
|
25
|
+
100% {
|
|
26
|
+
transform: scale(0.0);
|
|
27
|
+
}
|
|
28
|
+
50% {
|
|
29
|
+
transform: scale(1.0);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// End Spinner
|
|
33
|
+
#<%= file_name %>-response {
|
|
34
|
+
border-radius: 1em;
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
justify-content: center;
|
|
38
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module Thecore
|
|
2
|
+
module Generators
|
|
3
|
+
# Fetches one asset from thecore's own samples/ directory, via one overridable
|
|
4
|
+
# point: ENV["THECORE_SAMPLES_SOURCE"], resolved fresh on every call (never
|
|
5
|
+
# memoized), defaulting to the real raw GitHub URL for thecore's samples/ on
|
|
6
|
+
# `master` (thecore's own default branch). An http(s) value is fetched over the
|
|
7
|
+
# network via Thor's `get`; anything else is treated as a local directory and
|
|
8
|
+
# read directly with `File.read` (this gem's own tests point it at a fixture,
|
|
9
|
+
# so the suite runs offline and deterministically). Blank-string-safe
|
|
10
|
+
# (`nil? || empty?`, not `||` alone — `ENV["X"] || default` would treat
|
|
11
|
+
# THECORE_SAMPLES_SOURCE="" as a real override). Always writes `force: true` —
|
|
12
|
+
# a clean overwrite, no interactive Thor conflict prompt. Fails fast, naming
|
|
13
|
+
# the file/source/underlying error, rather than letting a raw
|
|
14
|
+
# OpenURI::HTTPError propagate and leave the caller half-scaffolded.
|
|
15
|
+
#
|
|
16
|
+
# A plain module function, not a mixin — `get`/`create_file` are public
|
|
17
|
+
# Thor::Actions instance methods (verified directly against Thor's own
|
|
18
|
+
# source), so they're callable on any `actor` passed in. `abort` (Kernel's) is
|
|
19
|
+
# private, so it's invoked via `actor.send(:abort, ...)` rather than a direct
|
|
20
|
+
# call — the one place this differs from calling it bare on `self`.
|
|
21
|
+
#
|
|
22
|
+
# A trailing slash on THECORE_SAMPLES_SOURCE is tolerated (`.chomp("/")`) before
|
|
23
|
+
# building the http(s) URL - a natural way to write/copy a base URL, and one
|
|
24
|
+
# `lib/templates/app_template.rb`'s own independent copy does not guard against
|
|
25
|
+
# (its own plain string interpolation would request a double-slashed path,
|
|
26
|
+
# 404ing against most static hosts/CDNs); caught here during review and not
|
|
27
|
+
# backported there, since that copy is intentionally left untouched (see below).
|
|
28
|
+
#
|
|
29
|
+
# AtomGenerator uses this module directly (`require`d normally, like any other
|
|
30
|
+
# file in this gem). The App application template's own `fetch_thecore_sample`
|
|
31
|
+
# (lib/templates/app_template.rb) is a *separate*, deliberately self-contained
|
|
32
|
+
# copy, NOT switched to call this module — that generator's initial version
|
|
33
|
+
# of this comment claimed the reason was instance_eval/mixin incompatibility,
|
|
34
|
+
# which review correctly identified as wrong (a module function needs no
|
|
35
|
+
# inheritance/mixin relationship to its caller; TtyDetection is proof this
|
|
36
|
+
# already works the same way from an instance_eval'd context). The real
|
|
37
|
+
# reason is deployment, not syntax: the App template's primary real-world
|
|
38
|
+
# invocation is `rails new myapp -m https://raw.githubusercontent.com/.../app_template.rb`
|
|
39
|
+
# — Thor's `apply`/`instance_eval` fetches and evaluates *that one URL's
|
|
40
|
+
# content only*, with no mechanism to also pull in a sibling file from this
|
|
41
|
+
# gem's own repo the way a normal `require` would. At the moment that command
|
|
42
|
+
# runs there is no app yet, so nothing has installed `thecore_generators` as a
|
|
43
|
+
# dependency either — a `require "generators/thecore/sample_fetcher"` inside
|
|
44
|
+
# the template would only work by accident (a global gem install happening to
|
|
45
|
+
# already be on the load path), not by design. So the App template keeps its
|
|
46
|
+
# own independent copy, and this module is not a hard requirement it could
|
|
47
|
+
# `require` — extracting it here still removes the duplication between this
|
|
48
|
+
# module and AtomGenerator, `thecore_generators`' own second, in-gem consumer.
|
|
49
|
+
module SampleFetcher
|
|
50
|
+
module_function
|
|
51
|
+
|
|
52
|
+
def fetch_thecore_sample(actor, relative_path, destination, label:)
|
|
53
|
+
source = ENV["THECORE_SAMPLES_SOURCE"]
|
|
54
|
+
source = "https://raw.githubusercontent.com/gabrieletassoni/thecore/master/samples" if source.nil? || source.empty?
|
|
55
|
+
|
|
56
|
+
if source.start_with?("http://", "https://")
|
|
57
|
+
actor.get("#{source.chomp("/")}/#{relative_path}", destination, force: true)
|
|
58
|
+
else
|
|
59
|
+
actor.create_file(destination, File.read(File.join(source, relative_path)), force: true)
|
|
60
|
+
end
|
|
61
|
+
rescue StandardError => e
|
|
62
|
+
actor.send(:abort, "Failed to fetch #{relative_path} from #{source} (#{e.class}: #{e.message}) " \
|
|
63
|
+
"-- aborting #{label}. Set THECORE_SAMPLES_SOURCE to override the source. If this left " \
|
|
64
|
+
"a partially-generated directory behind, remove it before retrying.")
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Thecore
|
|
2
|
+
module Generators
|
|
3
|
+
# A caller with no real TTY behind stdin/stdout (CI, a shelled-out child
|
|
4
|
+
# process) can never answer an interactive prompt. Shared by
|
|
5
|
+
# AssociationWiring's own inverse-association cardinality prompt and
|
|
6
|
+
# AtomGenerator's metadata/dependency prompts, extracted after the two
|
|
7
|
+
# independently implemented the identical condition (caught in review,
|
|
8
|
+
# thecore_generators#20) - a single source of truth means a future
|
|
9
|
+
# refinement to this detection (e.g. an ENV["CI"] check) can't silently
|
|
10
|
+
# apply to one generator's prompts and not the other's.
|
|
11
|
+
module TtyDetection
|
|
12
|
+
module_function
|
|
13
|
+
|
|
14
|
+
def real_tty?
|
|
15
|
+
$stdin.tty? && $stdout.tty?
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Thecore 3 Application Template — porting createApp.js's Gemfile/vendor-directory
|
|
4
|
+
# behavior (thecore_generators#17) plus devcontainer/CI/CLAUDE.md assets fetched from
|
|
5
|
+
# thecore's own samples/ (thecore_generators#18). See ADR 0005 in the thecore repo for
|
|
6
|
+
# the full design rationale behind both.
|
|
7
|
+
#
|
|
8
|
+
# Invoke via:
|
|
9
|
+
#
|
|
10
|
+
# rails new myapp --database=postgresql --asset-pipeline=sprockets \
|
|
11
|
+
# -m https://raw.githubusercontent.com/gabrieletassoni/thecore_generators/release/3/lib/templates/app_template.rb
|
|
12
|
+
#
|
|
13
|
+
# (or a local path to this file, e.g. while developing thecore_generators itself)
|
|
14
|
+
|
|
15
|
+
# --- Core Gemfile stack ------------------------------------------------------
|
|
16
|
+
# Always added, uncommented — every Thecore host app needs these (see thecore's own
|
|
17
|
+
# CLAUDE.md/GUIDE.md, "Standard Gem Stack").
|
|
18
|
+
gem "devise"
|
|
19
|
+
gem "cancancan"
|
|
20
|
+
gem "rails_admin"
|
|
21
|
+
# `rails_admin:install --asset=sprockets` (below) also unconditionally appends its own
|
|
22
|
+
# `gem 'sassc-rails'` line via its `configure_for_sprockets` step -- verified against
|
|
23
|
+
# the installed rails_admin 3.3.0 source, that step does nothing else. The resulting
|
|
24
|
+
# duplicate is harmless (empirically confirmed: `bundle lock` against two identical,
|
|
25
|
+
# unconstrained `gem` lines warns "lists the gem more than once" but resolves and
|
|
26
|
+
# exits 0) -- not worth a fragile post-install dedupe for a cosmetic Gemfile wart, and
|
|
27
|
+
# this declaration must stay regardless, since sassc-rails needs to be active even
|
|
28
|
+
# when the installer chain below is declined.
|
|
29
|
+
gem "sassc-rails"
|
|
30
|
+
# ADR 0001 (thecore repo) requires model_driven_api >= 3.9.0 / thecore_ui_rails_admin
|
|
31
|
+
# >= 3.8.0 for the DefaultModuleRegistry default-concern behavior this whole ecosystem
|
|
32
|
+
# now relies on -- matching the floor this gem's own Gemfile already pins to (see its
|
|
33
|
+
# comment), not an arbitrary choice.
|
|
34
|
+
gem "model_driven_api", "~> 3.9"
|
|
35
|
+
gem "thecore_ui_rails_admin", "~> 3.8"
|
|
36
|
+
gem "rails-erd", group: :development
|
|
37
|
+
|
|
38
|
+
# thecore_generators itself is dev-tooling only (it hooks `rails g model`/`migration`,
|
|
39
|
+
# see ADR 0002 in the thecore repo) — never a runtime dependency, so it goes in the
|
|
40
|
+
# :development group. A single-line `group:` option is equivalent to (and simpler
|
|
41
|
+
# than) createApp.js's manual `group :development do ... end` block insertion.
|
|
42
|
+
gem "thecore_generators", "~> 3.6", group: :development
|
|
43
|
+
|
|
44
|
+
# --- Optional ecosystem gems, discoverable but off by default ---------------
|
|
45
|
+
# Same "commented but documented" philosophy as the devcontainer's gh/glab CLI
|
|
46
|
+
# mounts (ADR 0005): each of these publishes to RubyGems.org (see thecore's own
|
|
47
|
+
# CLAUDE.md) but isn't needed by every app, so it starts commented out with a
|
|
48
|
+
# one-line description — uncomment only the ones this project actually needs.
|
|
49
|
+
append_to_file "Gemfile", <<~RUBY
|
|
50
|
+
|
|
51
|
+
# The rest of the generic Thecore ecosystem — uncomment only what you need.
|
|
52
|
+
# gem "thecore_auth_commons", "~> 3.0" # Role/permission/predicate models and authorization scaffolding
|
|
53
|
+
# gem "thecore_settings", "~> 3.0" # ThecoreSettings key/value configuration store
|
|
54
|
+
# gem "thecore_print_commons", "~> 3.0" # Shared PDF/print generation helpers
|
|
55
|
+
# gem "thecore_background_jobs", "~> 3.0" # Shared background job scheduling helpers
|
|
56
|
+
# gem "thecore_ui_commons", "~> 3.0" # Shared UI helpers/components for the admin frontend
|
|
57
|
+
# gem "thecore_tcp_debug", "~> 3.0" # TCP-level debugging/diagnostics support
|
|
58
|
+
# gem "thecore_download_documents", "~> 3.0" # Document download support
|
|
59
|
+
# gem "thecore_dataentry_commons", "~> 3.0" # Shared data-entry UI helpers
|
|
60
|
+
# gem "thecore_connectors" # Helpers for connecting to external systems/data sources
|
|
61
|
+
RUBY
|
|
62
|
+
|
|
63
|
+
# --- Developer-convenience placeholder directories --------------------------
|
|
64
|
+
# NOT template content (ADR 0005) — just known, git-trackable locations to clone
|
|
65
|
+
# auxiliary repos into during local development. Created empty; nothing is
|
|
66
|
+
# pre-wired, no submodule declarations, no Gemfile `path:` entries.
|
|
67
|
+
empty_directory "vendor/submodules"
|
|
68
|
+
create_file "vendor/submodules/.keep", <<~TEXT
|
|
69
|
+
Clone auxiliary Thecore ecosystem repos here during local development (e.g. an
|
|
70
|
+
ATOM you're developing against this app). Not consumed by any Gemfile entry
|
|
71
|
+
automatically — add a `path:` gem yourself if you want one of these clones
|
|
72
|
+
bundled from source instead of from RubyGems.org.
|
|
73
|
+
TEXT
|
|
74
|
+
|
|
75
|
+
empty_directory "vendor/external"
|
|
76
|
+
create_file "vendor/external/.keep", <<~TEXT
|
|
77
|
+
Clone read-only reference repos here during local development (framework docs,
|
|
78
|
+
sibling tooling repos you want open alongside this app). Not consumed by
|
|
79
|
+
anything automatically.
|
|
80
|
+
TEXT
|
|
81
|
+
|
|
82
|
+
# --- Devcontainer / CI / CLAUDE.md assets, from thecore's own samples -------
|
|
83
|
+
# Single source of truth (ADR 0005) — not duplicated inside this gem. The base
|
|
84
|
+
# location is resolved fresh inside `fetch_thecore_sample` on every call, through
|
|
85
|
+
# one overridable point: `ENV["THECORE_SAMPLES_SOURCE"]`, defaulting to the real
|
|
86
|
+
# raw GitHub URL for thecore's `samples/` directory on `master` (thecore's own
|
|
87
|
+
# default branch — double-checked directly against that repo, not assumed from
|
|
88
|
+
# this gem's own `release/3` naming convention, which doesn't apply there). An
|
|
89
|
+
# unset *or blank* env var falls back to the default (an explicit emptiness
|
|
90
|
+
# check, not `||` alone — `ENV["X"] || default` would treat `THECORE_SAMPLES_SOURCE=""`,
|
|
91
|
+
# a realistic shape for an optional env var in a compose file with no value set,
|
|
92
|
+
# as a real override and try to read a same-named file relative to whatever the
|
|
93
|
+
# current directory happens to be, instead of falling back). An http(s) value is
|
|
94
|
+
# fetched over the network via `get`; anything else is treated as a local
|
|
95
|
+
# directory and read directly — this gem's own offline test points it at a
|
|
96
|
+
# fixture instead.
|
|
97
|
+
#
|
|
98
|
+
# NOTE: this default URL only serves real content once `thecore`'s `master`
|
|
99
|
+
# carries the commits that added `samples/CLAUDE.md`/`samples/.gitlab-ci.yml`
|
|
100
|
+
# and brought `samples/devcontainer/` up to date (thecore#14/#15) — as of this
|
|
101
|
+
# gem's own 3.8.0 release those commits exist only in a local checkout, not
|
|
102
|
+
# pushed to `origin/master` yet. Until they're pushed, the default URL 404s for
|
|
103
|
+
# `.gitlab-ci.yml`/`CLAUDE.md`/the two devcontainer scripts and serves stale
|
|
104
|
+
# content for `devcontainer.json`/`docker-compose.yml`. This is an operational
|
|
105
|
+
# sequencing issue (push `thecore` before relying on the default in production),
|
|
106
|
+
# not a defect in this code — but it means `THECORE_SAMPLES_SOURCE` pointed at a
|
|
107
|
+
# local clone of `thecore` is the only way to exercise the real default content
|
|
108
|
+
# today.
|
|
109
|
+
#
|
|
110
|
+
# Every write below is unconditional (`force: true`, no interactive prompt).
|
|
111
|
+
# Of the six `.devcontainer/*` files, four (`devcontainer.json`,
|
|
112
|
+
# `docker-compose.yml`, `Dockerfile`, `create-db-user.sql`) are expected to
|
|
113
|
+
# already exist, written by the separate, prior "Setup Devcontainer" bootstrap
|
|
114
|
+
# step this template runs inside of (verified directly against that command's
|
|
115
|
+
# source, `thecore_code_extension/commands/setupDevContainer.js`) — replacing
|
|
116
|
+
# them is the whole point, not a conflict to ask about. The other two
|
|
117
|
+
# (`link-host-home.sh`/`check-plugins.sh`) are *not* written by that step at
|
|
118
|
+
# all — genuinely new files here, not overwrites — but `force: true` is harmless
|
|
119
|
+
# for a new file and keeps every write in this block uniform.
|
|
120
|
+
# `.gitlab-ci.yml`/`CLAUDE.md` don't exist yet in the documented flow either,
|
|
121
|
+
# but stay unconditional too so re-running this template later
|
|
122
|
+
# (`bin/rails app:template`) is a clean overwrite, not a prompt.
|
|
123
|
+
#
|
|
124
|
+
# A fetch failure (today: the 404s above; going forward: any network blip, or
|
|
125
|
+
# `thecore` reorganizing `samples/`) aborts the whole template with a clear,
|
|
126
|
+
# specific message instead of continuing into a silently half-scaffolded app
|
|
127
|
+
# (some `.devcontainer/*` files present, others not, no clear signal pointing
|
|
128
|
+
# back to the real cause) -- the same fail-fast philosophy thecore_generators#17
|
|
129
|
+
# already applies to `bundle_command`/`rails_command` failures in the installer
|
|
130
|
+
# chain below.
|
|
131
|
+
def fetch_thecore_sample(relative_path, destination)
|
|
132
|
+
source = ENV["THECORE_SAMPLES_SOURCE"]
|
|
133
|
+
source = "https://raw.githubusercontent.com/gabrieletassoni/thecore/master/samples" if source.nil? || source.empty?
|
|
134
|
+
|
|
135
|
+
if source.start_with?("http://", "https://")
|
|
136
|
+
get("#{source}/#{relative_path}", destination, force: true)
|
|
137
|
+
else
|
|
138
|
+
create_file(destination, File.read(File.join(source, relative_path)), force: true)
|
|
139
|
+
end
|
|
140
|
+
rescue StandardError => e
|
|
141
|
+
abort("Failed to fetch #{relative_path} from #{source} (#{e.class}: #{e.message}) " \
|
|
142
|
+
"-- aborting the app template. Set THECORE_SAMPLES_SOURCE to override the source.")
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
%w[devcontainer.json docker-compose.yml Dockerfile create-db-user.sql link-host-home.sh check-plugins.sh].each do |file|
|
|
146
|
+
fetch_thecore_sample("devcontainer/#{file}", ".devcontainer/#{file}")
|
|
147
|
+
end
|
|
148
|
+
# `get`/`create_file` only write content, never permissions — the executable bit
|
|
149
|
+
# has to be restored explicitly for the two scripts (`thecore/samples/devcontainer/`
|
|
150
|
+
# stores them executable, but that's lost the moment their bytes cross an HTTP
|
|
151
|
+
# fetch or a plain `File.read`).
|
|
152
|
+
chmod ".devcontainer/link-host-home.sh", 0o755
|
|
153
|
+
chmod ".devcontainer/check-plugins.sh", 0o755
|
|
154
|
+
|
|
155
|
+
fetch_thecore_sample(".gitlab-ci.yml", ".gitlab-ci.yml")
|
|
156
|
+
fetch_thecore_sample("CLAUDE.md", "CLAUDE.md")
|
|
157
|
+
|
|
158
|
+
# --- Standard installer chain ------------------------------------------------
|
|
159
|
+
# Needs the gems added above actually bundled and installable, i.e. real network
|
|
160
|
+
# access — genuinely optional (not a test-only escape hatch): a developer
|
|
161
|
+
# bootstrapping offline can say no here and run these steps by hand once they
|
|
162
|
+
# have connectivity. Wrapped in `after_bundle` (Rails' own template mechanism
|
|
163
|
+
# for "run this once the gems this template just added are actually bundled")
|
|
164
|
+
# so it runs after — never before — the gems above are installed.
|
|
165
|
+
if options[:asset_pipeline].to_s != "sprockets"
|
|
166
|
+
say_status :warning,
|
|
167
|
+
"this template assumes --asset-pipeline=sprockets (got #{options[:asset_pipeline].inspect}) " \
|
|
168
|
+
"-- rails_admin:install below is still configured for sprockets regardless, see the invocation " \
|
|
169
|
+
"documented in this gem's README.",
|
|
170
|
+
:yellow
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
run_setup_now = yes?(
|
|
174
|
+
"Run `bundle install` and the standard installer generators (devise, rails_admin, " \
|
|
175
|
+
"active_storage, action_text, action_mailbox, cancan, erd) now? (y/n)"
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
after_bundle do
|
|
179
|
+
next unless run_setup_now
|
|
180
|
+
|
|
181
|
+
# `bundle_command`/`rails_command` never abort on failure by themselves (verified
|
|
182
|
+
# against railties' own source: `bundle_command` is a bare `system` call with no
|
|
183
|
+
# result check at all; `rails_command` only aborts when `abort_on_failure: true` is
|
|
184
|
+
# passed explicitly -- `generate` sets that internally, `rails_command` does not).
|
|
185
|
+
# createApp.js's own equivalent was one `&&`-joined shell command that failed the
|
|
186
|
+
# whole chain atomically on any step; matched here explicitly rather than silently
|
|
187
|
+
# limping on into later steps against a broken bundle/app.
|
|
188
|
+
abort("bundle install failed -- aborting the app template's installer chain") unless bundle_command("install")
|
|
189
|
+
|
|
190
|
+
generate "devise:install"
|
|
191
|
+
|
|
192
|
+
# The `_namespace` positional argument ("app") is RailsAdmin::InstallGenerator's own
|
|
193
|
+
# mount-path argument (not a placeholder/app-name) -- passing a non-blank value here
|
|
194
|
+
# is what makes it skip its interactive "Where do you want to mount rails_admin?"
|
|
195
|
+
# prompt (verified against its source), which nothing in this non-interactive chain
|
|
196
|
+
# could ever answer. The resulting namespace is irrelevant: `thecore_ui_rails_admin`
|
|
197
|
+
# already mounts `RailsAdmin::Engine` itself, in its own engine routes (see that
|
|
198
|
+
# gem's `config/routes.rb`) -- a second, active mount in *this* app's routes.rb would
|
|
199
|
+
# be a genuine duplicate route, not just cosmetic. `route(...)` below writes a
|
|
200
|
+
# commented placeholder line containing the exact substring
|
|
201
|
+
# (`"mount RailsAdmin::Engine"`) the installer checks for
|
|
202
|
+
# (`routes.rb.include?('mount RailsAdmin::Engine')`) *before* calling it, so it skips
|
|
203
|
+
# inserting an active one at all -- more robust than adding one and regex-stripping
|
|
204
|
+
# it back out afterward (a future RailsAdmin release reformatting its generated line
|
|
205
|
+
# would silently break a regex-based removal with no error raised anywhere).
|
|
206
|
+
route "# mount RailsAdmin::Engine -- already mounted by thecore_ui_rails_admin's own engine routes, see that gem's config/routes.rb"
|
|
207
|
+
generate "rails_admin:install", "app", "--asset=sprockets"
|
|
208
|
+
|
|
209
|
+
rails_command "active_storage:install", abort_on_failure: true
|
|
210
|
+
rails_command "action_text:install", abort_on_failure: true
|
|
211
|
+
# action_text:install (above) may add its own `image_processing` Gemfile dependency
|
|
212
|
+
# (verified against its source) -- this bundle is the one that actually picks that
|
|
213
|
+
# up; devise:install/rails_admin:install above added nothing new to bundle beyond
|
|
214
|
+
# what the first `bundle_command("install")` already covered, so no bundle call sits
|
|
215
|
+
# between them.
|
|
216
|
+
abort("bundle install failed -- aborting the app template's installer chain") unless bundle_command("install")
|
|
217
|
+
rails_command "action_mailbox:install", abort_on_failure: true
|
|
218
|
+
generate "cancan:ability"
|
|
219
|
+
generate "erd:install"
|
|
220
|
+
end
|
|
@@ -5,6 +5,7 @@ require "generators/thecore/workspace_context"
|
|
|
5
5
|
require "generators/thecore/action_companion"
|
|
6
6
|
require "generators/thecore/root_action/root_action_generator"
|
|
7
7
|
require "generators/thecore/member_action/member_action_generator"
|
|
8
|
+
require "generators/thecore/collection_action/collection_action_generator"
|
|
8
9
|
|
|
9
10
|
module Thecore
|
|
10
11
|
# `rails thecore:check_practices` — a Ruby port of thecore_code_extension's
|
|
@@ -50,8 +51,9 @@ module Thecore
|
|
|
50
51
|
# then re-scans and returns whatever violations remain, per ADR 0004:
|
|
51
52
|
# "exits non-zero whenever violations remain unresolved after any --fix
|
|
52
53
|
# pass" — this makes a fix that turns out incomplete (or a violation
|
|
53
|
-
# this
|
|
54
|
-
#
|
|
54
|
+
# this gem doesn't know how to fix at all, e.g. a broken action-file
|
|
55
|
+
# marker, never fixable for any kind) visible in the result rather than
|
|
56
|
+
# silently assumed fixed.
|
|
55
57
|
def self.run(app_root:, atom_name: nil, fix: false)
|
|
56
58
|
violations = Runner.new(app_root: app_root, atom_name: atom_name).run
|
|
57
59
|
return violations unless fix
|
|
@@ -63,12 +65,15 @@ module Thecore
|
|
|
63
65
|
# A Thor::Group instance whose only purpose is running
|
|
64
66
|
# Thecore::Generators::CompanionFiles' generic (action-kind-agnostic)
|
|
65
67
|
# after_initialize.rb/locale fixes against a specific destination_root
|
|
66
|
-
# and action name — used by Runner's Actions check for all three kinds
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
#
|
|
68
|
+
# and action name — used by Runner's Actions check for all three kinds.
|
|
69
|
+
# Companion-file (view/JS/SCSS) fixes do NOT go through this class for
|
|
70
|
+
# any kind — those delegate straight to the kind's own real generator
|
|
71
|
+
# (RootActionGenerator/MemberActionGenerator/CollectionActionGenerator,
|
|
72
|
+
# via ACTION_GENERATOR_CLASSES below) so the fix always uses that
|
|
73
|
+
# generator's own template. Deliberately not placed under
|
|
74
|
+
# lib/generators/ (and so never discovered as a `rails generate`
|
|
75
|
+
# namespace) — it is an internal implementation detail of
|
|
76
|
+
# check_practices' --fix, not a public command.
|
|
72
77
|
class GenericFixTarget < Rails::Generators::NamedBase
|
|
73
78
|
include Thecore::Generators::AtomAware
|
|
74
79
|
include Thecore::Generators::CompanionFiles
|
|
@@ -85,14 +90,15 @@ module Thecore
|
|
|
85
90
|
VIEW_MARKERS = ["stylesheet_link_tag", "javascript_include_tag"].freeze
|
|
86
91
|
JS_MARKERS = ["document.addEventListener('turbo:load'"].freeze
|
|
87
92
|
SCSS_MARKERS = ["@keyframes sk-bounce"].freeze
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
#
|
|
91
|
-
#
|
|
92
|
-
#
|
|
93
|
+
# All three kinds now have a generator whose own template rendering a
|
|
94
|
+
# companion-file fix can delegate to (thecore_generators#21, per ADR
|
|
95
|
+
# 0006 in the thecore repo) - collection_action's missing-companion
|
|
96
|
+
# violations were never fixable before this (ADR 0004 tracked it as a
|
|
97
|
+
# deliberate, temporary gap: "no generator to have gotten it right").
|
|
93
98
|
ACTION_GENERATOR_CLASSES = {
|
|
94
99
|
"root_action" => Thecore::Generators::RootActionGenerator,
|
|
95
100
|
"member_action" => Thecore::Generators::MemberActionGenerator,
|
|
101
|
+
"collection_action" => Thecore::Generators::CollectionActionGenerator,
|
|
96
102
|
}.freeze
|
|
97
103
|
|
|
98
104
|
def initialize(app_root:, atom_name: nil)
|
|
@@ -235,7 +241,7 @@ module Thecore
|
|
|
235
241
|
end
|
|
236
242
|
|
|
237
243
|
# Renders only the one missing companion file, via the actual
|
|
238
|
-
# Root/Member Action generator's own template - never the bundled
|
|
244
|
+
# Root/Member/Collection Action generator's own template - never the bundled
|
|
239
245
|
# "render all three companions" method, which would risk a
|
|
240
246
|
# non-interactive file-collision hang/prompt on a hand-customized
|
|
241
247
|
# sibling file that already exists with different content. A file
|
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.
|
|
4
|
+
version: 3.11.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gabriele Tassoni
|
|
@@ -38,7 +38,15 @@ files:
|
|
|
38
38
|
- Rakefile
|
|
39
39
|
- lib/generators/thecore/action_companion.rb
|
|
40
40
|
- lib/generators/thecore/association_wiring.rb
|
|
41
|
+
- lib/generators/thecore/atom/atom_generator.rb
|
|
42
|
+
- lib/generators/thecore/atom/templates/abilities.rb.tt
|
|
43
|
+
- lib/generators/thecore/atom/templates/seeds.rb.tt
|
|
41
44
|
- lib/generators/thecore/atom_aware.rb
|
|
45
|
+
- lib/generators/thecore/collection_action/collection_action_generator.rb
|
|
46
|
+
- lib/generators/thecore/collection_action/templates/action.html.erb.tt
|
|
47
|
+
- lib/generators/thecore/collection_action/templates/action.js.tt
|
|
48
|
+
- lib/generators/thecore/collection_action/templates/action.rb.tt
|
|
49
|
+
- lib/generators/thecore/collection_action/templates/action.scss.tt
|
|
42
50
|
- lib/generators/thecore/companion_files.rb
|
|
43
51
|
- lib/generators/thecore/member_action/member_action_generator.rb
|
|
44
52
|
- lib/generators/thecore/member_action/templates/action.html.erb.tt
|
|
@@ -54,8 +62,11 @@ files:
|
|
|
54
62
|
- lib/generators/thecore/root_action/templates/action.js.tt
|
|
55
63
|
- lib/generators/thecore/root_action/templates/action.rb.tt
|
|
56
64
|
- lib/generators/thecore/root_action/templates/action.scss.tt
|
|
65
|
+
- lib/generators/thecore/sample_fetcher.rb
|
|
66
|
+
- lib/generators/thecore/tty_detection.rb
|
|
57
67
|
- lib/generators/thecore/workspace_context.rb
|
|
58
68
|
- lib/tasks/thecore_generators_tasks.rake
|
|
69
|
+
- lib/templates/app_template.rb
|
|
59
70
|
- lib/thecore_generators.rb
|
|
60
71
|
- lib/thecore_generators/check_practices.rb
|
|
61
72
|
- lib/thecore_generators/railtie.rb
|