suspenders 20230113.0 → 20250317.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 (170) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +98 -170
  3. data/Rakefile +17 -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 +54 -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 +85 -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/email/email_interceptor.rb +11 -0
  25. data/lib/generators/templates/factories/factories_spec.rb +7 -0
  26. data/lib/generators/templates/factories/factories_test.rb +9 -0
  27. data/lib/generators/templates/install/web/CONTRIBUTING.md +94 -0
  28. data/lib/generators/templates/lint/config_better_html.yml +2 -0
  29. data/lib/generators/templates/lint/config_initializers_better_html.rb +9 -0
  30. data/lib/generators/templates/lint/erb-lint.yml +63 -0
  31. data/lib/generators/templates/lint/erblint.rake +47 -0
  32. data/lib/generators/templates/lint/eslintrc.json +7 -0
  33. data/lib/generators/templates/lint/package.json +4 -0
  34. data/lib/generators/templates/lint/prettierignore +1 -0
  35. data/lib/generators/templates/lint/prettierrc +11 -0
  36. data/lib/generators/templates/lint/rubocop.yml.tt +7 -0
  37. data/lib/generators/templates/prerequisites/node-version.tt +1 -0
  38. data/lib/generators/templates/setup/bin_setup.rb +39 -0
  39. data/lib/generators/templates/styles/postcss.config.js +11 -0
  40. data/lib/generators/templates/testing/driver.rb +5 -0
  41. data/lib/generators/templates/views/flashes.html.erb +7 -0
  42. data/lib/install/web.rb +70 -0
  43. data/lib/suspenders/cleanup/generate_readme.rb +165 -0
  44. data/lib/suspenders/cleanup/organize_gemfile.rb +134 -0
  45. data/lib/suspenders/engine.rb +5 -0
  46. data/lib/suspenders/generators.rb +126 -0
  47. data/lib/suspenders/railtie.rb +4 -0
  48. data/lib/suspenders/version.rb +4 -6
  49. data/lib/suspenders.rb +9 -33
  50. data/lib/tasks/suspenders.rake +37 -0
  51. metadata +81 -173
  52. data/.ruby-version +0 -1
  53. data/CONTRIBUTING.md +0 -59
  54. data/GOALS.md +0 -65
  55. data/LICENSE +0 -21
  56. data/NEWS.md +0 -738
  57. data/RELEASING.md +0 -18
  58. data/bin/suspenders +0 -50
  59. data/docs/heroku_deploy.md +0 -19
  60. data/docs/rails_7.md +0 -5
  61. data/lib/suspenders/actions/strip_comments_action.rb +0 -254
  62. data/lib/suspenders/actions.rb +0 -106
  63. data/lib/suspenders/adapters/heroku.rb +0 -136
  64. data/lib/suspenders/app_builder.rb +0 -267
  65. data/lib/suspenders/exit_on_failure.rb +0 -19
  66. data/lib/suspenders/generators/accessibility_generator.rb +0 -12
  67. data/lib/suspenders/generators/advisories_generator.rb +0 -15
  68. data/lib/suspenders/generators/analytics_generator.rb +0 -24
  69. data/lib/suspenders/generators/app_generator.rb +0 -215
  70. data/lib/suspenders/generators/base.rb +0 -60
  71. data/lib/suspenders/generators/ci_generator.rb +0 -32
  72. data/lib/suspenders/generators/db_optimizations_generator.rb +0 -18
  73. data/lib/suspenders/generators/factories_generator.rb +0 -22
  74. data/lib/suspenders/generators/forms_generator.rb +0 -18
  75. data/lib/suspenders/generators/inline_svg_generator.rb +0 -14
  76. data/lib/suspenders/generators/jobs_generator.rb +0 -37
  77. data/lib/suspenders/generators/js_driver_generator.rb +0 -18
  78. data/lib/suspenders/generators/json_generator.rb +0 -14
  79. data/lib/suspenders/generators/lint_generator.rb +0 -14
  80. data/lib/suspenders/generators/production/compression_generator.rb +0 -14
  81. data/lib/suspenders/generators/production/deployment_generator.rb +0 -16
  82. data/lib/suspenders/generators/production/email_generator.rb +0 -34
  83. data/lib/suspenders/generators/production/force_tls_generator.rb +0 -11
  84. data/lib/suspenders/generators/production/manifest_generator.rb +0 -25
  85. data/lib/suspenders/generators/production/single_redirect.rb +0 -15
  86. data/lib/suspenders/generators/production/timeout_generator.rb +0 -22
  87. data/lib/suspenders/generators/profiler_generator.rb +0 -35
  88. data/lib/suspenders/generators/runner_generator.rb +0 -48
  89. data/lib/suspenders/generators/staging/pull_requests_generator.rb +0 -25
  90. data/lib/suspenders/generators/static_generator.rb +0 -14
  91. data/lib/suspenders/generators/stylelint_generator.rb +0 -71
  92. data/lib/suspenders/generators/stylesheet_base_generator.rb +0 -15
  93. data/lib/suspenders/generators/testing_generator.rb +0 -43
  94. data/lib/suspenders/generators/views_generator.rb +0 -25
  95. data/templates/Gemfile.erb +0 -49
  96. data/templates/Procfile +0 -2
  97. data/templates/README.md.erb +0 -28
  98. data/templates/_analytics.html.erb +0 -8
  99. data/templates/_css_overrides.html.erb +0 -7
  100. data/templates/_flashes.html.erb +0 -7
  101. data/templates/active_job.rb +0 -14
  102. data/templates/application.postcss.css +0 -1
  103. data/templates/bin_auto_migrate +0 -5
  104. data/templates/bin_deploy +0 -10
  105. data/templates/bin_setup +0 -28
  106. data/templates/bin_setup_review_app.erb +0 -21
  107. data/templates/bin_yarn +0 -18
  108. data/templates/bundler_audit.rake +0 -4
  109. data/templates/capybara_silence_puma.rb +0 -1
  110. data/templates/chromedriver.rb +0 -27
  111. data/templates/circle.yml.erb +0 -6
  112. data/templates/config_locales_en.yml.erb +0 -19
  113. data/templates/descriptions/advisories.md +0 -5
  114. data/templates/descriptions/analytics.md +0 -4
  115. data/templates/descriptions/ci.md +0 -4
  116. data/templates/descriptions/compression.md +0 -4
  117. data/templates/descriptions/db_optimizations.md +0 -2
  118. data/templates/descriptions/deployment.md +0 -5
  119. data/templates/descriptions/email.md +0 -9
  120. data/templates/descriptions/factories.md +0 -12
  121. data/templates/descriptions/force_tls.md +0 -1
  122. data/templates/descriptions/forms.md +0 -1
  123. data/templates/descriptions/inline_svg.md +0 -2
  124. data/templates/descriptions/jobs.md +0 -3
  125. data/templates/descriptions/js_driver.md +0 -4
  126. data/templates/descriptions/json.md +0 -1
  127. data/templates/descriptions/lint.md +0 -3
  128. data/templates/descriptions/manifest.md +0 -2
  129. data/templates/descriptions/profiler.md +0 -7
  130. data/templates/descriptions/pull_requests.md +0 -4
  131. data/templates/descriptions/runner.md +0 -10
  132. data/templates/descriptions/single_redirect.md +0 -1
  133. data/templates/descriptions/static.md +0 -5
  134. data/templates/descriptions/stylelint.md +0 -3
  135. data/templates/descriptions/stylesheet_base.md +0 -1
  136. data/templates/descriptions/testing.md +0 -9
  137. data/templates/descriptions/timeout.md +0 -4
  138. data/templates/descriptions/views.md +0 -8
  139. data/templates/email.rb +0 -3
  140. data/templates/errors.rb +0 -35
  141. data/templates/flashes_helper.rb +0 -5
  142. data/templates/hound.yml +0 -15
  143. data/templates/json_encoding.rb +0 -1
  144. data/templates/oj.rb +0 -3
  145. data/templates/partials/ci_simplecov.rb +0 -14
  146. data/templates/partials/db_optimizations_configuration.rb +0 -7
  147. data/templates/partials/deployment_readme.md +0 -8
  148. data/templates/partials/email_smtp.rb +0 -2
  149. data/templates/partials/profiler_readme.md +0 -8
  150. data/templates/partials/pull_requests_config.rb +0 -5
  151. data/templates/partials/runner_readme.md +0 -31
  152. data/templates/partials/runner_setup.rb +0 -2
  153. data/templates/postcss.config.js +0 -8
  154. data/templates/postgresql_database.yml.erb +0 -20
  155. data/templates/rack_mini_profiler.rb +0 -7
  156. data/templates/rails_helper.rb +0 -25
  157. data/templates/sample_env +0 -12
  158. data/templates/secrets.yml +0 -8
  159. data/templates/smtp.rb +0 -9
  160. data/templates/spec_helper.rb +0 -25
  161. data/templates/suspenders_gitignore +0 -18
  162. data/templates/suspenders_layout.html.erb.erb +0 -23
  163. /data/{templates → lib/generators/templates/factories}/factories.rb +0 -0
  164. /data/{templates → lib/generators/templates/factories}/factory_bot_rspec.rb +0 -0
  165. /data/{templates → lib/generators/templates/inline_svg}/inline_svg.rb +0 -0
  166. /data/{templates → lib/generators/templates/lint}/stylelintrc.json +0 -0
  167. /data/{templates → lib/generators/templates/tasks}/dev.rake +0 -0
  168. /data/{templates → lib/generators/templates/testing}/action_mailer.rb +0 -0
  169. /data/{templates → lib/generators/templates/testing}/i18n.rb +0 -0
  170. /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,85 @@
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
+ #### Use the latest suspenders release:
17
+
18
+ ```
19
+ rails new <app_name> \\
20
+ --skip-rubocop \\
21
+ --skip-test \\
22
+ -d=postgresql \\
23
+ -m=https://raw.githubusercontent.com/thoughtbot/suspenders/main/lib/install/web.rb
24
+ ```
25
+
26
+ #### OR use the current (possibly unreleased) `main` branch of suspenders:
27
+
28
+ ```
29
+ rails new app_name \\
30
+ --suspenders-main \\
31
+ --skip-rubocop \\
32
+ --skip-test \\
33
+ -d=postgresql \\
34
+ -m=https://raw.githubusercontent.com/thoughtbot/suspenders/main/lib/install/web.rb
35
+ ```
36
+
37
+ [application template]: https://guides.rubyonrails.org/rails_application_templates.html
38
+ MARKDOWN
39
+
40
+ def invoke_generators
41
+ # This needs to go first, since it configures `.node-version`
42
+ generate "suspenders:prerequisites"
43
+
44
+ generate "suspenders:accessibility"
45
+ generate "suspenders:advisories"
46
+ generate "suspenders:email"
47
+ generate "suspenders:factories"
48
+ generate "suspenders:inline_svg"
49
+ generate "suspenders:lint"
50
+ generate "suspenders:rake"
51
+ generate "suspenders:setup"
52
+ generate "suspenders:tasks"
53
+ generate "suspenders:testing"
54
+ generate "suspenders:views"
55
+
56
+ # suspenders:jobs needs to be invoked before suspenders:styles, since
57
+ # suspenders:styles generator creates Procfile.dev
58
+ generate "suspenders:styles"
59
+ generate "suspenders:jobs"
60
+
61
+ # Needs to run after other generators, since some touch the
62
+ # configuration files.
63
+ generate "suspenders:environments:test"
64
+ generate "suspenders:environments:development"
65
+ generate "suspenders:environments:production"
66
+
67
+ # Needs to be run last since it depends on lint, testing, and
68
+ # advisories
69
+ generate "suspenders:ci"
70
+ end
71
+
72
+ def cleanup
73
+ rake "suspenders:cleanup:organize_gemfile"
74
+ rake "suspenders:cleanup:generate_readme"
75
+ copy_file "CONTRIBUTING.md", "CONTRIBUTING.md"
76
+ end
77
+
78
+ def lint
79
+ run "yarn run fix:prettier"
80
+ run "bundle exec rake standard:fix_unsafely"
81
+ end
82
+ end
83
+ end
84
+ end
85
+ 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/shoulda_matchers.rb
19
+ ```
20
+
21
+ - Uses [action_dispatch-testing-integration-capybara][] to introduce Capybara assertions into Request specs.
22
+ - Uses [shoulda-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
+ [shoulda-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