From c5efbbbccb8fabb25d95f6c5758225f31b3879ba Mon Sep 17 00:00:00 2001 From: Edward Rudd Date: Wed, 20 Sep 2017 13:00:01 -0400 Subject: Fix checking for template variants when using the ActionView::FixtureResolver --- actionview/CHANGELOG.md | 4 ++++ actionview/lib/action_view/testing/resolvers.rb | 4 ++-- actionview/test/template/testing/fixture_resolver_test.rb | 10 ++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index abb97804e1..be67aff543 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -6,6 +6,10 @@ *John Hawthorn* +* Fix `ActionView::FixtureResolver` so that it handles template variants correctly. + + *Edward Rudd* + ## Rails 6.0.0.beta3 (March 11, 2019) ## diff --git a/actionview/lib/action_view/testing/resolvers.rb b/actionview/lib/action_view/testing/resolvers.rb index 11ae9f731c..a97fb71b26 100644 --- a/actionview/lib/action_view/testing/resolvers.rb +++ b/actionview/lib/action_view/testing/resolvers.rb @@ -25,8 +25,8 @@ module ActionView #:nodoc: def query(path, exts, _, locals) query = +"" - EXTENSIONS.each_key do |ext| - query << "(" << exts[ext].map { |e| e && Regexp.escape(".#{e}") }.join("|") << "|)" + EXTENSIONS.each do |ext, prefix| + query << "(" << exts[ext].map { |e| e && Regexp.escape("#{prefix}#{e}") }.join("|") << "|)" end query = /^(#{Regexp.escape(path)})#{query}$/ diff --git a/actionview/test/template/testing/fixture_resolver_test.rb b/actionview/test/template/testing/fixture_resolver_test.rb index afb6686dac..a90440574e 100644 --- a/actionview/test/template/testing/fixture_resolver_test.rb +++ b/actionview/test/template/testing/fixture_resolver_test.rb @@ -17,4 +17,14 @@ class FixtureResolverTest < ActiveSupport::TestCase assert_equal "arbitrary/path", templates.first.virtual_path assert_nil templates.first.format end + + def test_should_match_templates_with_variants + resolver = ActionView::FixtureResolver.new("arbitrary/path.html+variant.erb" => "this text") + templates = resolver.find_all("path", "arbitrary", false, locale: [], formats: [:html], variants: [:variant], handlers: [:erb]) + assert_equal 1, templates.size, "expected one template" + assert_equal "this text", templates.first.source + assert_equal "arbitrary/path", templates.first.virtual_path + assert_equal [:html], templates.first.formats + assert_equal ["variant"], templates.first.variants + end end -- cgit v1.2.3 From 90a8ce645085e475f668643195652b7518a7b9cc Mon Sep 17 00:00:00 2001 From: Edward Rudd Date: Tue, 15 Jan 2019 15:06:59 -0500 Subject: add documentation about variants --- guides/CHANGELOG.md | 5 +++++ guides/source/layouts_and_rendering.md | 39 ++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md index beace1ed6f..798354550b 100644 --- a/guides/CHANGELOG.md +++ b/guides/CHANGELOG.md @@ -1,3 +1,8 @@ +* Added documentation about the `variants` option to `render` + + *Edward Rudd* + + ## Rails 6.0.0.beta3 (March 11, 2019) ## * No changes. diff --git a/guides/source/layouts_and_rendering.md b/guides/source/layouts_and_rendering.md index a2ae4ea59e..43cc958cb1 100644 --- a/guides/source/layouts_and_rendering.md +++ b/guides/source/layouts_and_rendering.md @@ -296,6 +296,7 @@ Calls to the `render` method generally accept five options: * `:location` * `:status` * `:formats` +* `:variants` ##### The `:content_type` Option @@ -417,6 +418,44 @@ render formats: [:json, :xml] If a template with the specified format does not exist an `ActionView::MissingTemplate` error is raised. +##### The `:variants` Option + +This tells rails to look for template variations of the same format. +You can specify a list of variants by passing the `:variants` option with a symbol or an array. + +An example of use would be this. + +```ruby +# called in HomeController#index +render variants: [:mobile, :desktop] +``` + +With this set of variants Rails will look for the following set of templates and use the first that exists. + +- `app/views/home/index.html+mobile.erb` +- `app/views/home/index.html+desktop.erb` +- `app/views/home/index.html.erb` + +If a template with the specified format does not exist an `ActionView::MissingTemplate` error is raised. + +Instead of setting the variant on the render call you may also set it on the request object in your controller action. + +```ruby +def index + request.variant = determine_variant +end + +private + +def determine_variant + variant = nil + # some code to determine the variant(s) to use + variant = :mobile if session[:use_mobile] + + variant +end +``` + #### Finding Layouts To find the current layout, Rails first looks for a file in `app/views/layouts` with the same base name as the controller. For example, rendering actions from the `PhotosController` class will use `app/views/layouts/photos.html.erb` (or `app/views/layouts/photos.builder`). If there is no such controller-specific layout, Rails will use `app/views/layouts/application.html.erb` or `app/views/layouts/application.builder`. If there is no `.erb` layout, Rails will use a `.builder` layout if one exists. Rails also provides several ways to more precisely assign specific layouts to individual controllers and actions. -- cgit v1.2.3