2017-02-02 30 views
0

我正在嘗試將Rails 2.3應用程序更新到更新的Rails版本(4/5)。
我有一個方法,打印一個HTML表使用列表作爲輸入,並且調用者可以自定義行的顯示。我還搜尋了一些現有的做類似的寶石,但他們沒有我需要的所有要求。所以我必須做這個工作。該代碼是在Rails的一種方法中使用多個content_tag

def model_table_2(collection, headers, options = {}, &proc) 
    options.reverse_merge!({ 
     :id   => nil, 
     :class  => nil, 
     :style  => nil, 
     :placeholder => 'Empty', 
     :caption  => nil, 
     :summary  => nil, 
     :footer  => nil 
     }) 
    placeholder_unless !collection.empty?, options[:placeholder] do 
     html_opt = options.slice(:id, :class, :style, :summary) 
     content_tag(:table, html_opt) do 
     table_sections = [] 
     table_sections << content_tag(:caption, options[:caption]).to_s if options[:caption] 
     table_sections << content_tag(:thead, 
      content_tag(:tr, 
       headers.collect { |h| 
       concat(content_tag(:th, h)) 
       } 
      ) 
     ) 
     if options[:footer] 
      table_sections << content_tag(:tfoot, 
      content_tag(:tr, content_tag(:th, concat(options[:footer]), :colspan => headers.size)) 
     ) 
     end 
     table_sections << content_tag(:tbody, 
      collection.each_with_index.collect do |row, row_index| 
      concat(
       proc.call(row, cycle('odd', 'even'), row_index) 
      ) 
      end.join 
     ) 
     table_sections.join 
     end 
    end 
    end 

    def placeholder(message = t('general.empty'), options = {}, &proc) 
    # set default options 
    o = { :class => 'placeholder', :tag => 'p' }.merge(options) 

    # wrap the results of the supplied block, or just print out the message 
    if proc 
     t = o.delete(:tag) 
     concat tag(t, o, true), proc.binding 
     yield 
     concat "</#{t}>", proc.binding 
    else 
     content_tag o.delete(:tag), message, o 
    end 
    end 

    def placeholder_unless(condition, *args, &proc) 
    condition ? proc.call : concat(placeholder(args), proc.binding) 
    end 

在視圖文件,我這樣稱呼它:

<% table_cols = ["No.", "Name"] %> 
<% obj_list = [{active: true, name: 'First'}, {active: true, name: 'Second'}, {active: false, name: 'Last'}, nil] %> 
<%= model_table_2(obj_list, table_cols, {:class=>'table table-bordered', :caption=>'Model Table Test', :footer=>'The Footer'}) do |record, klass, row_index| -%> 
    <% if !record.nil? then %> 
    <% content_tag :tr, :class => klass + (record[:active] ? '' : ' text-muted') do -%> 
     <td><%= row_index+1 -%></td> 
     <td><%= record[:name] %></td> 
    <% end %> 
    <% else %> 
    <% content_tag :tr, :class => klass do -%> 
     <td style="text-align:center;">*</td> 
     <td>render form</td> 
    <% end %> 
    <% end %> 
<% end %> 

但輸出是不是我所期望的:

<table class="table table-bordered"> 
    <th>No.</th> 
    <th>Name</th> 
    The Footer 
    <tr class="even"> 
     <td>1</td> 
     <td>First</td> 
    </tr> 
    <tr class="odd"> 
     <td>2</td> 
     <td>Second</td> 
    </tr> 
    <tr class="even text-muted"> 
     <td>3</td> 
     <td>Last</td> 
    </tr> 
    <tr class="odd"> 
     <td>*</td> 
     <td>render form</td> 
    </tr> 
</table> 

正如你所看到的,一些的標籤丟失,如captionthead,tbodytfoot。我想這是因爲content_tag調用是嵌套的。我之前嘗試過沒有table_sections陣列,但它也沒有工作。

此外,列表爲空時出現錯誤,代碼將轉至placeholder...方法。

+0

嵌套'content_tag'應該可以工作。看着你的代碼,我會爭辯說,有多個partials將是一個更清潔,更簡單的解決方案。 – phoet

回答

0

這是一個奇怪的content_tag怪癖,但如果你築巢它們,你需要use a concat on each return in the inner tags。否則,你只需得到最後一個返回的字符串,而內層標籤就會消失在以太網中。可悲的是,根據我的經驗,我發現複雜的嵌套不值得進入輔助方法。

也許,更好的方法是用decorator模式,rails偏分列或使用類似cells gem的東西來幹掉html。

+0

你的回答真的幫了我。我通過爲每個放入'table_sections'的元素使用一個'concat'來實現它:'table_sections << concat(content_tag(...'當數組obj_list爲空時,你能幫我解決嗎?I得到_wrong參數個數(2代表1)_但我不知道什麼方法有這個問題 –

+0

錯誤消息棧跟蹤說什麼? – engineerDave

+0

這是因爲'concat'現在有一個參數,並且在過去它有2。 –

相關問題