suspenders 20230113.0 → 20240516.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +83 -176
  3. data/Rakefile +13 -0
  4. data/lib/generators/suspenders/accessibility_generator.rb +24 -0
  5. data/lib/generators/suspenders/advisories_generator.rb +32 -0
  6. data/lib/generators/suspenders/ci_generator.rb +57 -0
  7. data/lib/generators/suspenders/email_generator.rb +56 -0
  8. data/lib/generators/suspenders/environments/development_generator.rb +50 -0
  9. data/lib/generators/suspenders/environments/production_generator.rb +27 -0
  10. data/lib/generators/suspenders/environments/test_generator.rb +39 -0
  11. data/lib/generators/suspenders/factories_generator.rb +64 -0
  12. data/lib/generators/suspenders/inline_svg_generator.rb +24 -0
  13. data/lib/generators/suspenders/install/web_generator.rb +71 -0
  14. data/lib/generators/suspenders/jobs_generator.rb +34 -0
  15. data/lib/generators/suspenders/lint_generator.rb +94 -0
  16. data/lib/generators/suspenders/prerequisites_generator.rb +19 -0
  17. data/lib/generators/suspenders/rake_generator.rb +25 -0
  18. data/lib/generators/suspenders/setup_generator.rb +14 -0
  19. data/lib/generators/suspenders/styles_generator.rb +84 -0
  20. data/lib/generators/suspenders/tasks_generator.rb +20 -0
  21. data/lib/generators/suspenders/testing_generator.rb +113 -0
  22. data/lib/generators/suspenders/views_generator.rb +38 -0
  23. data/lib/generators/templates/ci/ci.yml.tt +148 -0
  24. data/lib/generators/templates/ci/dependabot.yml +7 -0
  25. data/lib/generators/templates/email/email_interceptor.rb +11 -0
  26. data/lib/generators/templates/factories/factories_spec.rb +7 -0
  27. data/lib/generators/templates/factories/factories_test.rb +9 -0
  28. data/lib/generators/templates/install/web/CONTRIBUTING.md +94 -0
  29. data/lib/generators/templates/lint/config_better_html.yml +2 -0
  30. data/lib/generators/templates/lint/config_initializers_better_html.rb +9 -0
  31. data/lib/generators/templates/lint/erb-lint.yml +63 -0
  32. data/lib/generators/templates/lint/erblint.rake +47 -0
  33. data/lib/generators/templates/lint/eslintrc.json +7 -0
  34. data/lib/generators/templates/lint/package.json +4 -0
  35. data/lib/generators/templates/lint/prettierignore +1 -0
  36. data/lib/generators/templates/lint/prettierrc +11 -0
  37. data/lib/generators/templates/lint/rubocop.yml.tt +7 -0
  38. data/lib/generators/templates/prerequisites/node-version.tt +1 -0
  39. data/lib/generators/templates/setup/bin_setup.rb +39 -0
  40. data/lib/generators/templates/styles/postcss.config.js +11 -0
  41. data/lib/generators/templates/testing/driver.rb +5 -0
  42. data/lib/generators/templates/views/flashes.html.erb +7 -0
  43. data/lib/install/web.rb +54 -0
  44. data/lib/suspenders/cleanup/generate_readme.rb +165 -0
  45. data/lib/suspenders/cleanup/organize_gemfile.rb +134 -0
  46. data/lib/suspenders/engine.rb +5 -0
  47. data/lib/suspenders/generators.rb +126 -0
  48. data/lib/suspenders/railtie.rb +4 -0
  49. data/lib/suspenders/version.rb +4 -6
  50. data/lib/suspenders.rb +9 -33
  51. data/lib/tasks/suspenders.rake +37 -0
  52. metadata +82 -173
  53. data/.ruby-version +0 -1
  54. data/CONTRIBUTING.md +0 -59
  55. data/GOALS.md +0 -65
  56. data/LICENSE +0 -21
  57. data/NEWS.md +0 -738
  58. data/RELEASING.md +0 -18
  59. data/bin/suspenders +0 -50
  60. data/docs/heroku_deploy.md +0 -19
  61. data/docs/rails_7.md +0 -5
  62. data/lib/suspenders/actions/strip_comments_action.rb +0 -254
  63. data/lib/suspenders/actions.rb +0 -106
  64. data/lib/suspenders/adapters/heroku.rb +0 -136
  65. data/lib/suspenders/app_builder.rb +0 -267
  66. data/lib/suspenders/exit_on_failure.rb +0 -19
  67. data/lib/suspenders/generators/accessibility_generator.rb +0 -12
  68. data/lib/suspenders/generators/advisories_generator.rb +0 -15
  69. data/lib/suspenders/generators/analytics_generator.rb +0 -24
  70. data/lib/suspenders/generators/app_generator.rb +0 -215
  71. data/lib/suspenders/generators/base.rb +0 -60
  72. data/lib/suspenders/generators/ci_generator.rb +0 -32
  73. data/lib/suspenders/generators/db_optimizations_generator.rb +0 -18
  74. data/lib/suspenders/generators/factories_generator.rb +0 -22
  75. data/lib/suspenders/generators/forms_generator.rb +0 -18
  76. data/lib/suspenders/generators/inline_svg_generator.rb +0 -14
  77. data/lib/suspenders/generators/jobs_generator.rb +0 -37
  78. data/lib/suspenders/generators/js_driver_generator.rb +0 -18
  79. data/lib/suspenders/generators/json_generator.rb +0 -14
  80. data/lib/suspenders/generators/lint_generator.rb +0 -14
  81. data/lib/suspenders/generators/production/compression_generator.rb +0 -14
  82. data/lib/suspenders/generators/production/deployment_generator.rb +0 -16
  83. data/lib/suspenders/generators/production/email_generator.rb +0 -34
  84. data/lib/suspenders/generators/production/force_tls_generator.rb +0 -11
  85. data/lib/suspenders/generators/production/manifest_generator.rb +0 -25
  86. data/lib/suspenders/generators/production/single_redirect.rb +0 -15
  87. data/lib/suspenders/generators/production/timeout_generator.rb +0 -22
  88. data/lib/suspenders/generators/profiler_generator.rb +0 -35
  89. data/lib/suspenders/generators/runner_generator.rb +0 -48
  90. data/lib/suspenders/generators/staging/pull_requests_generator.rb +0 -25
  91. data/lib/suspenders/generators/static_generator.rb +0 -14
  92. data/lib/suspenders/generators/stylelint_generator.rb +0 -71
  93. data/lib/suspenders/generators/stylesheet_base_generator.rb +0 -15
  94. data/lib/suspenders/generators/testing_generator.rb +0 -43
  95. data/lib/suspenders/generators/views_generator.rb +0 -25
  96. data/templates/Gemfile.erb +0 -49
  97. data/templates/Procfile +0 -2
  98. data/templates/README.md.erb +0 -28
  99. data/templates/_analytics.html.erb +0 -8
  100. data/templates/_css_overrides.html.erb +0 -7
  101. data/templates/_flashes.html.erb +0 -7
  102. data/templates/active_job.rb +0 -14
  103. data/templates/application.postcss.css +0 -1
  104. data/templates/bin_auto_migrate +0 -5
  105. data/templates/bin_deploy +0 -10
  106. data/templates/bin_setup +0 -28
  107. data/templates/bin_setup_review_app.erb +0 -21
  108. data/templates/bin_yarn +0 -18
  109. data/templates/bundler_audit.rake +0 -4
  110. data/templates/capybara_silence_puma.rb +0 -1
  111. data/templates/chromedriver.rb +0 -27
  112. data/templates/circle.yml.erb +0 -6
  113. data/templates/config_locales_en.yml.erb +0 -19
  114. data/templates/descriptions/advisories.md +0 -5
  115. data/templates/descriptions/analytics.md +0 -4
  116. data/templates/descriptions/ci.md +0 -4
  117. data/templates/descriptions/compression.md +0 -4
  118. data/templates/descriptions/db_optimizations.md +0 -2
  119. data/templates/descriptions/deployment.md +0 -5
  120. data/templates/descriptions/email.md +0 -9
  121. data/templates/descriptions/factories.md +0 -12
  122. data/templates/descriptions/force_tls.md +0 -1
  123. data/templates/descriptions/forms.md +0 -1
  124. data/templates/descriptions/inline_svg.md +0 -2
  125. data/templates/descriptions/jobs.md +0 -3
  126. data/templates/descriptions/js_driver.md +0 -4
  127. data/templates/descriptions/json.md +0 -1
  128. data/templates/descriptions/lint.md +0 -3
  129. data/templates/descriptions/manifest.md +0 -2
  130. data/templates/descriptions/profiler.md +0 -7
  131. data/templates/descriptions/pull_requests.md +0 -4
  132. data/templates/descriptions/runner.md +0 -10
  133. data/templates/descriptions/single_redirect.md +0 -1
  134. data/templates/descriptions/static.md +0 -5
  135. data/templates/descriptions/stylelint.md +0 -3
  136. data/templates/descriptions/stylesheet_base.md +0 -1
  137. data/templates/descriptions/testing.md +0 -9
  138. data/templates/descriptions/timeout.md +0 -4
  139. data/templates/descriptions/views.md +0 -8
  140. data/templates/email.rb +0 -3
  141. data/templates/errors.rb +0 -35
  142. data/templates/flashes_helper.rb +0 -5
  143. data/templates/hound.yml +0 -15
  144. data/templates/json_encoding.rb +0 -1
  145. data/templates/oj.rb +0 -3
  146. data/templates/partials/ci_simplecov.rb +0 -14
  147. data/templates/partials/db_optimizations_configuration.rb +0 -7
  148. data/templates/partials/deployment_readme.md +0 -8
  149. data/templates/partials/email_smtp.rb +0 -2
  150. data/templates/partials/profiler_readme.md +0 -8
  151. data/templates/partials/pull_requests_config.rb +0 -5
  152. data/templates/partials/runner_readme.md +0 -31
  153. data/templates/partials/runner_setup.rb +0 -2
  154. data/templates/postcss.config.js +0 -8
  155. data/templates/postgresql_database.yml.erb +0 -20
  156. data/templates/rack_mini_profiler.rb +0 -7
  157. data/templates/rails_helper.rb +0 -25
  158. data/templates/sample_env +0 -12
  159. data/templates/secrets.yml +0 -8
  160. data/templates/smtp.rb +0 -9
  161. data/templates/spec_helper.rb +0 -25
  162. data/templates/suspenders_gitignore +0 -18
  163. data/templates/suspenders_layout.html.erb.erb +0 -23
  164. /data/{templates → lib/generators/templates/factories}/factories.rb +0 -0
  165. /data/{templates → lib/generators/templates/factories}/factory_bot_rspec.rb +0 -0
  166. /data/{templates → lib/generators/templates/inline_svg}/inline_svg.rb +0 -0
  167. /data/{templates → lib/generators/templates/lint}/stylelintrc.json +0 -0
  168. /data/{templates → lib/generators/templates/tasks}/dev.rake +0 -0
  169. /data/{templates → lib/generators/templates/testing}/action_mailer.rb +0 -0
  170. /data/{templates → lib/generators/templates/testing}/i18n.rb +0 -0
  171. /data/{templates/shoulda_matchers_config_rspec.rb → lib/generators/templates/testing/shoulda_matchers.rb} +0 -0
@@ -0,0 +1,64 @@
1
+ module Suspenders
2
+ module Generators
3
+ class FactoriesGenerator < Rails::Generators::Base
4
+ include Suspenders::Generators::Helpers
5
+
6
+ source_root File.expand_path("../../templates/factories", __FILE__)
7
+ desc <<~MARKDOWN
8
+ Uses [FactoryBot][] as an alternative to [Fixtures][] to help you define
9
+ dummy and test data for your test suite. The `create`, `build`, and
10
+ `build_stubbed` class methods are directly available to all tests.
11
+
12
+ Place FactoryBot definitions in `spec/factories.rb`, at least until it
13
+ grows unwieldy. This helps reduce confusion around circular dependencies and
14
+ makes it easy to jump between definitions.
15
+
16
+ [FactoryBot]: https://github.com/thoughtbot/factory_bot
17
+ [Fixtures]: https://guides.rubyonrails.org/testing.html#the-low-down-on-fixtures
18
+ MARKDOWN
19
+
20
+ def add_factory_bot
21
+ gem_group :development, :test do
22
+ gem "factory_bot_rails"
23
+ end
24
+
25
+ Bundler.with_unbundled_env { run "bundle install" }
26
+ end
27
+
28
+ def set_up_factory_bot
29
+ if default_test_helper_present?
30
+ insert_into_file Rails.root.join("test/test_helper.rb"), after: "class TestCase" do
31
+ "\n include FactoryBot::Syntax::Methods"
32
+ end
33
+ elsif rspec_test_helper_present?
34
+ copy_file "factory_bot_rspec.rb", "spec/support/factory_bot.rb"
35
+ insert_into_file Rails.root.join("spec/rails_helper.rb") do
36
+ %(Dir[Rails.root.join("spec/support/**/*.rb")].sort.each { |file| require file })
37
+ end
38
+ end
39
+ end
40
+
41
+ def generate_empty_factories_file
42
+ if default_test_suite?
43
+ copy_file "factories.rb", "test/factories.rb"
44
+ elsif rspec_test_suite?
45
+ copy_file "factories.rb", "spec/factories.rb"
46
+ end
47
+ end
48
+
49
+ def remove_fixture_definitions
50
+ if default_test_helper_present?
51
+ comment_lines "test/test_helper.rb", /fixtures :all/
52
+ end
53
+ end
54
+
55
+ def create_linting_test
56
+ if default_test_suite?
57
+ copy_file "factories_test.rb", "test/factory_bots/factories_test.rb"
58
+ elsif rspec_test_suite?
59
+ copy_file "factories_spec.rb", "spec/factory_bots/factories_spec.rb"
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,24 @@
1
+ module Suspenders
2
+ module Generators
3
+ class InlineSvgGenerator < Rails::Generators::Base
4
+ include Suspenders::Generators::APIAppUnsupported
5
+ source_root File.expand_path("../../templates/inline_svg", __FILE__)
6
+ desc <<~MARKDOWN
7
+ Uses [inline_svg][] for embedding SVG documents into views.
8
+
9
+ Configuration can be found at `config/initializers/inline_svg.rb`
10
+
11
+ [inline_svg]: https://github.com/jamesmartin/inline_svg
12
+ MARKDOWN
13
+
14
+ def add_inline_svg_gem
15
+ gem "inline_svg"
16
+ Bundler.with_unbundled_env { run "bundle install" }
17
+ end
18
+
19
+ def configure_inline_svg
20
+ copy_file "inline_svg.rb", "config/initializers/inline_svg.rb"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,71 @@
1
+ module Suspenders
2
+ module Generators
3
+ module Install
4
+ class WebGenerator < Rails::Generators::Base
5
+ include Suspenders::Generators::APIAppUnsupported
6
+ include Suspenders::Generators::DatabaseUnsupported
7
+ include Suspenders::Generators::NodeNotInstalled
8
+ include Suspenders::Generators::NodeVersionUnsupported
9
+
10
+ source_root File.expand_path("../../../templates/install/web", __FILE__)
11
+ desc <<~MARKDOWN
12
+ Invokes all necessary generators for new Rails applications generated with Suspenders.
13
+
14
+ This generatator is intended to be invoked as part of an [application template][].
15
+
16
+ ```
17
+ rails new suspenders_qa \
18
+ --skip-test \
19
+ -d=postgresql \
20
+ -m=https://raw.githubusercontent.com/thoughtbot/suspenders/main/lib/install/web.rb
21
+ ```
22
+
23
+ [application template]: https://guides.rubyonrails.org/rails_application_templates.html
24
+ MARKDOWN
25
+
26
+ def invoke_generators
27
+ # This needs to go first, since it configures `.node-version`
28
+ generate "suspenders:prerequisites"
29
+
30
+ generate "suspenders:accessibility"
31
+ generate "suspenders:advisories"
32
+ generate "suspenders:email"
33
+ generate "suspenders:factories"
34
+ generate "suspenders:inline_svg"
35
+ generate "suspenders:lint"
36
+ generate "suspenders:rake"
37
+ generate "suspenders:setup"
38
+ generate "suspenders:tasks"
39
+ generate "suspenders:testing"
40
+ generate "suspenders:views"
41
+
42
+ # suspenders:jobs needs to be invoked before suspenders:styles, since
43
+ # suspenders:styles generator creates Procfile.dev
44
+ generate "suspenders:styles"
45
+ generate "suspenders:jobs"
46
+
47
+ # Needs to run after other generators, since some touch the
48
+ # configuration files.
49
+ generate "suspenders:environments:test"
50
+ generate "suspenders:environments:development"
51
+ generate "suspenders:environments:production"
52
+
53
+ # Needs to be run last since it depends on lint, testing, and
54
+ # advisories
55
+ generate "suspenders:ci"
56
+ end
57
+
58
+ def cleanup
59
+ rake "suspenders:cleanup:organize_gemfile"
60
+ rake "suspenders:cleanup:generate_readme"
61
+ copy_file "CONTRIBUTING.md", "CONTRIBUTING.md"
62
+ end
63
+
64
+ def lint
65
+ run "yarn run fix:prettier"
66
+ run "bundle exec rake standard:fix_unsafely"
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,34 @@
1
+ module Suspenders
2
+ module Generators
3
+ class JobsGenerator < Rails::Generators::Base
4
+ desc <<~MARKDOWN
5
+ Uses [Sidekiq][] for [background job][] processing.
6
+
7
+ Configures the `test` environment to use the [inline][] adapter.
8
+
9
+ [Sidekiq]: https://github.com/sidekiq/sidekiq
10
+ [background job]: https://guides.rubyonrails.org/active_job_basics.html
11
+ [inline]: https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/InlineAdapter.html
12
+ MARKDOWN
13
+
14
+ def add_sidekiq_gem
15
+ gem "sidekiq"
16
+ Bundler.with_unbundled_env { run "bundle install" }
17
+ end
18
+
19
+ def configure_active_job
20
+ environment "config.active_job.queue_adapter = :sidekiq"
21
+ environment "config.active_job.queue_adapter = :inline", env: "test"
22
+ end
23
+
24
+ def configure_procfile
25
+ if Rails.root.join("Procfile.dev").exist?
26
+ append_to_file "Procfile.dev", "worker: bundle exec sidekiq"
27
+ else
28
+ say "Add default Procfile.dev"
29
+ create_file "Procfile.dev", "worker: bundle exec sidekiq"
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,94 @@
1
+ module Suspenders
2
+ module Generators
3
+ class LintGenerator < Rails::Generators::Base
4
+ include Suspenders::Generators::Helpers
5
+
6
+ source_root File.expand_path("../../templates/lint", __FILE__)
7
+ desc <<~MARKDOWN
8
+ - Uses [@thoughtbot/eslint-config][] for JavaScript linting.
9
+ - Uses [@thoughtbot/stylelint-config][] for CSS linting.
10
+ - Uses [prettier][] for additional linting.
11
+ - Uses [better_html][], [erb_lint][], and [erblint-github][] for ERB linting.
12
+ - Uses [standard][] for Ruby linting.
13
+
14
+ **Available Commands**
15
+
16
+ - Run `yarn lint` to lint front-end code.
17
+ - Run `yarn fix:prettier` to automatically fix prettier violations.
18
+ - Run `bin/rails standard` to lint ERB and Ruby code.
19
+ - Run `bundle exec standardrb --fix` to fix standard violations.
20
+
21
+ [@thoughtbot/eslint-config]: https://github.com/thoughtbot/eslint-config
22
+ [@thoughtbot/stylelint-config]: https://github.com/thoughtbot/stylelint-config
23
+ [prettier]: https://prettier.io
24
+ [better_html]: https://github.com/Shopify/better-html
25
+ [erb_lint]: https://github.com/Shopify/erb-lint
26
+ [erblint-github]: https://github.com/github/erblint-github
27
+ [standard]: https://github.com/standardrb/standard
28
+ MARKDOWN
29
+
30
+ def check_package_json
31
+ unless File.exist? Rails.root.join("package.json")
32
+ copy_file "package.json", "package.json"
33
+ end
34
+ end
35
+
36
+ # TODO: Remove eslint version pin once the follownig is solved
37
+ # https://github.com/thoughtbot/eslint-config/issues/10
38
+ def install_dependencies
39
+ run "yarn add stylelint eslint@^8.9.0 @thoughtbot/stylelint-config @thoughtbot/eslint-config npm-run-all prettier --dev"
40
+ end
41
+
42
+ def install_gems
43
+ gem_group :development, :test do
44
+ gem "better_html", require: false
45
+ gem "erb_lint", require: false
46
+ gem "erblint-github", require: false
47
+ gem "standard"
48
+ end
49
+ Bundler.with_unbundled_env { run "bundle install" }
50
+ end
51
+
52
+ def configure_stylelint
53
+ copy_file "stylelintrc.json", ".stylelintrc.json"
54
+ end
55
+
56
+ def configure_eslint
57
+ copy_file "eslintrc.json", ".eslintrc.json"
58
+ end
59
+
60
+ def configure_prettier
61
+ copy_file "prettierrc", ".prettierrc"
62
+ copy_file "prettierignore", ".prettierignore"
63
+ end
64
+
65
+ def configure_erb_lint
66
+ copy_file "erb-lint.yml", ".erb-lint.yml"
67
+ copy_file "config_better_html.yml", "config/better_html.yml"
68
+ copy_file "config_initializers_better_html.rb", "config/initializers/better_html.rb"
69
+ copy_file "erblint.rake", "lib/tasks/erblint.rake"
70
+ template "rubocop.yml.tt", ".rubocop.yml"
71
+ end
72
+
73
+ def update_package_json
74
+ content = File.read package_json
75
+ json = JSON.parse content
76
+ json["scripts"] ||= {}
77
+
78
+ json["scripts"]["lint"] = "run-p lint:eslint lint:stylelint lint:prettier"
79
+ json["scripts"]["lint:eslint"] = "eslint --max-warnings=0 --no-error-on-unmatched-pattern 'app/javascript/**/*.js'"
80
+ json["scripts"]["lint:stylelint"] = "stylelint 'app/assets/stylesheets/**/*.css'"
81
+ json["scripts"]["lint:prettier"] = "prettier --check '**/*' --ignore-unknown"
82
+ json["scripts"]["fix:prettier"] = "prettier --write '**/*' --ignore-unknown"
83
+
84
+ File.write package_json, JSON.pretty_generate(json)
85
+ end
86
+
87
+ private
88
+
89
+ def package_json
90
+ Rails.root.join("package.json")
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,19 @@
1
+ module Suspenders
2
+ module Generators
3
+ class PrerequisitesGenerator < Rails::Generators::Base
4
+ include Suspenders::Generators::Helpers
5
+ include Suspenders::Generators::NodeNotInstalled
6
+ include Suspenders::Generators::NodeVersionUnsupported
7
+
8
+ source_root File.expand_path("../../templates/prerequisites", __FILE__)
9
+
10
+ desc <<~MARKDOWN
11
+ Creates `.node-version` file set to the current LTS version.
12
+ MARKDOWN
13
+
14
+ def set_node_version
15
+ template "node-version", ".node-version"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ module Suspenders
2
+ module Generators
3
+ class RakeGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../../templates/rake", __FILE__)
5
+ desc <<~MARKDOWN
6
+ Adds default Raketask wich is a wrapper for `suspenders:rake`.
7
+
8
+ This will do the following:
9
+
10
+ - Run the test suite.
11
+ - Run a Ruby and ERB linter.
12
+ - Scan the Ruby codebase for any dependency vulnerabilities.
13
+ MARKDOWN
14
+
15
+ def configure_default_rake_task
16
+ append_to_file "Rakefile", <<~RUBY
17
+
18
+ if Rails.env.local?
19
+ task default: "suspenders:rake"
20
+ end
21
+ RUBY
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ module Suspenders
2
+ module Generators
3
+ class SetupGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../../templates/setup", __FILE__)
5
+ desc <<~MARKDOWN
6
+ Run `bin/setup` to install dependencies and seed development data.
7
+ MARKDOWN
8
+
9
+ def replace_bin_setup
10
+ copy_file "bin_setup.rb", "bin/setup", force: true
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,84 @@
1
+ module Suspenders
2
+ module Generators
3
+ class StylesGenerator < Rails::Generators::Base
4
+ include Suspenders::Generators::APIAppUnsupported
5
+
6
+ source_root File.expand_path("../../templates/styles", __FILE__)
7
+ desc <<~MARKDOWN
8
+ - Uses [PostCSS][] via [cssbundling-rails][].
9
+ - Uses [modern-normalize][] to normalize browsers' default style.
10
+
11
+ Configuration can be found at `postcss.config.js`.
12
+
13
+ Adds the following stylesheet structure.
14
+
15
+ ```
16
+ app/assets/stylesheets/base.css
17
+ app/assets/stylesheets/components.css
18
+ app/assets/stylesheets/utilities.css
19
+ ```
20
+
21
+ Adds `app/assets/static` so that [postcss-url][] has a directory to copy
22
+ assets to.
23
+
24
+ [PostCSS]: https://postcss.org
25
+ [cssbundling-rails]: https://github.com/rails/cssbundling-rails
26
+ [modern-normalize]: https://github.com/sindresorhus/modern-normalize
27
+ [postcss-url]: https://github.com/postcss/postcss-url
28
+ MARKDOWN
29
+
30
+ def add_cssbundling_rails_gem
31
+ gem "cssbundling-rails"
32
+
33
+ Bundler.with_unbundled_env { run "bundle install" }
34
+ run "bin/rails css:install:postcss"
35
+ end
36
+
37
+ def build_directory_structure
38
+ create_file "app/assets/stylesheets/base.css"
39
+ append_to_file "app/assets/stylesheets/base.css", "/* Base Styles */"
40
+
41
+ create_file "app/assets/stylesheets/components.css"
42
+ append_to_file "app/assets/stylesheets/components.css", "/* Component Styles */"
43
+
44
+ create_file "app/assets/stylesheets/utilities.css"
45
+ append_to_file "app/assets/stylesheets/utilities.css", "/* Utility Styles */"
46
+ end
47
+
48
+ def configure_application_stylesheet
49
+ run "yarn add modern-normalize"
50
+
51
+ append_to_file "app/assets/stylesheets/application.postcss.css" do
52
+ <<~TEXT
53
+ @import "modern-normalize";
54
+ @import "base.css";
55
+ @import "components.css";
56
+ @import "utilities.css";
57
+ TEXT
58
+ end
59
+ end
60
+
61
+ def install_postcss_url
62
+ run "yarn add postcss-url"
63
+ end
64
+
65
+ def configures_postcss
66
+ begin
67
+ File.delete(postcss_config)
68
+ rescue Errno::ENOENT
69
+ end
70
+
71
+ empty_directory "app/assets/static"
72
+ create_file "app/assets/static/.gitkeep"
73
+
74
+ copy_file "postcss.config.js", "postcss.config.js"
75
+ end
76
+
77
+ private
78
+
79
+ def postcss_config
80
+ Rails.root.join("postcss.config.js")
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,20 @@
1
+ module Suspenders
2
+ module Generators
3
+ class TasksGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../../templates/tasks", __FILE__)
5
+ desc <<~MARKDOWN
6
+ Creates `lib/tasks/dev.rake` which contains the following tasks:
7
+
8
+ `bin/rails dev:prime` which loads sample data for local development.
9
+ MARKDOWN
10
+
11
+ def create_dev_rake
12
+ if Bundler.rubygems.find_name("factory_bot").any?
13
+ copy_file "dev.rake", "lib/tasks/dev.rake"
14
+ else
15
+ say "This generator requires Factory Bot"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,113 @@
1
+ module Suspenders
2
+ module Generators
3
+ class TestingGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../../templates/testing", __FILE__)
5
+ desc <<~MARKDOWN
6
+ Uses [RSpec][] and [RSpec Rails][] in favor of the [default test suite][].
7
+
8
+ The test suite can be run with `bin/rails spec`.
9
+
10
+ Configuration can be found in the following files:
11
+
12
+ ```
13
+ spec/rails_helper.rb
14
+ spec/spec_helper.rb
15
+ spec/support/action_mailer.rb
16
+ spec/support/driver.rb
17
+ spec/support/i18n.rb
18
+ spec/support/should_matchers.rb
19
+ ```
20
+
21
+ - Uses [action_dispatch-testing-integration-capybara][] to introduce Capybara assertions into Request specs.
22
+ - Uses [should-matchers][] for simple one-liner tests for common Rails functionality.
23
+ - Uses [webmock][] for stubbing and setting expectations on HTTP requests in Ruby.
24
+
25
+ [RSpec]: http://rspec.info
26
+ [RSpec Rails]: https://github.com/rspec/rspec-rails
27
+ [default test suite]: https://guides.rubyonrails.org/testing.html
28
+ [action_dispatch-testing-integration-capybara]: https://github.com/thoughtbot/action_dispatch-testing-integration-capybara
29
+ [should-matchers]: https://github.com/thoughtbot/shoulda-matchers
30
+ [webmock]: https://github.com/bblimke/webmock
31
+ MARKDOWN
32
+
33
+ def add_gems
34
+ gem_group :development, :test do
35
+ gem "rspec-rails", "~> 6.1.0"
36
+ end
37
+
38
+ gem_group :test do
39
+ gem "capybara"
40
+ gem "action_dispatch-testing-integration-capybara",
41
+ github: "thoughtbot/action_dispatch-testing-integration-capybara", tag: "v0.1.1",
42
+ require: "action_dispatch/testing/integration/capybara/rspec"
43
+ gem "selenium-webdriver"
44
+ gem "shoulda-matchers", "~> 6.0"
45
+ gem "webmock"
46
+ end
47
+
48
+ Bundler.with_unbundled_env { run "bundle install" }
49
+ end
50
+
51
+ def run_rspec_installation_script
52
+ rails_command "generate rspec:install"
53
+ end
54
+
55
+ def modify_rails_helper
56
+ insert_into_file "spec/rails_helper.rb",
57
+ "\s\sconfig.infer_base_class_for_anonymous_controllers = false\n",
58
+ after: "RSpec.configure do |config|\n"
59
+
60
+ uncomment_lines "spec/rails_helper.rb", /Rails\.root\.glob/
61
+ end
62
+
63
+ def modify_spec_helper
64
+ persistence_file_path = "\s\sconfig.example_status_persistence_file_path = \"tmp/rspec_examples.txt\"\n"
65
+ order = "\s\sconfig.order = :random\n\n"
66
+ webmock_config = <<~RUBY
67
+
68
+ WebMock.disable_net_connect!(
69
+ allow_localhost: true,
70
+ allow: [
71
+ /(chromedriver|storage).googleapis.com/,
72
+ "googlechromelabs.github.io"
73
+ ]
74
+ )
75
+ RUBY
76
+
77
+ insert_into_file "spec/spec_helper.rb",
78
+ persistence_file_path + order,
79
+ after: "RSpec.configure do |config|\n"
80
+
81
+ insert_into_file "spec/spec_helper.rb", "require \"webmock/rspec\"\n\n", before: "RSpec.configure do |config|"
82
+ insert_into_file "spec/spec_helper.rb", webmock_config
83
+ end
84
+
85
+ def create_system_spec_dir
86
+ empty_directory "spec/system"
87
+ create_file "spec/system/.gitkeep"
88
+ end
89
+
90
+ def configure_chromedriver
91
+ copy_file "driver.rb", "spec/support/driver.rb"
92
+ end
93
+
94
+ def configure_i18n_helper
95
+ copy_file "i18n.rb", "spec/support/i18n.rb"
96
+ end
97
+
98
+ def configure_shoulda_matchers
99
+ copy_file "shoulda_matchers.rb", "spec/support/shoulda_matchers.rb"
100
+ end
101
+
102
+ def configure_action_mailer_helpers
103
+ # https://guides.rubyonrails.org/testing.html#the-basic-test-case
104
+ #
105
+ # The ActionMailer::Base.deliveries array is only reset automatically in
106
+ # ActionMailer::TestCase and ActionDispatch::IntegrationTest tests. If
107
+ # you want to have a clean slate outside these test cases, you can reset
108
+ # it manually with: ActionMailer::Base.deliveries.clear
109
+ copy_file "action_mailer.rb", "spec/support/action_mailer.rb"
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,38 @@
1
+ module Suspenders
2
+ module Generators
3
+ class ViewsGenerator < Rails::Generators::Base
4
+ include Suspenders::Generators::APIAppUnsupported
5
+
6
+ source_root File.expand_path("../../templates/views", __FILE__)
7
+ desc <<~MARKDOWN
8
+ - A [partial][] for [flash messages][] is located in `app/views/application/_flashes.html.erb`.
9
+ - Sets [lang][] attribute on `<html>` element to `en` via `I18n.local`.
10
+ - Dynamically sets `<title>` via the [title][] gem.
11
+ - Disables Turbo's [Prefetch][] in an effort to reduce unnecessary network requests.
12
+
13
+ [partial]: https://guides.rubyonrails.org/layouts_and_rendering.html#using-partials
14
+ [flash messages]: https://guides.rubyonrails.org/action_controller_overview.html#the-flash
15
+ [lang]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang
16
+ [title]: https://github.com/calebhearth/title
17
+ [Prefetch]: https://turbo.hotwired.dev/handbook/drive#prefetching-links-on-hover
18
+ MARKDOWN
19
+
20
+ def install_gems
21
+ gem "title"
22
+
23
+ Bundler.with_unbundled_env { run "bundle install" }
24
+ end
25
+
26
+ def create_views
27
+ copy_file "flashes.html.erb", "app/views/application/_flashes.html.erb"
28
+ end
29
+
30
+ def update_application_layout
31
+ insert_into_file "app/views/layouts/application.html.erb", " <%= render \"flashes\" -%>\n", after: "<body>\n"
32
+ gsub_file "app/views/layouts/application.html.erb", /<html>/, "<html lang=\"<%= I18n.locale %>\">"
33
+ gsub_file "app/views/layouts/application.html.erb", /<title>.*<\/title>/, "<title><%= title %></title>"
34
+ insert_into_file "app/views/layouts/application.html.erb", " <meta name=\"turbo-prefetch\" content=\"false\">\n", after: "</title>"
35
+ end
36
+ end
37
+ end
38
+ end