登录时content_for为空白

时间:2013-10-10 17:38:02

标签: ruby-on-rails

我正在我的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_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

1 个答案:

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

        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