From 21a4c1ea4e740ad570eecc8c6f1987604b526579 Mon Sep 17 00:00:00 2001 From: Andy Cohen Date: Tue, 29 Sep 2026 11:51:51 -0500 Subject: [PATCH 1/6] Drop the redundant unbundled env around bundle add simple_form bundle_command already runs in Bundler.with_original_env. Co-Authored-By: Claude Opus 5.5 (1M context) --- lib/generators/rolemodel/simple_form/simple_form_generator.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/generators/rolemodel/simple_form/simple_form_generator.rb b/lib/generators/rolemodel/simple_form/simple_form_generator.rb index a27b637b..82e09ff2 100644 --- a/lib/generators/rolemodel/simple_form/simple_form_generator.rb +++ b/lib/generators/rolemodel/simple_form/simple_form_generator.rb @@ -8,9 +8,7 @@ class SimpleFormGenerator < GeneratorBase desc: 'Install the tailored_select experimental component input' def add_gem - Bundler.with_unbundled_env do - bundle_command 'add simple_form' - end + bundle_command 'add simple_form' end def add_files From 9b6832ac1ec2d127b917a5286c93b14ab3b2f4b2 Mon Sep 17 00:00:00 2001 From: Andy Cohen Date: Tue, 29 Sep 2026 11:51:51 -0500 Subject: [PATCH 2/6] Add a tom_select generator and run it from core_setup Installs tom-select, its stylesheet, and a Stimulus controller that tears Tom Select down before a Turbo morph and rebuilds it after, so the selected values survive. When SimpleForm is present it also installs the tom_select and grouped_tom_select inputs, both wired to those morph actions. core_setup runs it right after simple_form. Co-Authored-By: Claude Opus 5.5 (1M context) --- README.md | 1 + lib/generators/rolemodel/core_setup/README.md | 1 + .../core_setup/core_setup_generator.rb | 1 + lib/generators/rolemodel/tom_select/README.md | 14 ++++++ lib/generators/rolemodel/tom_select/USAGE | 7 +++ .../app/inputs/grouped_tom_select_input.rb | 9 ++++ .../templates/app/inputs/tom_select_input.rb | 19 ++++++++ .../controllers/tom_select_controller.js | 34 +++++++++++++++ .../tom_select/tom_select_generator.rb | 43 +++++++++++++++++++ .../rolemodel/core_setup_generator_spec.rb | 15 +++++++ .../rolemodel/tom_select_generator_spec.rb | 39 +++++++++++++++++ 11 files changed, 183 insertions(+) create mode 100644 lib/generators/rolemodel/tom_select/README.md create mode 100644 lib/generators/rolemodel/tom_select/USAGE create mode 100644 lib/generators/rolemodel/tom_select/templates/app/inputs/grouped_tom_select_input.rb create mode 100644 lib/generators/rolemodel/tom_select/templates/app/inputs/tom_select_input.rb create mode 100644 lib/generators/rolemodel/tom_select/templates/app/javascript/controllers/tom_select_controller.js create mode 100644 lib/generators/rolemodel/tom_select/tom_select_generator.rb create mode 100644 spec/generators/rolemodel/core_setup_generator_spec.rb create mode 100644 spec/generators/rolemodel/tom_select_generator_spec.rb diff --git a/README.md b/README.md index 3a75f3bb..9d767c78 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,7 @@ bin/rails g * [GoodJob](./lib/generators/rolemodel/good_job) * [Editors](./lib/generators/rolemodel/editors) * [Tailored Select](./lib/generators/rolemodel/tailored_select) +* [Tom Select](./lib/generators/rolemodel/tom_select) * [Lograge](./lib/generators/rolemodel/lograge) ## Utilities diff --git a/lib/generators/rolemodel/core_setup/README.md b/lib/generators/rolemodel/core_setup/README.md index 6b7c3116..35910902 100644 --- a/lib/generators/rolemodel/core_setup/README.md +++ b/lib/generators/rolemodel/core_setup/README.md @@ -21,6 +21,7 @@ app you can push straight to Heroku right after generation. - [Testing](../testing) — RSpec, FactoryBot, parallel_tests, TestProf (pass `--js-runner` to include jasmine-playwright-runner) - [SimpleForm](../simple_form) — SimpleForm with our configuration + - [Tom Select](../tom_select) — Tom Select with a Stimulus controller and SimpleForm inputs - [Linters](../linters) — Rubocop and ESLint - [UI Components](../ui_components) — flash, the modal pattern, & Turbo 8 support - [Editors](../editors) — EditorConfig and recommended VSCode extensions diff --git a/lib/generators/rolemodel/core_setup/core_setup_generator.rb b/lib/generators/rolemodel/core_setup/core_setup_generator.rb index 2efa2a6f..166ebbba 100644 --- a/lib/generators/rolemodel/core_setup/core_setup_generator.rb +++ b/lib/generators/rolemodel/core_setup/core_setup_generator.rb @@ -7,6 +7,7 @@ def run_the_core_generators generate 'rolemodel:webpack' generate 'rolemodel:optics:all' generate 'rolemodel:simple_form' + generate 'rolemodel:tom_select' generate 'rolemodel:testing:all' generate 'rolemodel:turbo:all' generate 'rolemodel:ui_components:flash' diff --git a/lib/generators/rolemodel/tom_select/README.md b/lib/generators/rolemodel/tom_select/README.md new file mode 100644 index 00000000..87604404 --- /dev/null +++ b/lib/generators/rolemodel/tom_select/README.md @@ -0,0 +1,14 @@ +# Tom Select Generator + +`rails g rolemodel:tom_select` + +## What you get + +* The [Tom Select](https://tom-select.js.org/) package and its stylesheet +* A `tom-select` Stimulus controller that survives Turbo morphs +* `tom_select` and `grouped_tom_select` SimpleForm inputs, if the app uses SimpleForm + +```slim += f.input :project_manager, as: :tom_select, collection: User.all += f.input :material, as: :grouped_tom_select, collection: Category.all, group_method: :materials +``` diff --git a/lib/generators/rolemodel/tom_select/USAGE b/lib/generators/rolemodel/tom_select/USAGE new file mode 100644 index 00000000..4a31c6c1 --- /dev/null +++ b/lib/generators/rolemodel/tom_select/USAGE @@ -0,0 +1,7 @@ +Description: + Installs the tom-select package, its stylesheet, and a tom-select Stimulus + controller. If the app is using SimpleForm, it also installs the matching + tom_select and grouped_tom_select SimpleForm inputs. + +Example: + rails generate rolemodel:tom_select diff --git a/lib/generators/rolemodel/tom_select/templates/app/inputs/grouped_tom_select_input.rb b/lib/generators/rolemodel/tom_select/templates/app/inputs/grouped_tom_select_input.rb new file mode 100644 index 00000000..6b7a12cf --- /dev/null +++ b/lib/generators/rolemodel/tom_select/templates/app/inputs/grouped_tom_select_input.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class GroupedTomSelectInput < SimpleForm::Inputs::GroupedCollectionSelectInput + def input(wrapper_options = nil) + super(merge_wrapper_options(TomSelectInput.stimulus_options, wrapper_options)) + end + + def input_html_classes = [] +end diff --git a/lib/generators/rolemodel/tom_select/templates/app/inputs/tom_select_input.rb b/lib/generators/rolemodel/tom_select/templates/app/inputs/tom_select_input.rb new file mode 100644 index 00000000..6043849e --- /dev/null +++ b/lib/generators/rolemodel/tom_select/templates/app/inputs/tom_select_input.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class TomSelectInput < SimpleForm::Inputs::CollectionSelectInput + def self.stimulus_options + { + data: { + controller: 'tom-select', + tom_select_target: 'dropdown', + action: 'turbo:before-morph-element->tom-select#disconnect:self turbo:morph-element->tom-select#afterMorph:self' + } + } + end + + def input(wrapper_options = nil) + super(merge_wrapper_options(self.class.stimulus_options, wrapper_options)) + end + + def input_html_classes = [] +end diff --git a/lib/generators/rolemodel/tom_select/templates/app/javascript/controllers/tom_select_controller.js b/lib/generators/rolemodel/tom_select/templates/app/javascript/controllers/tom_select_controller.js new file mode 100644 index 00000000..b53fda9c --- /dev/null +++ b/lib/generators/rolemodel/tom_select/templates/app/javascript/controllers/tom_select_controller.js @@ -0,0 +1,34 @@ +import { Controller } from '@hotwired/stimulus' +import TomSelect from 'tom-select' + +export default class extends Controller { + static targets = ['dropdown'] + + connect() { + this.tomSelect = new TomSelect(this.dropdownTarget, this.baseSettings) + this.element.tomSelect = this.tomSelect + } + + disconnect() { + // In case a Turbo morph is happening, we need to update TomSelect's revertSettings, + // in order to preserve the current value(s) when reconnecting. + this.tomSelect.revertSettings.innerHTML = this.element.innerHTML + + this.tomSelect.destroy() + delete this.element.tomSelect + } + + afterMorph() { + queueMicrotask(() => this.connect()) + } + + get baseSettings() { + return { + create: false, + persist: false, + maxOptions: null, + maxItems: this.dropdownTarget.multiple ? null : 1, + plugins: this.dropdownTarget.multiple ? ['remove_button', 'dropdown_input'] : ['dropdown_input'], + } + } +} diff --git a/lib/generators/rolemodel/tom_select/tom_select_generator.rb b/lib/generators/rolemodel/tom_select/tom_select_generator.rb new file mode 100644 index 00000000..d39ef607 --- /dev/null +++ b/lib/generators/rolemodel/tom_select/tom_select_generator.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module Rolemodel + class TomSelectGenerator < GeneratorBase + source_root File.expand_path('templates', __dir__) + + def add_tom_select_package + say 'Installing Tom Select package', :green + + yarn_command 'add tom-select' + end + + def import_stylesheet + say 'Importing Tom Select stylesheet', :green + + prepend_to_file application_stylesheet_path, <<~CSS + @import 'tom-select/dist/css/tom-select.css'; + CSS + end + + def add_stimulus_controller + say 'Adding Tom Select Stimulus controller', :green + + directory 'app/javascript/controllers' + + rails_command 'stimulus:manifest:update' + end + + def add_simple_form_inputs + return unless simple_form? + + say 'Installing the Tom Select SimpleForm inputs', :green + + directory 'app/inputs' + end + + private + + def simple_form? + File.exist?(File.expand_path('config/initializers/simple_form.rb', destination_root)) + end + end +end diff --git a/spec/generators/rolemodel/core_setup_generator_spec.rb b/spec/generators/rolemodel/core_setup_generator_spec.rb new file mode 100644 index 00000000..3a8fd027 --- /dev/null +++ b/spec/generators/rolemodel/core_setup_generator_spec.rb @@ -0,0 +1,15 @@ +RSpec.describe Rolemodel::CoreSetupGenerator, type: :generator do + let(:invoked_generators) { [] } + + before do + allow_any_instance_of(Rails::Generators::Actions).to receive(:generate) do |_instance, name, *| + invoked_generators << name + end + + run_generators + end + + it 'installs tom_select after simple_form' do + expect(invoked_generators.index('rolemodel:tom_select')).to eq(invoked_generators.index('rolemodel:simple_form') + 1) + end +end diff --git a/spec/generators/rolemodel/tom_select_generator_spec.rb b/spec/generators/rolemodel/tom_select_generator_spec.rb new file mode 100644 index 00000000..d05495fc --- /dev/null +++ b/spec/generators/rolemodel/tom_select_generator_spec.rb @@ -0,0 +1,39 @@ +RSpec.describe Rolemodel::TomSelectGenerator, type: :generator do + it 'adds tom-select to package.json' do + run_generators + + assert_file 'package.json' do |content| + expect(content).to include('"tom-select":') + end + end + + it 'imports the tom-select stylesheet' do + run_generators + + assert_file 'app/assets/stylesheets/application.css' do |content| + expect(content).to include("@import 'tom-select/dist/css/tom-select.css';") + end + end + + it 'registers the stimulus controller' do + run_generators + + assert_file 'app/javascript/controllers/tom_select_controller.js' + assert_file 'app/javascript/controllers/index.js' do |content| + expect(content).to include('application.register("tom-select", TomSelectController)') + end + end + + it 'does not install the SimpleForm inputs when SimpleForm is absent' do + run_generators + + assert_no_file 'app/inputs/tom_select_input.rb' + end + + it 'installs the SimpleForm inputs when SimpleForm is present' do + run_generators generators: [::Rolemodel::SimpleFormGenerator, described_class] + + assert_file 'app/inputs/tom_select_input.rb' + assert_file 'app/inputs/grouped_tom_select_input.rb' + end +end From 362670fc790adfca851e8811d28ac01ed8508a92 Mon Sep 17 00:00:00 2001 From: Andy Cohen Date: Tue, 29 Sep 2026 11:55:50 -0500 Subject: [PATCH 3/6] Adopt tarsco_bolted_tank's tom-select settings The controller binds to the select itself instead of a target, takes a create value from the input's allow_create option, keeps commas in values, clears the search text after a pick, and drops the dropdown_input plugin so the rspec SelectHelper can type into the control. The per-element morph actions stay. Co-Authored-By: Claude Opus 5.5 (1M context) --- lib/generators/rolemodel/tom_select/README.md | 1 + .../app/inputs/grouped_tom_select_input.rb | 8 +++++++- .../templates/app/inputs/tom_select_input.rb | 18 ++++++++---------- .../controllers/tom_select_controller.js | 14 ++++++++------ 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/lib/generators/rolemodel/tom_select/README.md b/lib/generators/rolemodel/tom_select/README.md index 87604404..74698fb8 100644 --- a/lib/generators/rolemodel/tom_select/README.md +++ b/lib/generators/rolemodel/tom_select/README.md @@ -10,5 +10,6 @@ ```slim = f.input :project_manager, as: :tom_select, collection: User.all += f.input :substance, as: :tom_select, collection: Substance.all, allow_create: true = f.input :material, as: :grouped_tom_select, collection: Category.all, group_method: :materials ``` diff --git a/lib/generators/rolemodel/tom_select/templates/app/inputs/grouped_tom_select_input.rb b/lib/generators/rolemodel/tom_select/templates/app/inputs/grouped_tom_select_input.rb index 6b7a12cf..7bc5de71 100644 --- a/lib/generators/rolemodel/tom_select/templates/app/inputs/grouped_tom_select_input.rb +++ b/lib/generators/rolemodel/tom_select/templates/app/inputs/grouped_tom_select_input.rb @@ -2,8 +2,14 @@ class GroupedTomSelectInput < SimpleForm::Inputs::GroupedCollectionSelectInput def input(wrapper_options = nil) - super(merge_wrapper_options(TomSelectInput.stimulus_options, wrapper_options)) + super(merge_wrapper_options(tom_select_options, wrapper_options)) end def input_html_classes = [] + + private + + def tom_select_options + { data: { controller: 'tom-select', action: TomSelectInput::MORPH_ACTIONS } } + end end diff --git a/lib/generators/rolemodel/tom_select/templates/app/inputs/tom_select_input.rb b/lib/generators/rolemodel/tom_select/templates/app/inputs/tom_select_input.rb index 6043849e..88bcc106 100644 --- a/lib/generators/rolemodel/tom_select/templates/app/inputs/tom_select_input.rb +++ b/lib/generators/rolemodel/tom_select/templates/app/inputs/tom_select_input.rb @@ -1,19 +1,17 @@ # frozen_string_literal: true class TomSelectInput < SimpleForm::Inputs::CollectionSelectInput - def self.stimulus_options - { - data: { - controller: 'tom-select', - tom_select_target: 'dropdown', - action: 'turbo:before-morph-element->tom-select#disconnect:self turbo:morph-element->tom-select#afterMorph:self' - } - } - end + MORPH_ACTIONS = 'turbo:before-morph-element->tom-select#disconnect:self turbo:morph-element->tom-select#afterMorph:self' def input(wrapper_options = nil) - super(merge_wrapper_options(self.class.stimulus_options, wrapper_options)) + super(merge_wrapper_options(tom_select_options, wrapper_options)) end def input_html_classes = [] + + private + + def tom_select_options + { data: { controller: 'tom-select', tom_select_create_value: options.delete(:allow_create) || false, action: MORPH_ACTIONS } } + end end diff --git a/lib/generators/rolemodel/tom_select/templates/app/javascript/controllers/tom_select_controller.js b/lib/generators/rolemodel/tom_select/templates/app/javascript/controllers/tom_select_controller.js index b53fda9c..e4fb1090 100644 --- a/lib/generators/rolemodel/tom_select/templates/app/javascript/controllers/tom_select_controller.js +++ b/lib/generators/rolemodel/tom_select/templates/app/javascript/controllers/tom_select_controller.js @@ -2,10 +2,10 @@ import { Controller } from '@hotwired/stimulus' import TomSelect from 'tom-select' export default class extends Controller { - static targets = ['dropdown'] + static values = { create: Boolean } connect() { - this.tomSelect = new TomSelect(this.dropdownTarget, this.baseSettings) + this.tomSelect = new TomSelect(this.element, this.settings) this.element.tomSelect = this.tomSelect } @@ -22,13 +22,15 @@ export default class extends Controller { queueMicrotask(() => this.connect()) } - get baseSettings() { + get settings() { return { - create: false, + create: this.createValue, persist: false, maxOptions: null, - maxItems: this.dropdownTarget.multiple ? null : 1, - plugins: this.dropdownTarget.multiple ? ['remove_button', 'dropdown_input'] : ['dropdown_input'], + delimiter: null, + maxItems: this.element.multiple ? null : 1, + plugins: this.element.multiple ? ['remove_button'] : [], + onItemAdd: () => this.tomSelect.setTextboxValue(''), // clear the input text box when a selection is made } } } From c5cd841efb5fe4bf2c32c8de16dac81e3b997326 Mon Sep 17 00:00:00 2001 From: Andy Cohen Date: Tue, 29 Sep 2026 12:02:04 -0500 Subject: [PATCH 4/6] Run the tom_select generator from rolemodel:all Co-Authored-By: Claude Opus 5.5 (1M context) --- lib/generators/rolemodel/README.md | 1 + lib/generators/rolemodel/all_generator.rb | 1 + spec/generators/rolemodel/all_generator_spec.rb | 1 + 3 files changed, 3 insertions(+) diff --git a/lib/generators/rolemodel/README.md b/lib/generators/rolemodel/README.md index a2651040..12b3fa69 100644 --- a/lib/generators/rolemodel/README.md +++ b/lib/generators/rolemodel/README.md @@ -18,6 +18,7 @@ * [SoftDestroyable](./soft_destroyable) * [Source Map](./source_map) * [Testing](./testing) +* [Tom Select](./tom_select) * [Webpack](./webpack) ## Helpful documentation diff --git a/lib/generators/rolemodel/all_generator.rb b/lib/generators/rolemodel/all_generator.rb index 4b8ae9c0..03041bb0 100644 --- a/lib/generators/rolemodel/all_generator.rb +++ b/lib/generators/rolemodel/all_generator.rb @@ -13,6 +13,7 @@ def run_all_the_generators generate 'rolemodel:optics:all' generate 'rolemodel:testing:all' generate 'rolemodel:simple_form' + generate 'rolemodel:tom_select' generate 'rolemodel:soft_destroyable' generate 'rolemodel:saas:all' generate 'rolemodel:mailers' diff --git a/spec/generators/rolemodel/all_generator_spec.rb b/spec/generators/rolemodel/all_generator_spec.rb index e4cbf4d2..abc2458d 100644 --- a/spec/generators/rolemodel/all_generator_spec.rb +++ b/spec/generators/rolemodel/all_generator_spec.rb @@ -26,6 +26,7 @@ 'rolemodel:optics:all', 'rolemodel:testing:all', 'rolemodel:simple_form', + 'rolemodel:tom_select', 'rolemodel:soft_destroyable', 'rolemodel:saas:all', 'rolemodel:mailers', From e4784249fcf938627561fc220257d4520e58a703 Mon Sep 17 00:00:00 2001 From: Andy Cohen Date: Tue, 29 Sep 2026 12:09:47 -0500 Subject: [PATCH 5/6] Check rolemodel:all against the generators on disk The all generator spec now derives the expected generators from lib/generators/rolemodel, delegating to a directory's all generator when it has one, minus a named exclusion list. That surfaced rolemodel:all never running rolemodel:turbo:all, which core_setup does, so it runs it now and its README lists the Turbo generators in place of a dead Modals link. The core_setup ordering spec goes away. Co-Authored-By: Claude Opus 5.5 (1M context) --- lib/generators/rolemodel/README.md | 6 +- lib/generators/rolemodel/all_generator.rb | 1 + .../rolemodel/all_generator_spec.rb | 57 ++++++------------- .../rolemodel/core_setup_generator_spec.rb | 15 ----- 4 files changed, 24 insertions(+), 55 deletions(-) delete mode 100644 spec/generators/rolemodel/core_setup_generator_spec.rb diff --git a/lib/generators/rolemodel/README.md b/lib/generators/rolemodel/README.md index 12b3fa69..e776c1b0 100644 --- a/lib/generators/rolemodel/README.md +++ b/lib/generators/rolemodel/README.md @@ -9,7 +9,6 @@ * [Heroku](./heroku) * [Linters](./linters) * [Mailers](./mailers) -* [Modals](./modals) * [Optics](./optics) * [README](./readme) * [SaaS](./saas) @@ -19,6 +18,11 @@ * [Source Map](./source_map) * [Testing](./testing) * [Tom Select](./tom_select) +* [Turbo](./turbo/all) + * [Ready](./turbo/ready) + * [Confirm](./turbo/confirm) + * [Modals](./turbo/modals) + * [Form](./turbo/form) * [Webpack](./webpack) ## Helpful documentation diff --git a/lib/generators/rolemodel/all_generator.rb b/lib/generators/rolemodel/all_generator.rb index 03041bb0..d7eb6e36 100644 --- a/lib/generators/rolemodel/all_generator.rb +++ b/lib/generators/rolemodel/all_generator.rb @@ -12,6 +12,7 @@ def run_all_the_generators generate 'rolemodel:slim' generate 'rolemodel:optics:all' generate 'rolemodel:testing:all' + generate 'rolemodel:turbo:all' generate 'rolemodel:simple_form' generate 'rolemodel:tom_select' generate 'rolemodel:soft_destroyable' diff --git a/spec/generators/rolemodel/all_generator_spec.rb b/spec/generators/rolemodel/all_generator_spec.rb index abc2458d..e58c4e22 100644 --- a/spec/generators/rolemodel/all_generator_spec.rb +++ b/spec/generators/rolemodel/all_generator_spec.rb @@ -1,7 +1,22 @@ RSpec.describe Rolemodel::AllGenerator, type: :generator do # Each sub-generator is exercised by its own spec, so here we only verify - # which generators get delegated to (and in what order). + # which generators get delegated to. let(:invoked_generators) { [] } + let(:generators_root) { File.expand_path('../../../lib/generators/rolemodel', __dir__) } + let(:excluded_generators) do + { + 'rolemodel:core_setup' => 'a subset of rolemodel:all', + 'rolemodel:tailored_select' => 'not production ready' + } + end + + # A directory with its own all generator is delegated to as a group. + def generators_on_disk + Dir.children(generators_root).select { File.directory?(File.join(generators_root, it)) }.map do |dir| + grouped = Dir.exist?(File.join(generators_root, dir, 'all')) || File.exist?(File.join(generators_root, dir, 'all_generator.rb')) + grouped ? "rolemodel:#{dir}:all" : "rolemodel:#{dir}" + end + end before do # Stub on the Actions module rather than the generator class: stubbing the @@ -14,43 +29,7 @@ run_generators end - it 'delegates to every rolemodel generator in order' do - expect(invoked_generators).to eq([ - 'rolemodel:github', - 'rolemodel:heroku', - 'rolemodel:readme', - 'rolemodel:webpack', - 'rolemodel:sentry', - 'rolemodel:react', - 'rolemodel:slim', - 'rolemodel:optics:all', - 'rolemodel:testing:all', - 'rolemodel:simple_form', - 'rolemodel:tom_select', - 'rolemodel:soft_destroyable', - 'rolemodel:saas:all', - 'rolemodel:mailers', - 'rolemodel:linters:all', - 'rolemodel:ui_components:all', - 'rolemodel:source_map', - 'rolemodel:good_job', - 'rolemodel:kaminari', - 'rolemodel:editors', - 'rolemodel:lograge' - ]) - end - - it 'only delegates to generators that exist' do - unknown = invoked_generators.reject { |name| Rails::Generators.find_by_namespace(name) } - - expect(unknown).to eq([]) - end - - it 'does not delegate to tailored_select, which is not production ready' do - expect(invoked_generators).not_to include('rolemodel:tailored_select') - end - - it 'does not delegate to a semaphore generator' do - expect(invoked_generators).not_to include(a_string_matching(/semaphore/)) + it 'delegates to every generator on disk that is not excluded' do + expect(invoked_generators).to match_array(generators_on_disk - excluded_generators.keys) end end diff --git a/spec/generators/rolemodel/core_setup_generator_spec.rb b/spec/generators/rolemodel/core_setup_generator_spec.rb deleted file mode 100644 index 3a8fd027..00000000 --- a/spec/generators/rolemodel/core_setup_generator_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -RSpec.describe Rolemodel::CoreSetupGenerator, type: :generator do - let(:invoked_generators) { [] } - - before do - allow_any_instance_of(Rails::Generators::Actions).to receive(:generate) do |_instance, name, *| - invoked_generators << name - end - - run_generators - end - - it 'installs tom_select after simple_form' do - expect(invoked_generators.index('rolemodel:tom_select')).to eq(invoked_generators.index('rolemodel:simple_form') + 1) - end -end From 86046e22b93434fa676a5be11b04eef372ef541a Mon Sep 17 00:00:00 2001 From: Andy Cohen Date: Tue, 29 Sep 2026 12:11:50 -0500 Subject: [PATCH 6/6] List every generator rolemodel:all runs in its README Co-Authored-By: Claude Opus 5.5 (1M context) --- lib/generators/rolemodel/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/generators/rolemodel/README.md b/lib/generators/rolemodel/README.md index e776c1b0..68b371be 100644 --- a/lib/generators/rolemodel/README.md +++ b/lib/generators/rolemodel/README.md @@ -4,14 +4,19 @@ ## What you get +* [Editors](./editors) * [Github](./github) * [GoodJob](./good_job) * [Heroku](./heroku) +* [Kaminari](./kaminari) * [Linters](./linters) +* [Lograge](./lograge) * [Mailers](./mailers) * [Optics](./optics) +* [React](./react) * [README](./readme) * [SaaS](./saas) +* [Sentry](./sentry) * [SimpleForm](./simple_form) * [Slim](./slim) * [SoftDestroyable](./soft_destroyable) @@ -23,6 +28,7 @@ * [Confirm](./turbo/confirm) * [Modals](./turbo/modals) * [Form](./turbo/form) +* [UI Components](./ui_components) * [Webpack](./webpack) ## Helpful documentation