Skip to content

Commit

Permalink
Fixes #22
Browse files Browse the repository at this point in the history
A PathResolver method that extracts the handler and format was broken
since the re-arrangement of the extensions. It was no longer properly
extracting the format of the template. The symptom was the layout file
was no longer being looked up properly (#22).

The sequence is as follows:
 - look up the template users/index
 - take the template and extract the handler and format, the format is
seen as null
 - set the template format as the new format to use
 - lookup the layout file with the new format to match the template
 - no layout file is found

The fix is to monkey patch the
`ActionView::PathResolver#extract_handler_and_format` method. It will
now make an additional attempt to lookup the types with another part of
the extension if it exists.

It is not ideal to monkey patch Rails methods, but in this case I think
it is necessary. The `extract_handler_and_format` method uses knowledge
of the constants set about the ‘registered details’ to extract the
extension data and since we’ve modified the registered details, we need
to modify the function as well.
  • Loading branch information
bwillis committed Jan 16, 2014
1 parent d5cf6a0 commit d060e1d
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
49 changes: 49 additions & 0 deletions lib/versioncake/view_additions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,55 @@
# it to the default pattern
ActionView::PathResolver::DEFAULT_PATTERN.replace ":prefix/:action{.:locale,}{.:formats,}{.:versions,}{.:handlers,}"

# The default extract handler expects that the handler is the last extension and
# the format is the next one. Since we are replacing the DEFAULT_PATTERN, we need to
# make sure that we extract the format from the correct position.
#
# The version may be stuck inbetween the format and the handler. This is actually pretty tricky
# because the version is optional and the locale is optional-which means when there are 3 'pieces'
# it may be the locale, format and handler or the format, version and handler. To check this, we will
# try one additional time if there are more pieces, which should cover all the cases:
#
# Cases:
# 1: assume version is in the extension, pieces = ['html','erb']
# 2: assume version is in the extension, pieces = ['html','v1','erb']
# 3: assume version is in the extension, pieces = ['en','html','erb']
# 4: assume version is in the extension, pieces = ['en','html','v1','erb']
#
def extract_handler_and_format(path, default_formats)
if ActionPack::VERSION::MAJOR == 4
pieces = File.basename(path).split(".")
pieces.shift

extension = pieces.pop
unless extension
message = "The file #{path} did not specify a template handler. The default is currently ERB, " \
"but will change to RAW in the future."
ActiveSupport::Deprecation.warn message
end

handler = ActionView::Template.handler_for_extension(extension)
format = get_format_from_pieces(pieces, ActionView::Template::Types)

[handler, format]
else # Rails < 4.1
pieces = File.basename(path).split(".")
pieces.shift
handler = ActionView::Template.handler_for_extension(pieces.pop)
format = get_format_from_pieces(pieces, Mime)
[handler, format]
end
end

# If there are still pieces and we didn't find a valid format, we may
# have a version in the extension, so try one more time to pop the format.
def get_format_from_pieces(pieces, format_list)
format = pieces.last && format_list[pieces.pop]
if format.nil? && pieces.length > 0
format = pieces.last && format_list[pieces.pop]
end
format
end
end

ActionView::Template.class_eval do
Expand Down
27 changes: 27 additions & 0 deletions test/unit/view_additions_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require './test/test_helper'

class ViewAdditionsTest < ActiveSupport::TestCase
setup do
@resolver = ActionView::PathResolver.new
end

test "it retrieves the correct handler and format when only hanlder and format are present" do
handler, format = @resolver.extract_handler_and_format('application.html.erb', nil)
assert_equal format.to_s, 'text/html'
end

test "it retrieves the correct handler and format when only hanlder, format and version are present" do
handler, format = @resolver.extract_handler_and_format('application.json.v1.jbuilder', nil)
assert_equal format.to_s, 'application/json'
end

test "it retrieves the correct handler and format when only hanlder, format and locale are present" do
handler, format = @resolver.extract_handler_and_format('application.en.json.jbuilder', nil)
assert_equal format.to_s, 'application/json'
end

test "it retrieves the correct handler and format when only hanlder, format, locale and version are present" do
handler, format = @resolver.extract_handler_and_format('application.en.json.v1.jbuilder', nil)
assert_equal format.to_s, 'application/json'
end
end

0 comments on commit d060e1d

Please sign in to comment.