2011-09-26 19 views
3

我正在开发一个应用程序,该应用程序在许多不同的区域显示表格数据,并且我发现自己经常反复使用相同的HTML表结构。例如,一个特定的表看起来像这样:在Rails 3.1中,如何创建一个使用块样式格式的HTML表生成器

%table.zebra-striped#user-table{ :cellspacing => "0" } 
    %colgroup 
    %col{:id => "email"} 
    %col{:id => "username"} 
    %col{:id => "sign-in-count"} 
    %col{:id => "last-sign-in-at"} 

    %thead 
    %tr 
     %th{:id => "email-head", :scope => "col"} E-mail 
     %th{:id => "username-head", :scope => "col"} Username 
     %th{:id => "sign-in-count-head", :scope => "col"} Sign Ins 
     %th{:id => "last-sign-in-at-head", :scope => "col"} Last Sign In 

    %tbody 
    - @users.each do |user| 
     %tr{ :class => zebra } 
     %td 
      =h user.email 
     %td 
      =h user.username 
     %td 
      =h user.sign_in_count 
     %td 
      =h user.last_sign_in_at 

理想情况下,我想创造某种辅助方法,在那里我可以这样做:

= custom_table_for @users do 
    = column :email 
    = column :username do |user| 
    = link_to user.username, user_path(user) 
    = column "Sign Ins", :sign_in_count 
    = column :last_sign_in_at 

这样我可以改变的格式列中的数据和列标题名称(如果我对默认值不满意),但会为我生成表格。

我想我可以创建一个正常的帮手,但我不得不使用数组,我不知道如何包括自定义数据格式每列。

active_admin有类似这样的,你可以在这里看到的东西:http://activeadmin.info/docs/3-index-pages/index-as-table.html

任何线索或想法,将不胜感激。

回答

4

我只是想出了这一点:

的几点:

  • 线@columns = []是复位,所以你可以把它不止一次。
  • custom_table_for中的yield调用您传递它的块。
  • 列方法中的block被存储并在custom_table_for中调用(如果已设置)。

我还包括一个示例类以显示使用情况。

请注意我这样做一个Rails应用程序之外,你几乎可以肯定要使用http://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-content_tag代替p "<table>"的这仅是为了示例的目的,当你在控制台中运行它。

module TableHelper 
    def custom_table_for(items) 
    @columns = [] 
    yield 
    p "<table>" 
     @columns.each do |c| 
     p "<th>#{c[:value]}</th>" 
     end 

     items.each do |e| 
     p "<tr>" 
     @columns.each do |c| 
      e[c[:name]] = c[:block].call(e[c[:name]]) if c[:block] 
      p "<td>#{e[c[:name]]}</td>" 
     end 
     p "</tr>" 
     end 
    p "</table>" 
    end 

    def column(name, value = nil, &block) 
    value = name unless value 
    @columns << {:name => name, :value => value, :block => block} 
    end 
end 

class ExampleTable 
    include TableHelper 
    def test 
    @users = [{:email => "Email 1", :username => "Test User"}, {:email => "Email 2", :username => "Test User 2"}] 
    custom_table_for @users do 
     column :email, "Email" 
     column :username do |user| 
     user.upcase 
     end 
    end 
    end 
end 

et = ExampleTable.new 
et.test 

UPDATE

我迁移这轨使用content_tags

module TableHelper 
    def custom_table_for(items) 
    @columns = [] 
    yield 


    content_tag :table do 
     thead + tbody(items) 
    end 

    end 

    def thead 
    content_tag :thead do 
     content_tag :tr do 
     @columns.each do |c| 
      concat(content_tag(:th, c[:value])) 
     end 
     end 
    end 
    end 

    def tbody(items) 
    content_tag :tbody do 
     items.each { |e| 
     concat(content_tag(:tr){ 
      @columns.each { |c| 
      e[c[:name]] = c[:block].call(e[c[:name]]) if c[:block] 
      concat(content_tag(:td, e[c[:name]])) 
      } 
     }) 
     } 
    end 
    end 

    def column(name, value = nil, &block) 
    value = name unless value 
    @columns << {:name => name, :value => value, :block => block} 
    end 
end 
+0

真棒,迫不及待地让这个旋转。我想我可以将模块粘贴在/lib/table_helper.rb文件中,然后我必须在我的应用程序视图中明确包含TableHelper模块以使用它。 – jklina

+0

嗯,很好的问题,我想你可以将它包含在你的应用程序帮助器中? – Gazler

+0

当我回家时,我会玩弄它。我现在肯定有足够的领先优势。 – jklina

0

恭维@ gazler的回应,这里有一个方法,使一个单一的resource--列的表一个用于属性名称,第二列用于它们的值:

module TableHelper 

    @resource = nil 

    def simple_table_for(resource) 
    @resource = resource 

    content_tag :table do 
     content_tag :tbody do 
     yield 
     end 
    end 
    end 

    def row(key, label = nil, &block) 
    if key.is_a? String 
     label = key 
    end 

    content_tag(:tr) { 
     concat content_tag :td, label || key.capitalize 
     concat content_tag(:td){ 
      if block_given? 
      yield 
      else 
      @resource.send(key) 
      end 
     } 
    } 
    end 
end 
相关问题