ruby_ui_scaffold 0.1.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.
Files changed (27) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +343 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +530 -0
  5. data/lib/generators/ruby_ui_scaffold/install/install_generator.rb +188 -0
  6. data/lib/generators/ruby_ui_scaffold/ruby_ui_scaffold_generator.rb +119 -0
  7. data/lib/generators/ruby_ui_scaffold/scaffold/scaffold_generator.rb +252 -0
  8. data/lib/generators/ruby_ui_scaffold/scaffold/templates/edit.rb.tt +34 -0
  9. data/lib/generators/ruby_ui_scaffold/scaffold/templates/form.rb.tt +50 -0
  10. data/lib/generators/ruby_ui_scaffold/scaffold/templates/index.rb.tt +108 -0
  11. data/lib/generators/ruby_ui_scaffold/scaffold/templates/index_data_table.rb.tt +187 -0
  12. data/lib/generators/ruby_ui_scaffold/scaffold/templates/new.rb.tt +34 -0
  13. data/lib/generators/ruby_ui_scaffold/scaffold/templates/show.rb.tt +55 -0
  14. data/lib/generators/ruby_ui_scaffold/scaffold_controller/scaffold_controller_generator.rb +43 -0
  15. data/lib/generators/ruby_ui_scaffold/scaffold_controller/templates/controller.rb.tt +75 -0
  16. data/lib/generators/ruby_ui_scaffold/scaffold_controller/templates/controller_data_table.rb.tt +110 -0
  17. data/lib/rails/commands/ruby_ui_scaffold/seed_command.rb +62 -0
  18. data/lib/ruby_ui_scaffold/attribute_helpers.rb +38 -0
  19. data/lib/ruby_ui_scaffold/component_installer.rb +24 -0
  20. data/lib/ruby_ui_scaffold/component_resolver.rb +74 -0
  21. data/lib/ruby_ui_scaffold/field_type_mapper.rb +164 -0
  22. data/lib/ruby_ui_scaffold/railtie.rb +25 -0
  23. data/lib/ruby_ui_scaffold/seeder.rb +115 -0
  24. data/lib/ruby_ui_scaffold/value_generator.rb +168 -0
  25. data/lib/ruby_ui_scaffold/version.rb +5 -0
  26. data/lib/ruby_ui_scaffold.rb +22 -0
  27. metadata +197 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ea2c9998050e2208005c500148ed961b083d93530e699992e5d8c2cd2463df05
4
+ data.tar.gz: 2331070feb2defcd9763082d11b8dd8c38a3523e2e3f1333eca359dd1b042d09
5
+ SHA512:
6
+ metadata.gz: b1965a5ee407847b93b9c01410ac939d9383143f864d7b9d96e2691304ff3f9e7034e7ed61910aa82421b8164760b1273dbdc9685906c083a1d3f1bed79bc692
7
+ data.tar.gz: fdde9d0a8f65ad928ece8044b07ec1dda306576d48e49bbed7eda5bfdb5ca3822278c9823109f7c977d5f383e2aa57b0130b53e41da3343d9b3c0de690177579
data/CHANGELOG.md ADDED
@@ -0,0 +1,343 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-06-09
11
+
12
+ ### Added
13
+
14
+ - **Lucide icons on the action buttons.** The index "New" link gets a `plus`
15
+ icon, the show "Edit" link a `pencil`, and the form's submit a `plus`
16
+ (create) / `check` (update). Each button gets `gap-2` for spacing and the
17
+ icon `size-4`, since ruby_ui's Button/Link don't auto-size or space SVGs.
18
+ Reuses the already-registered `lucide_icon` helper — no new dependency.
19
+ - **"Back" link in the new/edit form.** The shared form now renders a `Back`
20
+ link next to the submit button, pointing at `request.referer` and falling
21
+ back to the index path when there's no referer. Requires `request` in the
22
+ views, so the post-scaffold injection now also adds
23
+ `include Phlex::Rails::Helpers::Request` to `Components::Base` (idempotent).
24
+ - **`--skip-model` flag** for the scaffold generator — skips model/migration/
25
+ model-test/fixtures generation (the whole `:orm` hook) and only
26
+ (re)generates the controller, views, and route. Intended for re-runs
27
+ against an existing model: refresh the views after a template change, or
28
+ add `--datatable`, without Rails creating a duplicate migration or
29
+ clobbering the model. Implies `--force` (overwrites the regenerated files
30
+ and bypasses the class-collision check, which a re-run would otherwise
31
+ abort on). The model is never touched — put custom code there; the
32
+ controller/views are treated as regenerable.
33
+ - **Installer generator** — `bin/rails g ruby_ui_scaffold:install` automates
34
+ the first-time setup on a fresh Rails app. Runs `phlex:install`,
35
+ `ruby_ui:install`, `ruby_ui:component:all`, and backfills the 12
36
+ components the scaffold uses but that `:component:all` currently misses
37
+ (`link`, `table`, `alert_dialog`, `badge`, `select`, `combobox`,
38
+ `checkbox`, `textarea`, `data_table`, `native_select`, `calendar`,
39
+ `date_picker`). Every step is idempotent — re-running only touches what's
40
+ missing.
41
+ - **Automatic `ruby_ui` gem bootstrap** — when the `ruby_ui` gem isn't
42
+ loadable, the installer now adds
43
+ `gem "ruby_ui", github: "ruby-ui/ruby_ui", branch: "main", require: false`
44
+ to the Gemfile and runs `bundle install`, instead of aborting with manual
45
+ instructions. Idempotent: skips the Gemfile edit when an entry already
46
+ exists, and does nothing once the gem loads. Works even when the install
47
+ runs as a subprocess of the scaffold generator — the later sub-generator
48
+ steps spawn fresh subprocesses that boot with the updated bundle.
49
+ `phlex-rails` (a declared runtime dependency) keeps the abort-with-
50
+ instructions behavior. No-op when no Gemfile is present.
51
+ - **Auto-install on scaffold** — `bin/rails g ruby_ui_scaffold ...` now
52
+ auto-runs the idempotent `ruby_ui_scaffold:install` when phlex/ruby_ui
53
+ aren't detected, so generated views work out of the box. Falls back to a
54
+ non-blocking warning when there's no app `bin/rails` to drive it, or when
55
+ opted out with the new `--skip-install` flag.
56
+ - **`--literal` flag** for the scaffold generator — emits Phlex views using
57
+ [`literal`](https://literal.fun)'s `prop` macros instead of explicit
58
+ `def initialize` + `@ivar` assignments. Less boilerplate per view;
59
+ runtime type-checking included. On first use, also injects
60
+ `extend Literal::Properties` into `app/components/base.rb` (idempotent).
61
+ Combines with `--datatable` — the DataTable index gets the full typed
62
+ prop set (`_Any` collection, `Integer` pagination, `_Nilable(String)`
63
+ search/sort/direction). Controllers don't change: `render Views::*.new(...)`
64
+ still works since Literal generates a compatible `initialize`. `literal
65
+ (>= 1.0)` is now a runtime dependency.
66
+ - `phlex-rails (>= 2.0)` is now a declared runtime dependency, so Bundler
67
+ pulls it in automatically. `lib/ruby_ui_scaffold.rb` requires it eagerly
68
+ to ensure phlex-rails' railtie fires under `Bundler.require`, which is
69
+ what makes `bin/rails g phlex:install` discoverable.
70
+
71
+ ### Changed
72
+
73
+ - **Components are now installed on demand instead of all upfront.** The
74
+ installer no longer runs `ruby_ui:component:all` + a `MISSING_COMPONENTS`
75
+ backfill; it installs only the `ComponentResolver::BASE` shell every
76
+ scaffold uses (`table`, `link`, `button`, `card`, `typography`,
77
+ `dropdown_menu`, `alert_dialog`, `form`, `input`). Each `rails g
78
+ ruby_ui_scaffold` then installs just the column/flag-specific components
79
+ that scaffold references — `badge`/`checkbox` (boolean), `textarea`
80
+ (text), `combobox`/`select` (references), `date_picker` (date),
81
+ `data_table` (`--datatable`) — right after writing the views, skipping any
82
+ already present. Net result: apps carry only the components they use, and
83
+ total component installs are always ≤ the old install-everything approach.
84
+ New `ComponentResolver` (pure mapping logic) and `ComponentInstaller`
85
+ (shared install/skip helpers) modules back this. `--skip-install` opts out
86
+ of on-demand installs too. Relies on `ruby_ui:component` resolving
87
+ transitive dependencies (it does, via ruby_ui's `dependencies.yml`).
88
+ - `date` columns now render the ruby_ui `DatePicker` (a Popover + Calendar
89
+ over a submittable input) instead of a native `Input(type: "date")`. The
90
+ generated form passes the record's date straight to `selected_date:` (the
91
+ component derives the input's ISO `yyyy-MM-dd` value from it) and
92
+ `label: nil` to avoid duplicating the form's `FormFieldLabel`. `datetime`
93
+ and `time` columns are unchanged (still native inputs — `DatePicker` has
94
+ no time component). The installer's component backfill now includes
95
+ `calendar` and `date_picker` to cover the new dependency.
96
+ - The post-scaffold `Components::Base` injection now adds four more Phlex
97
+ helpers in addition to `lucide_icon` — `Phlex::Rails::Helpers::FormWith`,
98
+ `LinkTo`, `ButtonTo`, and `Request`. They're required by the
99
+ scaffold-generated views (`form_with`, `link_to`, `button_to`, and
100
+ `request.referer` for the form's Back link) but aren't included by
101
+ `phlex:install` / `ruby_ui:install` by default. Each line is added only
102
+ if absent, so re-running is safe.
103
+ - The installer now invokes sub-generators via `system` (instead of Thor's
104
+ `generate` action) and aborts with a clear message on the first
105
+ subprocess failure. Thor's `abort_on_failure` doesn't reliably propagate
106
+ when the failure originates inside a nested Rails command (e.g. Bundler
107
+ bootstrap errors swallow the exit code). Without this, one bad step would
108
+ cascade into dozens of follow-up failures with the same root cause —
109
+ drowning the actual error in noise.
110
+ - The installer now injects `@source "../../views/**/*.rb"` and
111
+ `@source "../../components/**/*.rb"` into `app/assets/tailwind/application.css`.
112
+ Tailwind v4's automatic content detection skips `.rb` files, so without
113
+ this every Phlex class name (`mx-auto`, `max-w-3xl`, `max-w-prose`, etc.)
114
+ would silently fail to compile — making the scaffold's centered layout
115
+ render as left-aligned and unstyled. Idempotent; skipped if the file
116
+ isn't present (non-Tailwind setups).
117
+ - Form and Card layouts now use `w-full max-w-prose mx-auto` so they're
118
+ visually centered within the wrapper instead of sitting at the left edge.
119
+ - The outer `h-dvh overflow-y-auto` wrapper on every scaffolded view
120
+ (index, show, new, edit) now also has `w-full`. Without it, when the
121
+ host layout's container uses `display: flex` (common pattern: e.g.
122
+ `<main class="container mx-auto flex">...</main>`), the wrapper becomes
123
+ a flex item and shrinks to its content width — collapsing the
124
+ `mx-auto max-w-3xl` inner wrapper from 768px down to ~256px and making
125
+ the whole page render left-aligned instead of centered. `w-full` forces
126
+ the flex item to fill the parent regardless of flex/block context.
127
+
128
+ ## [0.1.0] - 2026-05-22
129
+
130
+ First public-ready release. Pre-1.0 — the API may still evolve before the
131
+ first stable cut.
132
+
133
+ ### Added
134
+
135
+ #### Scaffold generator (`rails g ruby_ui_scaffold MODEL field:type ...`)
136
+
137
+ - Inherits the full Rails scaffold pipeline (model, migration, resource route,
138
+ helper, tests) and replaces the controller + view layer with Phlex classes
139
+ wired to [ruby_ui](https://github.com/ruby-ui/ruby_ui) components.
140
+ - Three internal generators:
141
+ - `RubyUiScaffold::Generators::RubyUiScaffoldGenerator` — entry point,
142
+ namespaced flat as `ruby_ui_scaffold` (not `ruby_ui_scaffold:ruby_ui_scaffold`)
143
+ to avoid `find_by_namespace` shadowing.
144
+ - `RubyUiScaffold::Generators::ScaffoldControllerGenerator` — overrides
145
+ Rails' scaffold_controller template to render Phlex view classes via
146
+ `render ::Views::ModelName::Index.new(...)`.
147
+ - `RubyUiScaffold::Generators::ScaffoldGenerator` — the "template engine"
148
+ that emits the Phlex view files.
149
+ - Generated views live under the `Views::` module
150
+ (e.g. `Views::Buddies::Index < Views::Base`), matching the convention
151
+ installed by `phlex:install`. No bespoke initializer or autoload_paths
152
+ tweak required — `phlex:install` already wires `app/views/` as the
153
+ `Views::` namespace root in `config/initializers/phlex.rb`.
154
+ - On first run, `register_output_helper :lucide_icon` is injected into
155
+ `app/components/base.rb` (created by `phlex:install` / `ruby_ui:install`)
156
+ so the index dropdown trigger works out of the box. The injection is
157
+ idempotent — re-running the generator never duplicates the line.
158
+ - Field-type → ruby_ui component mapping (`RubyUiScaffold::FieldTypeMapper`),
159
+ covering `string`, `text`, `integer`, `float`, `decimal`, `boolean`, `date`,
160
+ `time`, `datetime`/`timestamp`, `password_digest`, `attachment(s)`,
161
+ `references`/`belongs_to`. Date/datetime values are formatted via `iso8601`
162
+ / `strftime` so the HTML5 inputs accept them.
163
+
164
+ #### Index view: plain `Table` (default) or `DataTable` (`--datatable`)
165
+
166
+ - Default index is a plain ruby_ui `Table` with header + body. Controller's
167
+ `index` is the bare minimum (`Model.all` plus `.includes(:assoc)` when
168
+ `belongs_to` is present); the view takes a single `models:` kwarg.
169
+ - Pass `--datatable` to opt into the full ruby_ui `DataTable` instead — adds
170
+ `DataTableToolbar` (`DataTableSearch` + `DataTablePerPageSelect`),
171
+ `DataTableSortHead` for sortable columns, and `DataTablePaginationBar` +
172
+ `DataTablePagination` (manual `page`/`per_page`/`total_count` adapter —
173
+ no pagy/kaminari dependency). The controller is upgraded with
174
+ `SORTABLE_COLUMNS` allowlist, `params[:search]` LIKE clause across
175
+ string columns, `params[:sort]`/`[:direction]` allowlist, and
176
+ `params[:page]`/`[:per_page]` clamp.
177
+ - Wrapped in `Table(class: "table-fixed")` so column widths stay equal
178
+ and the table never overflows its container. Text and reference cells
179
+ are wrapped in `div(class: "truncate", title: value)` — long content
180
+ is clipped with an ellipsis and revealed on hover, eliminating
181
+ horizontal scroll. The action column is locked to `w-16` (with
182
+ `whitespace-nowrap`) so the `•••` dropdown trigger is always visible.
183
+ - Search is rendered only when at least one `:string` column exists.
184
+ - Sortable columns exclude `:text`, `:rich_text`, `:json`/`:jsonb`, `:binary`,
185
+ and attachments. Non-sortable columns render as plain `TableHead`.
186
+ - The actions column is a `DropdownMenu` (`options: { strategy: "fixed" }`)
187
+ triggered by a Lucide `more-horizontal` icon (`lucide_icon("more-horizontal",
188
+ class: "size-5 cursor-pointer text-muted-foreground hover:text-foreground")`)
189
+ — matches Linkana's production pattern (no extra `<span>` wrapper so the
190
+ `data-action="click->ruby-ui--dropdown-menu#toggle"` reliably fires).
191
+ Menu items: Show, Edit, Separator, Delete.
192
+ - The entire view_template body is wrapped in
193
+ `div(class: "h-dvh overflow-y-auto")` so vertical scrolling works
194
+ regardless of how the host layout handles overflow — critical for
195
+ dashboards that ship with `body { overflow: hidden }` (e.g. Linkana)
196
+ where natural page scroll is suppressed in favor of inner-scroll
197
+ containers.
198
+
199
+ #### `--phlex-layout` flag
200
+
201
+ - `--phlex-layout=ClassName` makes every generated view wrap its
202
+ `view_template` body in `render(ClassName) do ... end` and emits
203
+ `layout false` in the controller. Use this when your app has a
204
+ Phlex layout class (with `include Phlex::Rails::Layout`) that's
205
+ responsible for the full HTML shell (including the `<script>`
206
+ tags). Without it, scaffolded pages would inherit the default
207
+ Rails layout — which in dual-layout apps (one ERB layout for
208
+ guest pages, one Phlex layout for the dashboard) can mean
209
+ loading the wrong JS bundle and breaking Stimulus controllers
210
+ on the page.
211
+
212
+ #### Destroy confirmation — ruby_ui `AlertDialog` (no JS confirm)
213
+
214
+ - The Delete dropdown item is **always** wrapped in a ruby_ui
215
+ `AlertDialog` with Title + Description + Cancel + Delete form
216
+ (submitted via `form_with(method: :delete)`). No JS browser
217
+ `confirm()` dialog — the confirmation lives inside the dropdown.
218
+ - The trigger inside the AlertDialog is a `DropdownMenuItem(href: nil)`
219
+ styled with `text-destructive`, matching Linkana's production pattern.
220
+
221
+ #### Centered, max-width layout
222
+
223
+ - Index: `mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-8` (wide for tables).
224
+ - Show / New / Edit: `mx-auto max-w-3xl ...` (focused on a single record /
225
+ form).
226
+
227
+ #### Real controller behavior (not just shell)
228
+
229
+ - Generated controller's `index` action:
230
+ - `SORTABLE_COLUMNS` allowlist baked at generator time.
231
+ - `params[:per_page]` clamped to `[1, MAX_PER_PAGE = 100]`, defaulting to
232
+ `DEFAULT_PER_PAGE = 10`.
233
+ - Case-insensitive `LOWER(col) LIKE :q` search across string columns (works
234
+ on PostgreSQL **and** SQLite).
235
+ - `scope.includes(:assoc)` auto-added when the model has non-polymorphic
236
+ `belongs_to` references — avoids N+1 on the index.
237
+ - `render ::Views::Model::Index.new(...)` with all pagination/search/sort kwargs.
238
+
239
+ #### `belongs_to` / `references` first-class support
240
+
241
+ - Forms switch dynamically between a searchable ruby_ui `Combobox`
242
+ (when the parent table has more than `COMBOBOX_THRESHOLD = 100`
243
+ records) and a plain `Select` (below the threshold) — no
244
+ `Input(type: "number")` placeholder. The threshold is baked as a
245
+ per-form class constant so users can tune per-resource.
246
+ - Both branches share the same option-label fallback chain:
247
+ `record.try(:name) → :title → :display_name → "Class #id"`,
248
+ so it works with any parent model out of the box.
249
+ - Index and Show display the friendly assoc label
250
+ (`book.author&.try(:name) || ...`) instead of the raw foreign key.
251
+ - Polymorphic references (`commentable:references{polymorphic}`) fall back
252
+ to `Input(type: "number")` + TODO comment.
253
+
254
+ ### Added
255
+
256
+ #### Seed command (`rails ruby_ui_scaffold:seed MODEL [COUNT]`)
257
+
258
+ - Implemented as a `Rails::Command::Base` subclass at
259
+ `lib/rails/commands/ruby_ui_scaffold/seed_command.rb` — auto-discovered
260
+ via Rails' `$LOAD_PATH`-based command lookup. Native flag syntax
261
+ (`rails ruby_ui_scaffold:seed Buddy --count 50`), no rake bracket
262
+ workarounds.
263
+ - Three options:
264
+ - `--count N` / `-c N` — number of records to create (defaults to 10
265
+ when omitted).
266
+ - `--reset` — `Model.destroy_all` before seeding.
267
+ - `--dry-run` — print one sample attribute hash without persisting.
268
+ - Output: per-10-record progress line + final summary with elapsed time,
269
+ created/skipped counts, and first 3 unique validation errors.
270
+
271
+ #### Inference chain (`RubyUiScaffold::ValueGenerator`)
272
+
273
+ For each column, the value comes from the first source that matches:
274
+
275
+ 1. **`belongs_to` foreign key** — samples an existing parent record's id
276
+ (`Parent.unscoped.ids.sample`).
277
+ 2. **`ActiveRecord::Enum`** — samples a key from `Model.defined_enums[col]`.
278
+ 3. **`validates :col, inclusion: { in: [...] }`** — samples from the list.
279
+ 4. **`validates :col, numericality: { greater_than: X, less_than: Y }`** —
280
+ respects the range.
281
+ 5. **Column name heuristics** — `email`, `first_name`, `last_name`, `name`,
282
+ `username`, `phone`, `address`, `city`, `state`, `country`, `zip`,
283
+ `url`, `title`, `body`/`content`/`description`/`bio`/`summary`/`notes`,
284
+ `company`, `slug`, `uuid`, `birthdate`/`birthday`/`dob`/`date_of_birth`,
285
+ `age`, `color`, `latitude`/`longitude`, `price`/`amount`, `quantity`/`qty`,
286
+ `password`/`password_digest`. With Faker installed these yield realistic
287
+ values; without, sensible `SecureRandom`-based fallbacks.
288
+ 6. **Column type fallback** — `:integer`, `:bigint`, `:float`/`:decimal`,
289
+ `:boolean`, `:date`, `:datetime`/`:timestamp`, `:time`, `:json`/`:jsonb`,
290
+ `:uuid`, `:string`, `:text`.
291
+
292
+ #### Seeder orchestration (`RubyUiScaffold::Seeder`)
293
+
294
+ - Preflight check: aborts with a helpful message if a `belongs_to` parent
295
+ has no records (`"Post requires Author records first. Run …"`).
296
+ - Per-record retry on validation failure (up to 3 attempts with newly
297
+ generated attributes).
298
+ - Skips columns automatically: `id`, `created_at`, `updated_at`, `*_count`
299
+ (counter caches), STI `inheritance_column`, and polymorphic `*_type`
300
+ columns.
301
+ - `Faker` is a **runtime dependency** of the gem, so realistic fake data
302
+ (names, emails, addresses, paragraphs) is always available — no extra
303
+ setup needed.
304
+
305
+ ### Dependencies
306
+
307
+ - Runtime: `railties >= 7.1`, `faker >= 2.0`, `lucide-rails >= 0.7`
308
+ - Development (tests): `rails >= 7.1`, `minitest ~> 5.0`, `rake ~> 13.0`,
309
+ `sqlite3 >= 2.0`
310
+
311
+ `lucide_icon` is registered as a Phlex output helper on `Components::Base`
312
+ (`register_output_helper :lucide_icon`, injected on first scaffold), so
313
+ it's callable from any scaffold-generated view. The injection is a no-op
314
+ if your `Components::Base` already declares it.
315
+
316
+ ### Tests
317
+
318
+ 68 runs, 442 assertions, 0 failures. Coverage:
319
+
320
+ - `FieldTypeMapper` — every type mapping plus Select (references) and
321
+ polymorphic fallback.
322
+ - `ValueGenerator` — type-based fallbacks (no Faker required) and the
323
+ full name-based heuristic catalog via mock columns.
324
+ - `Seeder` — happy path, retry on validations, enums, inclusion,
325
+ numericality range, `belongs_to` preflight, `--reset`, `--dry-run`,
326
+ using a real `sqlite3` in-memory connection with inline AR models.
327
+ - Scaffold generator — full template surface: DataTable structure,
328
+ centered layout, DropdownMenu trigger, AlertDialog destroy, references →
329
+ Combobox/Select switch in form, references → friendly label in
330
+ index/show, `--phlex-layout` wrapping.
331
+
332
+ ### Internal notes
333
+
334
+ - Rails::Generators option propagation: the railtie sets
335
+ `Rails::Generators.options[:ruby_ui_scaffold][:template_engine] =
336
+ "ruby_ui_scaffold"` **before** loading generator classes, because
337
+ `class_option` defaults are frozen at class-definition time.
338
+ - The entry generator's namespace is overridden to flat `"ruby_ui_scaffold"`
339
+ (not `"ruby_ui_scaffold:ruby_ui_scaffold"`) to avoid `find_by_namespace`
340
+ shadowing of the sub-generators when hooks fire.
341
+
342
+ [Unreleased]: https://github.com/jacksonpires/ruby_ui_scaffold/compare/v0.1.0...HEAD
343
+ [0.1.0]: https://github.com/jacksonpires/ruby_ui_scaffold/releases/tag/v0.1.0
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jackson Pires
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.