2

我正在我的 Rails 应用程序中实现(或多或少)WordPress 的简码概念。问题是,当我在视图中:yield定义布局content_for中的任何内容时,它只是空白。所以额外的 javascript 和 title 标签不会被渲染。

换句话说,content_for? :title在布局中调用返回 false。

这只会发生在帖子/索引中,并且仅在我登录时 filter_shortcodes助手运行时。有没有人遇到过这样的事情?

在视图/帖子/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_shortcodesShortcode模块中定义的辅助函数):

: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 /&quot;|"/, '"'

            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
4

1 回答 1

1

原来这简码模块的问题。基本上,它的render_to_string行为类似于渲染,并且您只能在控制器操作中调用一次因此,因为filter_shortcode它表现为控制器方法(通过将模块包含在我的控制器类中),render_to_string违反了一次性原则。

如果 Rails 像您尝试调用render两次时那样执行此操作会很好,但也许这是一个边缘情况?

无论如何,我的解决方案是渲染一个单元格而不是一个模板。下面的代码有点冗长,但它也更健壮,因为它允许您进行特定于短代码的验证:

库/简码.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 /&quot;|"/, '"'

        params = {}
        params_list.scan /([a-z]+)="([^"]*)"/ do |param|
            params[param[0].to_sym] = param[1]
        end

        return params
    end

细胞/简码_cell.rb:

class ShortcodeCell < Cell::Rails
    def soundcloud args
        if args[:url].blank?
            raise ArgumentError.new 'missing URL'
        end

        render locals: args
    end
end
于 2013-11-06T20:10:20.873 回答