From 80cdffc97eac59f337c1a5c06bab56f1742e3bd6 Mon Sep 17 00:00:00 2001 From: Steve Polito Date: Tue, 2 Jan 2024 14:59:19 -0500 Subject: [PATCH] Introduce `suspenders:views` generator Configures flash messages, page titles via the [title][] gem, and sets the document [lang][]. [title]: https://github.com/calebhearth/title [lang]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang It should be noted that running `rails gscaffold` generates [views][] that contain the flash. Although we could have [overridden][] this generator, that would risk drift between our overridden generator and the one in Rails core. Additionally, we decided to remove the `FlashesHelper` introduced in [6c562b95e2e3c7ea31a04e6ef71c6a44b0b9ab2f][] since that is not a pattern we currently use. [views]: https://github.com/rails/rails/blob/main/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt [overridden]: https://guides.rubyonrails.org/generators.html#overriding-rails-generator-templates [6c562b95e2e3c7ea31a04e6ef71c6a44b0b9ab2f]: https://github.com/thoughtbot/suspenders/commit/6c562b95e2e3c7ea31a04e6ef71c6a44b0b9ab2f --- NEWS.md | 1 + README.md | 8 ++ lib/generators/suspenders/views_generator.rb | 26 +++++ .../templates/views/flashes.html.erb | 7 ++ .../suspenders/views_generator_test.rb | 104 ++++++++++++++++++ 5 files changed, 146 insertions(+) create mode 100644 lib/generators/suspenders/views_generator.rb create mode 100644 lib/generators/templates/views/flashes.html.erb create mode 100644 test/generators/suspenders/views_generator_test.rb diff --git a/NEWS.md b/NEWS.md index 84d8d12f0..54f224388 100644 --- a/NEWS.md +++ b/NEWS.md @@ -9,6 +9,7 @@ Unreleased * Introduce `suspenders:jobs` generator * Introduce `suspenders:lint` generator * Introduce `suspenders:rake` generator +* Introduce `suspenders:views` generator 20230113.0 (January, 13, 2023) diff --git a/README.md b/README.md index b00d16714..9d167c951 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,14 @@ Configures the default Rake task to audit and lint the codebase with [bundler-audit]: https://github.com/rubysec/bundler-audit [standard]: https://github.com/standardrb/standard +### Views + +Configures flash messages, page titles via the [title][] gem, and sets the +document [lang][]. + +[title]: https://github.com/calebhearth/title +[lang]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang + ## Contributing See the [CONTRIBUTING] document. diff --git a/lib/generators/suspenders/views_generator.rb b/lib/generators/suspenders/views_generator.rb new file mode 100644 index 000000000..9fb392a2b --- /dev/null +++ b/lib/generators/suspenders/views_generator.rb @@ -0,0 +1,26 @@ +module Suspenders + module Generators + class ViewsGenerator < Rails::Generators::Base + include Suspenders::Generators::APIAppUnsupported + + desc "Configures flash messages, page titles and the document lang." + source_root File.expand_path("../../templates/views", __FILE__) + + def install_gems + gem "title" + + Bundler.with_unbundled_env { run "bundle install" } + end + + def create_views + copy_file "flashes.html.erb", "app/views/application/_flashes.html.erb" + end + + def update_application_layout + insert_into_file "app/views/layouts/application.html.erb", " <%= render \"flashes\" -%>\n", after: "\n" + gsub_file "app/views/layouts/application.html.erb", //, "\">" + gsub_file "app/views/layouts/application.html.erb", /.*<\/title>/, "<title><%= title %>" + end + end + end +end diff --git a/lib/generators/templates/views/flashes.html.erb b/lib/generators/templates/views/flashes.html.erb new file mode 100644 index 000000000..ae9805a03 --- /dev/null +++ b/lib/generators/templates/views/flashes.html.erb @@ -0,0 +1,7 @@ +<% if flash.any? %> +
+ <% flash.each do |type, message| -%> +
<%= message %>
+ <% end -%> +
+<% end %> diff --git a/test/generators/suspenders/views_generator_test.rb b/test/generators/suspenders/views_generator_test.rb new file mode 100644 index 000000000..0c881eec5 --- /dev/null +++ b/test/generators/suspenders/views_generator_test.rb @@ -0,0 +1,104 @@ +require "test_helper" +require "generators/suspenders/views_generator" + +module Suspenders + module Generators + class ViewsGeneratorTest < Rails::Generators::TestCase + include Suspenders::TestHelpers + + tests Suspenders::Generators::ViewsGenerator + destination Rails.root + setup :prepare_destination + teardown :restore_destination + + test "raises if API only application" do + within_api_only_app do + assert_raises Suspenders::Generators::APIAppUnsupported::Error do + run_generator + end + + assert_file app_root("Gemfile") do |file| + assert_no_match "title", file + end + end + end + + test "creates flash partial" do + expected = <<~ERB + <% if flash.any? %> +
+ <% user_facing_flashes.each do |key, value| -%> +
<%= value %>
+ <% end -%> +
+ <% end %> + ERB + + run_generator + + assert_file app_root("app/views/application/_flashes.html.erb") do |file| + assert_equal expected, file + end + end + + test "includes flash partial in layout" do + run_generator + + assert_file app_root("app/views/layouts/application.html.erb") do |file| + assert_match(/\s{5}<%= render "flashes" -%>$/, file) + end + end + + test "sets the language" do + run_generator + + assert_file app_root("app/views/layouts/application.html.erb") do |file| + assert_match(//, file) + end + end + + test "adds gems to Gemfile" do + expected_output = <<~RUBY + gem "title" + RUBY + + run_generator + + assert_file app_root("Gemfile") do |file| + assert_match(expected_output, file) + end + end + + test "installs gems with Bundler" do + output = run_generator + + assert_match(/bundle install/, output) + end + + test "sets title" do + run_generator + + assert_file app_root("app/views/layouts/application.html.erb") do |file| + assert_match(/<%= title %><\/title>/, file) + end + end + + test "has a custom description" do + assert_no_match(/Description:\n/, generator_class.desc) + end + + private + + def prepare_destination + touch "Gemfile" + backup_file "app/views/layouts/application.html.erb" + end + + def restore_destination + remove_file_if_exists "Gemfile" + remove_file_if_exists "app/views/application/_flashes.html.erb" + restore_file "app/views/layouts/application.html.erb" + end + end + end +end