2013-10-10 36 views
2

我在我的Rails應用中實施(或多或少)WordPress's concept of shortcodes。問題是,當我在視圖中通過content_for定義的任何佈局中的:yield時,它只是空白。所以額外的JavaScript和標題標籤不會呈現。content_for登錄時爲空

換句話說,在佈局中調用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', 

而在視圖/物品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 
+0

我們不需要看到你的filter_shortcodes模塊,但是產生內容的佈局很好看。 – MrYoshiji

+0

好的,我編輯了我的問題以包含佈局 – acobster

回答

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