我在名为partials
的文件夹中有几个部分,我使用render 'partials/name_of_my_partial'
将它们渲染到我的视图中,这没关系。
无论如何,是否可以设置方式而不是使用render 'name_of_my_partial'
并且rails自动检查此partials
文件夹?
现在,我遇到Missing partial
错误。
答案 0 :(得分:10)
在rails 3.0中这是一个挑战,但在调查中我发现在rails 3.1中,它们改变了路径查找的工作方式,使其更加简单。 (我不知道他们改变了什么确切的版本,它可能早得多)。
在3.1中,这是相对简单的,因为它们引入了一种向路径查找发送多个前缀的方法。它们通过实例方法_prefixes
检索。
对于所有控制器来说,通过简单地覆盖基本控制器(或者包含在基本控制器中的模块中,无论哪个)都可以很容易地使用任意前缀。
所以在3.1.x中(查找使用多个前缀):
class ApplicationController
...
protected
def _prefixes
@_prefixes_with_partials ||= super | %w(partials)
end
end
在此更改之前,单个前缀用于查找,这使得这更加复杂。这可能不是最好的方法,但我过去解决了这个问题,试图通过我的“后备”前缀查找相同的路径来避免丢失模板错误。
在3.0.x中(其中lookup使用单个路径前缀)
# in an initializer
module YourAppPaths
extend ActiveSupport::Concern
included do
# override the actionview base class method to wrap its paths with your
# custom pathset class
def self.process_view_paths(value)
value.is_a?(::YourAppPaths::PathSet) ?
value.dup : ::YourAppPaths::PathSet.new(Array.wrap(value))
end
end
class PathSet < ::ActionView::PathSet
# our simple subclass of pathset simply rescues and attempts to
# find the same path under "partials", throwing out the original prefix
def find(path, prefix, *args)
super
rescue ::ActionView::MissingTemplate
super(path, "partials", *args)
end
end
end
ActionView::Base.end(:include, YourAppPaths)
答案 1 :(得分:2)
我还没有找到关于这个主题的其他资源,所以我在这里发布了我的努力。
在 Rails 3.2 + (也在4.2中测试)中,可以从控制器操作中访问和修改lookup_context.prefixes
。因此,修改模板和模板的查找部分前缀包括您可以执行此操作的另一个路径:
class MyObjectsController < ApplicationController
def show
# WARNING: Keep reeding for issues with this approach!
unless lookup_context.prefixes.first == "partials"
lookup_context.prefixes.prepend "partials"
end
end
end
这样,如果 app / views / partials / 文件夹中有 show.html.erb 模板,则会呈现该模板。对于 show.html.erb 中引用的任何部分内容也是如此。
方法lookup_context
返回类型为ActionView::LookupContext
的对象,该对象负责保存在ActionView
中查找模板所需的所有信息。值得注意的是,它还允许您访问lookup_context.view_paths
,不在此问题中要求的内容,但声音应该是这样。
为所有将来的请求缓存lookup_context.prefixes
数组的修改。因此,为了无故障地使用它,最好确保我们删除我们添加的任何前缀。
不确定。对于我自己的项目,我已经创建了一个模块,我可以将其包含在需要此功能的任何控制器中(或者只是将其包含在ApplicationController
中)。这是我的代码:
# Helper methods for adding ActionView::LookupContext prefixes on including
# controllers. The lookup_context.prefixes collection is persisted on cached
# controllers, so these helpers take care to remove the passed-in prefixes
# after calling the block.
#
# @example Expected Usage:
# around_action only: :show do |_, block|
# prepend_lookup_context_prefixes("my_optional_name_space/my_objects", &block)
# end
#
# around_action only: %i[index edit update] do |_, block|
# append_penultimate_lookup_context_prefixes("my_optional_name_space/my_objects", &block)
# end
module PrefixesHelper
# Prepends the passed in prefixes to the current `lookup_context.prefixes`
# array, calls the block, then removes the prefixes.
#
# @param [Array<String>] prefixes
def prepend_lookup_context_prefixes(*prefixes, &block)
lookup_context.prefixes.prepend(*prefixes)
block.call
remove_lookup_context_prefixes(*prefixes, index: 0)
end
# Sets the penultimate (2nd-to-last) prefixes in the current
# `lookup_context.prefixes` array, calls the block, then removes the prefixes.
#
# @param [Array<String>] prefixes
def append_penultimate_lookup_context_prefixes(*prefixes, &block)
lookup_context.prefixes.insert(-2, *prefixes)
block.call
remove_lookup_context_prefixes(*prefixes.reverse, index: -2)
end
# Removes the passed in prefixes from the current `lookup_context.prefixes`
# array. If index is passed in, then will only remove prefixes found at the
# specified index in the array.
#
# @param [Array<String>] prefixes
# @param [Integer] index
def remove_lookup_context_prefixes(*prefixes, index: nil)
prefixes.each do |prefix|
if index
if lookup_context.prefixes[index] == prefix
lookup_context.prefixes.delete_at(index)
end
else
lookup_context.prefixes.delete(prefix)
end
end
end
end
如本模块中的注释所述,此模块的预期用法是通过控制器中的around_filter
调用来调用其中包含的方法。这样,模块将在控制器操作产生后删除它添加的任何前缀。
例如:
around_filter only: :show do |_, block|
prepend_lookup_context_prefixes("my_optional_name_space/my_objects", &block)
end
或者:
around_filter only: %i[index edit update] do |_, block|
append_penultimate_lookup_context_prefixes("my_optional_name_space/my_objects", &block)
end
我还将此处发布的PrefixesHelper
模块包含在一个gem中,我用它来为我的Rails应用添加一些不错的扩展名。如果您也想使用它,请参阅此处:https://github.com/pdobb/core_extensions
答案 2 :(得分:0)
注意:由于一些奇怪的行为以及与multi_fetch_fragments宝石不兼容,我已放弃了这种方法
如果您想为STI集合添加局部元素前缀,我会提供以下猴子补丁(用于Rails 3.2,Ruby 2.2 +)。
config / initializers / partial_renderer_prefix.rb
module ActionView
class PartialRenderer
def merge_prefix_into_object_path(prefix, object_path)
# Begin monkey patch
if @options.key?(:prefix)
prefixes = [@options[:prefix]]
return (prefixes << object_path).join("/")
end
# End monkey patch
if prefix.include?(?/) && object_path.include?(?/)
prefixes = []
prefix_array = File.dirname(prefix).split('/')
object_path_array = object_path.split('/')[0..-3] # skip model dir & partial
prefix_array.each_with_index do |dir, index|
break if dir == object_path_array[index]
prefixes << dir
end
(prefixes << object_path).join("/")
else
object_path
end
end
end
end
在视图中,像这样使用它:
<%= render @order_items, prefix: 'orders/timeline' %>
每个STI模型都有app/views/orders/timeline/product_order_items/_product_order_item.html.erb
和app/views/orders/timeline/subscription_order_items/_subscription_order_item.html.erb
零件的地方。