Module: Gridder

Defined in:
lib/gridder.rb,
lib/gridder/version.rb

Constant Summary collapse

GRID_HEADER_SPLITTER =
"::"
VERSION =
"0.0.10"

Class Method Summary collapse

Class Method Details

.for(data, *opts) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/gridder.rb', line 5

def self.for(data, *opts)
  config = {:empty_message => "Empty"}
  config = config.update(opts.extract_options!)

  titles = config[:body].map{|e| e[:title].to_s}
  max_level = titles.map{|e| e.split(GRID_HEADER_SPLITTER).size}.max

  header_rows = []
  max_level.times{header_rows << []}

  titles.each do |title_token|
    if title_token.blank?
      header_rows[0] << {:title => title_token, :rowspan => max_level}
      next
    end

    splitted_title_token = title_token.split(GRID_HEADER_SPLITTER)

    splitted_title_token.each_with_index do |title, idx|
      level = idx+1
      _hash = {}
      _hash[:title] = title

      if (splitted_title_token.size == level) && (max_level > level)
        _hash[:rowspan] = (max_level - idx)
      end

      if (header_rows[idx].last || {})[:title] != _hash[:title]
        header_rows[idx] << _hash
      else
        a = header_rows[idx].last
        a[:colspan] ||= 1
        a[:colspan] += 1
      end

    end
  end

  builder = Nokogiri::HTML::Builder.new do |doc|

    doc.table(config[:table]) do
      doc.thead(config[:thead]) do
        header_rows.each do |row|
          doc.tr do
            row.each do |cell|
              doc.th(:rowspan => cell[:rowspan], :colspan => cell[:colspan]){ doc.cdata cell[:title] }
            end
          end
        end
      end
      doc.tbody(config[:tbody]) do
        if data.blank?
          doc.tr{ doc.td(config[:empty_message], :class => :empty, :colspan => config[:body].size) }
        else
          data.each do |record|
            tr_config = if config[:tr].blank? && record.is_a?(ActiveRecord::Base)
                          {:id => ActionController::RecordIdentifier.dom_id(record)}
                        elsif config[:tr].is_a?(Proc)
                          config[:tr].arity.zero? ? config[:tr].call : config[:tr].call(record)
                        elsif config[:tr].is_a?(Symbol)
                          record.send(config[:tr])
                        else
                          config[:tr]
                        end

            doc.tr(tr_config) do
              config[:body].each do |cell|
                r, opts = Gridder.get_cell_content(cell, record)
                doc.td(opts){doc.cdata r}
              end
            end
          end
        end

      end

      if config[:footer] && config[:footer].is_a?(Array)
        doc.tfoot(config[:tfooter]) do
          doc.tr do
            config[:footer].each do |cell|
              r, opts = Gridder.get_cell_content(cell, data)
              doc.td(opts){doc.cdata r}
            end
          end
        end
      end
    end
  end

  builder.doc.root.to_html.html_safe
end