我正在我的Rails应用中实现(或多或少)WordPress's concept of shortcodes。问题是,当我:yield
我的布局中的任何内容通过视图中的content_for
定义时,它只是空白。因此,不会呈现额外的javascript和标题标记。
换句话说,在布局中调用content_for? :title
会返回false。
这只发布在帖子/索引中,只有在我登录时 才会运行filter_shortcodes
帮助程序。有没有人遇到过这样的事情?
在views / posts / index.html.haml中:
- content_for :script do
= javascript_include_tag '/assets/autoload.js'
- content_for :title do
Blog
...
= render template: 'article-content',
在views / article-content.html.haml中(filter_shortcodes
是Shortcode
模块中定义的辅助函数。):
:plain
#{filter_shortcodes instance.content}
我仍然确信这个问题出现在我的短代码模块中,所以在这里它是不受欢迎的需求:
module Shortcode
def filter_shortcodes content
content.gsub /(?<!\\)\[.+\]/ do |code|
# A shortcode must:
# - be on its own line
# - be [contained within square brackets]
# - be named using only lowercase letters
# If it contains parameters, they must come in the form:
# key="value"
shortcode = /^\s*\[(?<name>[a-z]+) (?<params>.*)\s*\]\s*$/.match code
params_list = shortcode[:params].gsub /"|"/, '"'
param_regexp = /([a-z]+)="([^"]*)"/
shortcode_params = {}
params_list.scan param_regexp do |param|
shortcode_params[param[0].to_sym] = param[1]
end
render_to_string template: "shortcodes/#{shortcode[:name]}",
:locals => shortcode_params, layout: false
end
end
end
答案 0 :(得分:1)
事实证明 是短代码模块的问题。基本上,render_to_string
的行为类似于渲染,并且您只能在控制器操作中对 进行一次调用。因此,因为filter_shortcode
表现为控制器方法(通过模块包含在我的控制器类中),render_to_string
违反了一次性主体。
如果Rails在尝试两次调用render
时执行此操作会很好,但这可能是一个边缘情况吗?
无论如何,我的解决方案是渲染一个单元而不是一个模板。下面的代码有点冗长,但它也更强大,因为它允许您进行特定于短代码的验证:
LIB / shortcode.rb:
module Shortcode
def filter_shortcodes content
# A shortcode must:
# - be on its own line
# - be [contained within square brackets]
# - be named using only lowercase letters
# - be unescaped (not preceded by a "\")
# If it contains parameters, they must come in the form:
# key="value"
regex = /^\s*\[(?<name>[\w]+)\s+(?<params>([^\]]+\s*)*)?\](?<contents>([^\[])*)?(\[(\\|\/)[a-z]+\])?$/
# Here's the negative lookbehind for the escaping \
content.gsub /(?<!\\)\[.+\]/ do |code|
shortcode = regex.match code
# return shortcode[:params]
params = get_params shortcode
params[:contents] = shortcode[:contents] if shortcode[:contents].present?
if ShortcodeCell.method_defined? shortcode[:name]
# just spit out the content if the template doesn't exist
begin
render_cell :shortcode, shortcode[:name], params
rescue ArgumentError => error
"[#{shortcode[:name]} ERROR: #{error.message}]"
end
else
"Unsupported shortcode: #{shortcode[:name]}"
end
end
end
def get_params shortcode
# hack to render quotes...
params_list = shortcode[:params].gsub /"|"/, '"'
params = {}
params_list.scan /([a-z]+)="([^"]*)"/ do |param|
params[param[0].to_sym] = param[1]
end
return params
end
细胞/ shortcode_cell.rb:
class ShortcodeCell < Cell::Rails
def soundcloud args
if args[:url].blank?
raise ArgumentError.new 'missing URL'
end
render locals: args
end
end