Skip to content

Commit

Permalink
ction View: Fallback to existing partial when possible
Browse files Browse the repository at this point in the history
Closes [#50844][]

Motivation / Background
---

A controller declared in the top-level module can render a top-level
Active Model instance whose partial is declared in the root view
directory (like `articles/_article.html.erb`).

A controller scoped within a module can render an Active Model instance
whose partial is similarly scoped within view directory (like
`scoped/articles/_article.html.erb`).

A controller scoped within a module cannot render an Active Model
instance whose partial is declared in the root view directory (like
`articles/_article.html.erb`), despite the absence of a similarly scoped
partial.

This is intended behavior that's powered by
[`config.action_view.prefix_partial_path_with_controller_namespace =
true`][prefix_partial_path_with_controller_namespace] (`true` by
default).

This change was introduced in March of 2012 as part of [#5625][].

Detail
---

As a consumer of Action View, my intuition is that the lookup would
fallback, in the same way that a controller that inherits from
`ApplicationController` could define its own view, then rely on fallback
to render an `app/views/application` partial.

This commit modifies the behavior to gracefully fall back to the
root-level view partial.

Checklist
---

Before submitting the PR make sure the following are checked:

* [x] This Pull Request is related to one change. Changes that are unrelated should be opened in separate PRs.
* [x] Commit message has a detailed description of what changed and why. If this PR fixes a related issue include it in the commit message. Ex: `[Fix #issue-number]`
* [x] Tests are added or updated if you fix a bug or add a feature.
* [x] CHANGELOG files are updated for the changed libraries if there is a behavior change or additional feature. Minor bug fixes and documentation changes should not be included.

[#59844]: #50844
[prefix_partial_path_with_controller_namespace]: https://guides.rubyonrails.org/configuring.html#config-action-view-prefix-partial-path-with-controller-namespace
[#5625]: #5625
  • Loading branch information
seanpdoyle committed Apr 20, 2024
1 parent 284baa1 commit 334de31
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 2 deletions.
30 changes: 30 additions & 0 deletions actionview/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,33 @@
* Fallback to rendering partial without controller namespace prefix when available

When `config.action_view.prefix_partial_path_with_controller_namespace =
true` and a root-level partial exists, fallback to rendering the partial:

```erb
<%# app/views/articles/_article.html.erb %>
Rendered
```

```ruby
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def show
render partial: Article.find(params[:id])
# => "Rendered"
end
end

# app/controllers/scoped/articles_controller.rb
class Scoped::ArticlesController < ApplicationController
def show
render partial: Article.find(params[:id])
# => "Rendered"
end
end
```

*Sean Doyle*

* Add queries count to template rendering instrumentation

```
Expand Down
4 changes: 2 additions & 2 deletions actionview/lib/action_view/path_set.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def find(path, prefixes, partial, details, details_key, locals)
end

def find_all(path, prefixes, partial, details, details_key, locals)
search_combinations(prefixes) do |resolver, prefix|
search_combinations(*prefixes, path.pluralize) do |resolver, prefix|
templates = resolver.find_all(path, prefix, partial, details, details_key, locals)
return templates unless templates.empty?
end
Expand All @@ -55,7 +55,7 @@ def exists?(path, prefixes, partial, details, details_key, locals)
end

private
def search_combinations(prefixes)
def search_combinations(*prefixes)
prefixes = Array(prefixes)
prefixes.each do |prefix|
paths.each do |resolver|
Expand Down
21 changes: 21 additions & 0 deletions actionview/test/actionpack/controller/render_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,27 @@ def test_render_to_string_inline
assert_equal "Hello world!", @response.body
end

def test_unnested_rendering_with_fallback
@controller = Fun::GamesController.new
def @controller.hello_world
render partial: ::Customer.new("Rendered"), locals: { greeting: "Hello" }
end

get :hello_world
assert_equal "Hello: Rendered", @response.body
end

def test_unnested_rendering_without_fallback
@controller = Fun::GamesController.new
def @controller.hello_world
render partial: Post.new
end

assert_raises ActionView::MissingTemplate, match: "Missing partial fun/posts/_post" do
get :hello_world
end
end

# :ported:
def test_nested_rendering
@controller = Fun::GamesController.new
Expand Down

0 comments on commit 334de31

Please sign in to comment.