rolemodel-rails 0.26.0 → 1.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 (84) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -4
  3. data/lib/generators/rolemodel/all_generator.rb +2 -1
  4. data/lib/generators/rolemodel/editors/editors_generator.rb +1 -1
  5. data/lib/generators/rolemodel/github/README.md +14 -17
  6. data/lib/generators/rolemodel/github/USAGE +4 -1
  7. data/lib/generators/rolemodel/github/github_generator.rb +24 -18
  8. data/lib/generators/rolemodel/github/templates/CODEOWNERS +8 -0
  9. data/lib/generators/rolemodel/github/templates/dependabot.yml +87 -0
  10. data/lib/generators/rolemodel/github/templates/instructions +1 -0
  11. data/lib/generators/rolemodel/github/templates/pull_request_template.md +18 -0
  12. data/lib/generators/rolemodel/github/templates/workflows/ci.yml.tt +81 -0
  13. data/lib/generators/rolemodel/good_job/good_job_generator.rb +1 -1
  14. data/lib/generators/rolemodel/heroku/heroku_generator.rb +1 -1
  15. data/lib/generators/rolemodel/kaminari/kaminari_generator.rb +1 -1
  16. data/lib/generators/rolemodel/linters/all_generator.rb +1 -1
  17. data/lib/generators/rolemodel/linters/eslint/eslint_generator.rb +1 -1
  18. data/lib/generators/rolemodel/linters/rubocop/rubocop_generator.rb +1 -1
  19. data/lib/generators/rolemodel/lograge/lograge_generator.rb +1 -1
  20. data/lib/generators/rolemodel/mailers/mailers_generator.rb +1 -1
  21. data/lib/generators/rolemodel/mcp/README.md +13 -0
  22. data/lib/generators/rolemodel/mcp/USAGE +8 -0
  23. data/lib/generators/rolemodel/mcp/mcp_generator.rb +110 -0
  24. data/lib/generators/rolemodel/mcp/templates/app/assets/stylesheets/components/doorkeeper.css +140 -0
  25. data/lib/generators/rolemodel/mcp/templates/app/controllers/doorkeeper/base_controller.rb +7 -0
  26. data/lib/generators/rolemodel/mcp/templates/app/controllers/mcp_controller.rb.tt +91 -0
  27. data/lib/generators/rolemodel/mcp/templates/app/controllers/oauth_registrations_controller.rb +46 -0
  28. data/lib/generators/rolemodel/mcp/templates/app/controllers/well_known_controller.rb +39 -0
  29. data/lib/generators/rolemodel/mcp/templates/app/mcp/prompts/sample.rb +36 -0
  30. data/lib/generators/rolemodel/mcp/templates/app/mcp/resources/controller.rb +57 -0
  31. data/lib/generators/rolemodel/mcp/templates/app/mcp/resources/docs/SAMPLE_DOC.md +4 -0
  32. data/lib/generators/rolemodel/mcp/templates/app/mcp/resources/docs_controller.rb +46 -0
  33. data/lib/generators/rolemodel/mcp/templates/app/mcp/tools/sample.rb +42 -0
  34. data/lib/generators/rolemodel/mcp/templates/app/views/doorkeeper/authorizations/error.html.slim.tt +13 -0
  35. data/lib/generators/rolemodel/mcp/templates/app/views/doorkeeper/authorizations/new.html.slim.tt +41 -0
  36. data/lib/generators/rolemodel/mcp/templates/app/views/layouts/doorkeeper.html.slim +7 -0
  37. data/lib/generators/rolemodel/mcp/templates/config/initializers/doorkeeper.rb +537 -0
  38. data/lib/generators/rolemodel/mcp/templates/spec/mcp/prompts/sample_spec.rb +15 -0
  39. data/lib/generators/rolemodel/mcp/templates/spec/mcp/resources/controller_spec.rb +16 -0
  40. data/lib/generators/rolemodel/mcp/templates/spec/mcp/resources/docs_controller_spec.rb +55 -0
  41. data/lib/generators/rolemodel/mcp/templates/spec/mcp/tools/sample_spec.rb +15 -0
  42. data/lib/generators/rolemodel/mcp/templates/spec/requests/mcp_controller_spec.rb +84 -0
  43. data/lib/generators/rolemodel/mcp/templates/spec/requests/oauth_registrations_controller_spec.rb +62 -0
  44. data/lib/generators/rolemodel/mcp/templates/spec/requests/well_known_controller_spec.rb +30 -0
  45. data/lib/generators/rolemodel/optics/all_generator.rb +1 -1
  46. data/lib/generators/rolemodel/optics/base/base_generator.rb +2 -2
  47. data/lib/generators/rolemodel/optics/icons/icons_generator.rb +1 -1
  48. data/lib/generators/rolemodel/react/react_generator.rb +1 -1
  49. data/lib/generators/rolemodel/readme/readme_generator.rb +1 -1
  50. data/lib/generators/rolemodel/saas/all_generator.rb +1 -1
  51. data/lib/generators/rolemodel/saas/devise/devise_generator.rb +1 -1
  52. data/lib/generators/rolemodel/semaphore/semaphore_generator.rb +1 -1
  53. data/lib/generators/rolemodel/simple_form/simple_form_generator.rb +1 -1
  54. data/lib/generators/rolemodel/slim/slim_generator.rb +1 -1
  55. data/lib/generators/rolemodel/soft_destroyable/soft_destroyable_generator.rb +1 -1
  56. data/lib/generators/rolemodel/source_map/source_map_generator.rb +1 -1
  57. data/lib/generators/rolemodel/tailored_select/tailored_select_generator.rb +1 -1
  58. data/lib/generators/rolemodel/testing/all_generator.rb +1 -1
  59. data/lib/generators/rolemodel/testing/factory_bot/factory_bot_generator.rb +1 -1
  60. data/lib/generators/rolemodel/testing/jasmine_playwright/jasmine_playwright_generator.rb +1 -1
  61. data/lib/generators/rolemodel/testing/parallel_tests/parallel_tests_generator.rb +1 -1
  62. data/lib/generators/rolemodel/testing/rspec/rspec_generator.rb +1 -2
  63. data/lib/generators/rolemodel/testing/rspec/templates/rails_helper.rb +4 -0
  64. data/lib/generators/rolemodel/testing/rspec/templates/support/capybara_drivers.rb +0 -2
  65. data/lib/generators/rolemodel/testing/rspec/templates/support/helpers/capybara_helper.rb +0 -46
  66. data/lib/generators/rolemodel/testing/rspec/templates/support/helpers/playwright_helper.rb +0 -60
  67. data/lib/generators/rolemodel/testing/test_prof/test_prof_generator.rb +1 -1
  68. data/lib/generators/rolemodel/testing/vitest/vitest_generator.rb +1 -1
  69. data/lib/generators/rolemodel/ui_components/all_generator.rb +1 -1
  70. data/lib/generators/rolemodel/ui_components/flash/flash_generator.rb +1 -1
  71. data/lib/generators/rolemodel/ui_components/modals/modals_generator.rb +1 -1
  72. data/lib/generators/rolemodel/ui_components/navbar/navbar_generator.rb +1 -1
  73. data/lib/generators/rolemodel/webpack/webpack_generator.rb +1 -1
  74. data/lib/rolemodel/engine.rb +3 -1
  75. data/lib/rolemodel/generator_base.rb +17 -0
  76. data/lib/rolemodel/version.rb +1 -1
  77. data/lib/rolemodel-rails.rb +2 -0
  78. metadata +32 -7
  79. data/lib/generators/rolemodel/base_generator.rb +0 -14
  80. data/lib/generators/templates/generator/%filename%.rb.tt +0 -11
  81. data/lib/generators/templates/generator/README.md.tt +0 -11
  82. data/lib/generators/templates/generator/USAGE.tt +0 -5
  83. data/lib/generators/templates/generator_spec/%filename%_spec.rb.tt +0 -5
  84. /data/lib/{generators/rolemodel → rolemodel}/replace_content_helper.rb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '009bb14699c3ecc612283b81294506fdacc64e881d386d597c6b3e5302d708dd'
4
- data.tar.gz: 436e21097154c27592f5f9c89557050ae64ecd6be9c4f6ee767a1aa5d5b37ce9
3
+ metadata.gz: d3e11cf41b7d9e5afb68a8eaca61a30785b10dcb9032fc327a52f40ea8271a2e
4
+ data.tar.gz: 4b4388ba6e3b2608135be47000bc9ba655b32bd4936e096d2e3ba8cafe4904c3
5
5
  SHA512:
6
- metadata.gz: 83ec891bfb8720a836cd4145b2395c5db5b79e11ad2711da22be127d70da963b4cb254217aa530e279b20b68a3f47e148aea0da2643815ce3dbd753f9d0c0272
7
- data.tar.gz: be94ed5589774d6f39f26741c01353d28bbcd650b21fb5e05aa94ed763b353a9caeff94eb9639d57cd0039cfe1dd75f719fb593b9d99905e25eaecc8fd8b7e8b
6
+ metadata.gz: 173f38c6b5f5f0101a143aaf8a5301afd7a69295d68e1c8eb54a5bd2cf06b57254f658e312a19a3a2605f6920ddab05f6f8941a0797ce7400e83c2e3ff13ac38
7
+ data.tar.gz: 77b6be040efd20cd738c14c44c92c57ac84241a75685cc157bfa86ddc3b6b7b6675eec3b2ad8a3b8c6dfb83c7e568aca7420746b6b81ef7d1172d6392c490c47
data/README.md CHANGED
@@ -28,9 +28,7 @@ rails db:create
28
28
  Add this line to your application's Gemfile:
29
29
 
30
30
  ```ruby
31
- group :development do
32
- gem 'rolemodel-rails', github: 'RoleModel/rolemodel_rails'
33
- end
31
+ gem 'rolemodel-rails', group: :development
34
32
  ```
35
33
 
36
34
  And then execute:
@@ -115,7 +113,7 @@ e.g.
115
113
  bin/new_generator testing/fantasitic_specs 'A Fantastic Testing Framework'
116
114
  ```
117
115
 
118
- We use the embeded Rails apps (`example_rails*`) to test generators against. They reference the rolemodel-rails gem by local path,
116
+ We use the embeded Rails apps (`example_rails_current` & `example_rails_legacy`) to test generators against. They reference the rolemodel-rails gem by local path,
119
117
  so you can navigate into one of them and run your generator for immediate feedback while developing.
120
118
 
121
119
  > [!IMPORTANT]
@@ -146,6 +144,19 @@ RSpec.describe Rolemodel::Testing::JasminePlaywrightGenerator, type: :generator
146
144
  end
147
145
  ```
148
146
 
147
+ If the generator you're testing depends on being run after another generator, you should run that one first.
148
+
149
+ e.g.
150
+
151
+ ```ruby
152
+ RSpec.describe Rolemodel::MyGenerator, type: :generator do
153
+ before do
154
+ run_generator_against_test_app(generator: ::Rolemodel::PrereqGenerator)
155
+ run_generator_against_test_app
156
+ end
157
+ end
158
+ ```
159
+
149
160
  Additional information about testing generators and the available assertions & matchers can be found at the following resources.
150
161
 
151
162
  * [Rails Guide](https://guides.rubyonrails.org/generators.html#testing-generators)
@@ -1,5 +1,5 @@
1
1
  module Rolemodel
2
- class AllGenerator < BaseGenerator
2
+ class AllGenerator < GeneratorBase
3
3
  source_root File.expand_path('templates', __dir__)
4
4
 
5
5
  def run_all_the_generators
@@ -24,6 +24,7 @@ module Rolemodel
24
24
  generate 'rolemodel:editors'
25
25
  # generate 'rolemodel:tailored_select' # Not production ready
26
26
  generate 'rolemodel:lograge'
27
+ generate 'rolemodel:mcp'
27
28
  end
28
29
  end
29
30
  end
@@ -4,7 +4,7 @@ require_relative 'vscode_helpers'
4
4
 
5
5
  module Rolemodel
6
6
  # Add standard editorconfig and any extensions to enable it
7
- class EditorsGenerator < BaseGenerator
7
+ class EditorsGenerator < GeneratorBase
8
8
  include Rolemodel::VSCodeHelpers
9
9
 
10
10
  # This is bringing in the root from this gem, so we only modify
@@ -1,23 +1,20 @@
1
1
  # Github Generator
2
2
 
3
3
  ## Prerequisites
4
- You will need the parallel_tests generator to run the CI tests.
5
4
 
6
- ## What you get
7
-
8
- ### ci.yml
9
- A sensible default `ci.yml` to get you started with Github Actions. This will run linters, model tests, and system tests.
10
-
11
- Along with the `ci.yml`, your `database.yml` will be modified to be able to be run in GHA.
12
-
13
- ### Pull Request Template
5
+ It doesn't need to be run first, but the parallel_tests generator must be run in order for the CI workflow to run successfully on GitHub.
14
6
 
15
- When you open a Pull Request in Github it will use the Markdown file as a [template](./templates/pull_request_template.md) for the content of the PR.
16
-
17
- Helpful for reminding collaborators to add specific details to the PR.
18
-
19
- ### Copilot Instructions
7
+ ## What you get
20
8
 
21
- Installed into `.github/instructions`, these are context-specific instructions for Copilot to help it give more accurate
22
- and relevant results. These are a good starting point but they should be tweaked for your project's frameworks and
23
- standards.
9
+ - CI workflow
10
+ - A sensible default `ci.yml` to get you started with Github Actions. This will run linters, model tests, and system tests.
11
+ - Along with the `ci.yml`, your `database.yml` will be modified to be able to be run in GHA.
12
+ - Pull Request Template
13
+ - When you open a Pull Request in Github it will use the Markdown file as a [template](./templates/pull_request_template.md) for the content of the PR.
14
+ - Helpful for reminding collaborators to add specific details to the PR.
15
+ - Copilot Instructions
16
+ - Installed into `.github/instructions`, these are context-specific instructions for Copilot to help it give more accurate
17
+ and relevant results. These are a good starting point but they should be tweaked for your project's frameworks and
18
+ standards.
19
+ - Dependabot Configuration
20
+ - defines a set of rules that dependabot will use to keep your applications dependencies up-to-date on a weekly basis.
@@ -5,5 +5,8 @@ Example:
5
5
  rails generate rolemodel:github
6
6
 
7
7
  This will create:
8
- .github/pull_request_template.md
8
+ .github/instructions/
9
9
  .github/workflows/ci.yml
10
+ .github/pull_request_template.md
11
+ .github/dependabot.yml
12
+ .github/CODEOWNERS
@@ -1,31 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rolemodel
4
- class GithubGenerator < BaseGenerator
5
- # Source root is the project-level .github directory
6
- # This allows us to use the same templates for both the generated app and this gem
7
- source_root File.expand_path('.github')
4
+ class GithubGenerator < GeneratorBase
5
+ GITHUB_ACTIONS_REPO = 'https://github.com/RoleModel/actions.git'
6
+ # Files which are both used by the gem source and copied to the target app without modification
7
+ # are placed in the `.github` folder at the top level of this repository. This folder is then
8
+ # symlinked to the `templates` folder relative to this generator so they can still be copied over.
9
+ # Any files which are significantly different or not used by the gem source are just in `templates`.
10
+ source_root File.expand_path('templates', __dir__)
8
11
 
9
- def install_pull_request_template
10
- template 'pull_request_template.md', '.github/pull_request_template.md'
12
+ class_option :playwright, type: :boolean, default: true,
13
+ desc: 'Request Playwright Setup in CI workflow for system tests?'
14
+
15
+ def set_rm_actions_version
16
+ tags = `git ls-remote --tags #{GITHUB_ACTIONS_REPO}` rescue 'refs/tags/v3'
17
+ @rm_actions_version = tags.scan(%r{refs/tags/v(\d+)\s*$}).flatten.max_by(&:to_i)
11
18
  end
12
19
 
13
- def remove_rolemodel_rails_version_check
14
- gsub_file '.github/pull_request_template.md',
15
- "* [ ] Run `bin/bump_version` or `bin/bump_version --patch`\n",
16
- ''
20
+ def set_webdriver
21
+ @webdriver = options.playwright? ? 'playwright' : 'selenium'
17
22
  end
18
23
 
19
- def install_copilot_instructions
20
- copy_file 'instructions/css.instructions.md', '.github/instructions/css.instructions.md'
21
- copy_file 'instructions/js.instructions.md', '.github/instructions/js.instructions.md'
22
- copy_file 'instructions/project.instructions.md', '.github/instructions/project.instructions.md'
23
- copy_file 'instructions/ruby.instructions.md', '.github/instructions/ruby.instructions.md'
24
- copy_file 'instructions/slim.instructions.md', '.github/instructions/slim.instructions.md'
24
+ def install_github_config
25
+ directory 'instructions', '.github/instructions'
26
+ directory 'workflows', '.github/workflows', force: true
27
+ template 'pull_request_template.md', '.github/pull_request_template.md'
25
28
  end
26
29
 
27
- def install_ci_yml
28
- copy_file 'templates/ci.yml', '.github/workflows/ci.yml'
30
+ def install_dependabot_and_codeowners
31
+ copy_file 'dependabot.yml', '.github/dependabot.yml', force: true
32
+ copy_file 'CODEOWNERS', '.github/CODEOWNERS'
33
+
34
+ say '👉 See CODEOWNERS file for important instructions.', %i[bold red on_blue]
29
35
  end
30
36
 
31
37
  def update_database_yml_for_ci
@@ -0,0 +1,8 @@
1
+ # This file is used by Dependabot (and more broadly GitHub) to determine who needs to review
2
+ # pull requests which contain changes to specific files. Specifically, the setup below allows
3
+ # for the dependabot PRs to automatically assign (and notify) the Craftsman and Support Dev.
4
+
5
+ # Dependabot / Dependency reviewers:
6
+ # TODO: Update and uncomment the following lines.
7
+ # yarn.lock @craftsman @supportdev
8
+ # Gemfile.lock @craftsman @supportdev
@@ -0,0 +1,87 @@
1
+ version: 2
2
+ registries:
3
+ ruby-github:
4
+ type: rubygems-server
5
+ url: https://rubygems.pkg.github.com/RoleModel
6
+ token: ${{ secrets.ROLEMODEL_PACKAGE_REPO_READ_TOKEN }}
7
+
8
+ updates:
9
+ - package-ecosystem: bundler
10
+ insecure-external-code-execution: allow
11
+ registries:
12
+ - ruby-github
13
+ directory: /
14
+ schedule:
15
+ interval: weekly
16
+ day: monday
17
+ # Ignore specific dependencies or update types which may cause issues. For example:
18
+ # ignore:
19
+ # - dependency-name: 'some-gem'
20
+ # - update-types: ['version-update:semver-major']
21
+ groups:
22
+ production-security:
23
+ dependency-type: production
24
+ applies-to: security-updates
25
+ production-major-updates:
26
+ dependency-type: production
27
+ applies-to: version-updates
28
+ update-types:
29
+ - major
30
+ production-minor-updates:
31
+ dependency-type: production
32
+ applies-to: version-updates
33
+ update-types:
34
+ - minor
35
+ - patch
36
+ development-security:
37
+ dependency-type: development
38
+ applies-to: security-updates
39
+ development-major-updates:
40
+ dependency-type: development
41
+ applies-to: version-updates
42
+ update-types:
43
+ - major
44
+ development-minor-updates:
45
+ dependency-type: development
46
+ applies-to: version-updates
47
+ update-types:
48
+ - minor
49
+ - patch
50
+ - package-ecosystem: npm
51
+ directory: /
52
+ schedule:
53
+ interval: weekly
54
+ day: monday
55
+ # Ignore specific dependencies or update types which may cause issues. For example:
56
+ # ignore:
57
+ # - dependency-name: 'some-package'
58
+ # - update-types: ['version-update:semver-major']
59
+ groups:
60
+ production-security:
61
+ dependency-type: production
62
+ applies-to: security-updates
63
+ production-major-updates:
64
+ dependency-type: production
65
+ applies-to: version-updates
66
+ update-types:
67
+ - major
68
+ production-minor-updates:
69
+ dependency-type: production
70
+ applies-to: version-updates
71
+ update-types:
72
+ - minor
73
+ - patch
74
+ development-security:
75
+ dependency-type: development
76
+ applies-to: security-updates
77
+ development-major-updates:
78
+ dependency-type: development
79
+ applies-to: version-updates
80
+ update-types:
81
+ - major
82
+ development-minor-updates:
83
+ dependency-type: development
84
+ applies-to: version-updates
85
+ update-types:
86
+ - minor
87
+ - patch
@@ -0,0 +1 @@
1
+ ../../../../../.github/instructions
@@ -0,0 +1,18 @@
1
+ ## Why?
2
+
3
+ Why were the changes needed? What issues were the changes addressing?
4
+ (Note: some changes may seem unrelated to the ticket, this is a great place to explain further.)
5
+
6
+ ## What Changed
7
+
8
+ What changed in this PR?
9
+
10
+ * [ ] Change 1
11
+
12
+ ## Pre-merge checklist
13
+
14
+ * [ ] Update relevant READMEs
15
+
16
+ ## Screenshots
17
+
18
+ If any UI changes need to be shown off, please add screenshots here.
@@ -0,0 +1,81 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ concurrency:
8
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
9
+ cancel-in-progress: true
10
+
11
+ env:
12
+ CI: true
13
+ RAILS_ENV: test
14
+ POSTGRES_USER: postgres
15
+ POSTGRES_PASSWORD: password
16
+
17
+ jobs:
18
+ project-stats:
19
+ name: Project Stats
20
+ runs-on: blacksmith-4vcpu-ubuntu-2404
21
+ timeout-minutes: 3
22
+ steps:
23
+ - uses: actions/checkout@v6
24
+ - uses: RoleModel/actions/project-stats@v<%= @rm_actions_version %>
25
+
26
+ compile-assets:
27
+ name: Compile Assets
28
+ runs-on: blacksmith-8vcpu-ubuntu-2404
29
+ timeout-minutes: 5
30
+ steps:
31
+ - uses: actions/checkout@v6
32
+ - uses: RoleModel/actions/compile-assets@v<%= @rm_actions_version %>
33
+ id: check-asset-cache
34
+
35
+ non-system-test:
36
+ name: Linting & Ruby Non-System Tests
37
+ runs-on: blacksmith-4vcpu-ubuntu-2404
38
+ timeout-minutes: 5
39
+ services:
40
+ postgres:
41
+ image: postgres:17
42
+ ports: [ "5432:5432" ]
43
+ env:
44
+ POSTGRES_USER: postgres
45
+ POSTGRES_PASSWORD: password
46
+
47
+ steps:
48
+ - uses: actions/checkout@v6
49
+ - uses: ruby/setup-ruby@v1
50
+ with: { bundler-cache: true }
51
+ - run: bin/bundler-audit
52
+ - run: bin/brakeman --quiet --no-pager --exit-on-warn --exit-on-error
53
+ - run: bundle exec rubocop --format github
54
+ - uses: RoleModel/actions/linting-and-non-system-tests@v<%= @rm_actions_version %>
55
+ with:
56
+ needs-compiled-assets: false
57
+
58
+ system-test:
59
+ name: Ruby System Tests
60
+ runs-on: blacksmith-8vcpu-ubuntu-2404
61
+ timeout-minutes: 15
62
+ needs: compile-assets
63
+ services:
64
+ postgres:
65
+ image: postgres:17
66
+ ports: [ "5432:5432" ]
67
+ env:
68
+ POSTGRES_USER: postgres
69
+ POSTGRES_PASSWORD: password
70
+
71
+ steps:
72
+ - uses: actions/checkout@v6
73
+ # Uncomment the following if your app require VIPS for processing ActiveStorage variant images in system tests.
74
+ # - name: Setup vips
75
+ # run: |
76
+ # sudo apt-get update
77
+ # sudo apt-get install -y libvips
78
+ - uses: RoleModel/actions/system-tests@v<%= @rm_actions_version %>
79
+ with:
80
+ web-driver: <%= @webdriver %>
81
+ # failure-screenshot-dir: tmp/screenshots
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rolemodel
4
- class GoodJobGenerator < BaseGenerator
4
+ class GoodJobGenerator < GeneratorBase
5
5
  source_root File.expand_path('templates', __dir__)
6
6
 
7
7
  def install_good_job
@@ -1,5 +1,5 @@
1
1
  module Rolemodel
2
- class HerokuGenerator < BaseGenerator
2
+ class HerokuGenerator < GeneratorBase
3
3
  source_root File.expand_path('templates', __dir__)
4
4
 
5
5
  def install_app_json
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rolemodel
4
- class KaminariGenerator < BaseGenerator
4
+ class KaminariGenerator < GeneratorBase
5
5
  source_root File.expand_path('templates', __dir__)
6
6
 
7
7
  def install_kaminari
@@ -1,6 +1,6 @@
1
1
  module Rolemodel
2
2
  module Linters
3
- class AllGenerator < BaseGenerator
3
+ class AllGenerator < GeneratorBase
4
4
  source_root File.expand_path('templates', __dir__)
5
5
 
6
6
  def run_all_the_generators
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Rolemodel
4
4
  module Linters
5
- class EslintGenerator < BaseGenerator
5
+ class EslintGenerator < GeneratorBase
6
6
  include ReplaceContentHelper
7
7
  source_root File.expand_path('templates', __dir__)
8
8
 
@@ -3,7 +3,7 @@
3
3
  module Rolemodel
4
4
  module Linters
5
5
  # Install the standard rubocop and a custom cop
6
- class RubocopGenerator < BaseGenerator
6
+ class RubocopGenerator < GeneratorBase
7
7
  source_root File.expand_path('templates', __dir__)
8
8
 
9
9
  def install_rubocop
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rolemodel
4
- class LogrageGenerator < BaseGenerator
4
+ class LogrageGenerator < GeneratorBase
5
5
  source_root File.expand_path('templates', __dir__)
6
6
 
7
7
  def install_lograge
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rolemodel
4
- class MailersGenerator < BaseGenerator
4
+ class MailersGenerator < GeneratorBase
5
5
  source_root File.expand_path('templates', __dir__)
6
6
 
7
7
  def install_premailer_rails
@@ -0,0 +1,13 @@
1
+ # MCP Generator
2
+
3
+ Install boilerplate for your very own MCP server.
4
+
5
+ ## What you get
6
+
7
+ ### Doorkeeper
8
+
9
+ OAuth 2.1-enabled flow with dynamic application registration.
10
+
11
+ ### MCP
12
+
13
+ A basic MCP controller that you can build on to serve tools, resources, and prompts.
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Sets up RoleModel MCP support and any required application wiring for the MCP endpoint.
3
+
4
+ Example:
5
+ rails generate rolemodel:mcp
6
+
7
+ This generator adds the files and route updates needed to enable RoleModel MCP
8
+ in your Rails application.
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rolemodel
4
+ class McpGenerator < GeneratorBase
5
+ source_root File.expand_path('templates', __dir__)
6
+
7
+ def update_inflections
8
+ inflections_path = File.join(destination_root, 'config/initializers/inflections.rb')
9
+ block_start = "\nActiveSupport::Inflector.inflections(:en) do |inflect|\n"
10
+
11
+ return if File.read(inflections_path).include?("inflect.acronym 'MCP'")
12
+
13
+ if File.read(inflections_path).include?(block_start)
14
+ inject_into_file inflections_path, " inflect.acronym 'MCP'\n", after: block_start
15
+ else
16
+ append_to_file inflections_path, <<~RUBY
17
+
18
+ ActiveSupport::Inflector.inflections(:en) do |inflect|
19
+ inflect.acronym 'MCP'
20
+ end
21
+ RUBY
22
+ end
23
+ end
24
+
25
+ def install_mcp
26
+ bundle_command 'add mcp'
27
+ template 'app/controllers/mcp_controller.rb'
28
+ copy_file 'spec/requests/mcp_controller_spec.rb'
29
+
30
+ route <<~RUBY
31
+ match '/mcp', to: 'mcp#handle', via: %i[get post delete]
32
+ RUBY
33
+ end
34
+
35
+ def add_sample_mcp_resource
36
+ copy_file 'app/mcp/resources/controller.rb'
37
+ copy_file 'spec/mcp/resources/controller_spec.rb'
38
+
39
+ copy_file 'app/mcp/resources/docs/SAMPLE_DOC.md'
40
+ copy_file 'app/mcp/resources/docs_controller.rb'
41
+ copy_file 'spec/mcp/resources/docs_controller_spec.rb'
42
+ end
43
+
44
+ def add_sample_mcp_prompt
45
+ copy_file 'app/mcp/prompts/sample.rb'
46
+ copy_file 'spec/mcp/prompts/sample_spec.rb'
47
+ end
48
+
49
+ def add_sample_mcp_tool
50
+ copy_file 'app/mcp/tools/sample.rb'
51
+ copy_file 'spec/mcp/tools/sample_spec.rb'
52
+ end
53
+
54
+ def install_doorkeeper
55
+ bundle_command 'add doorkeeper'
56
+ run_bundle
57
+ generate 'doorkeeper:install'
58
+ end
59
+
60
+ def configure_doorkeeper
61
+ copy_file 'config/initializers/doorkeeper.rb', force: true
62
+ copy_file 'app/controllers/doorkeeper/base_controller.rb'
63
+
64
+ copy_file 'app/views/layouts/doorkeeper.html.slim'
65
+ template 'app/views/doorkeeper/authorizations/new.html.slim'
66
+ template 'app/views/doorkeeper/authorizations/error.html.slim'
67
+
68
+ copy_file 'app/assets/stylesheets/components/doorkeeper.css'
69
+
70
+ route 'use_doorkeeper'
71
+ end
72
+
73
+ def apply_doorkeeper_css
74
+ css_manifest = if File.exist?(File.join(destination_root, 'app/assets/stylesheets/application.scss'))
75
+ 'app/assets/stylesheets/application.scss'
76
+ else
77
+ 'app/assets/stylesheets/application.css'
78
+ end
79
+
80
+ return if File.read(File.join(destination_root, css_manifest)).include?("@import 'components/doorkeeper.css';")
81
+
82
+ append_to_file css_manifest, <<~CSS
83
+ @import 'components/doorkeeper.css';
84
+ CSS
85
+ end
86
+
87
+ def add_oauth_dynamic_registrations
88
+ copy_file 'app/controllers/oauth_registrations_controller.rb'
89
+ copy_file 'spec/requests/oauth_registrations_controller_spec.rb'
90
+ route <<~RUBY
91
+ post '/oauth/register', to: 'oauth_registrations#create'
92
+ RUBY
93
+ end
94
+
95
+ def add_well_known_route
96
+ copy_file 'app/controllers/well_known_controller.rb'
97
+ copy_file 'spec/requests/well_known_controller_spec.rb'
98
+ route <<~RUBY
99
+ get '/.well-known/oauth-protected-resource', to: 'well_known#oauth_protected_resource'
100
+ get '/.well-known/oauth-authorization-server', to: 'well_known#oauth_authorization_server'
101
+ RUBY
102
+ end
103
+
104
+ private
105
+
106
+ def application_name
107
+ Rails.application.name
108
+ end
109
+ end
110
+ end