Я добавил новый ответ для версии 3.2.X. Этот ответ действителен для <~ 3.0.1. </p>
Я пришел к этому вопросу, пытаясь найти возможностьнесколько откатов на вид.Например, если мой продукт может иметь белую маркировку, и, в свою очередь, если мой партнер по белой марке может продать спонсорство, тогда мне нужен каскад просмотров на каждой странице, подобный этому:
- Представление спонсора:.sponsor_html
- Представление партнера: .partner_html
- Представление по умолчанию: .html
Ответ Джо на простое удаление .html работает (очень хорошо), если вытолько на один уровень выше значения по умолчанию, но в реальных приложениях мне в некоторых случаях требовалось 5 уровней.
Похоже, в любом случае не было возможности реализовать такое короткое исправление обезьяны в том же духе, что и у Джереми.
Ядро Rails делает несколько довольно широких предположений о том, что вам нужен только один формат и что он сопоставляется с одним расширением (по умолчанию используется расширение NO).
Мне нужно было одно решение, котороебудет работать для всех элементов представления - макеты, шаблоны и частичные.
Попытка сделать это больше в соответствии с соглашением, я придумал следующее.
# app/config/initializers/resolver.rb
module ActionView
class Base
cattr_accessor :extension_fallbacks
@@extension_fallbacks = nil
end
class PathResolver < Resolver
private
def find_templates_with_fallbacks(name, prefix, partial, details)
fallbacks = Rails.application.config.action_view.extension_fallbacks
format = details[:formats].first
unless fallbacks && fallbacks[format]
return find_templates_without_fallbacks(name, prefix, partial, details)
end
deets = details.dup
deets[:formats] = fallbacks[format]
path = build_path(name, prefix, partial, deets)
query(path, EXTENSION_ORDER.map {|ext| deets[ext] }, details[:formats])
end
alias_method_chain :find_templates, :fallbacks
end
end
# config/application.rb
config.after_initialize do
config.action_view.extension_fallbacks = {
html: [:sponsor_html, :partner_html, :html],
mobile: [:sponsor_mobile, :partner_mobile, :sponsor_html, :partner_html, :html]
}
# config/initializers/mime_types.rb
register_alias 'text/html', :mobile
# app/controllers/examples_controller.rb
class ExamplesController
respond_to :html, :mobile
def index
@examples = Examples.all
respond_with(@examples)
end
end
Примечание: Iдействительно видел комментарии вокруг alias_method_chain, и первоначально сделал вызов super в соответствующем месте.На самом деле это называется ActionView :: Resolver # find_templates (что вызывает исключение NotImplemented), а не ActionView :: PathResolver # find_templates в некоторых случаях.Я не был достаточно терпелив, чтобы отследить почему.Я подозреваю, что это из-за того, что это закрытый метод.
Плюс, Rails в настоящее время не сообщает alias_method_chain как устаревший.Просто этот пост делает.
Мне не нравится этот ответ, поскольку он включает в себя очень хрупкую реализацию вокруг вызова find_templates.В частности, предположение, что у вас есть только ОДИН формат, но это предположение сделано повсеместно в запросе шаблона.
После 4 дней попыток решить эту проблему и прочесать весь стек запроса шаблонаэто лучшее, что я могу придумать.