grid_fu 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - 2.0.0
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # GridFu
2
2
 
3
- https://github.com/evilmartians/slashadmin/issues/3
3
+ Inspired by discussion at: https://github.com/evilmartians/slashadmin/issues/3.
4
+ Rails table renderer that tries to be flexible.
4
5
 
5
6
  ## Installation
6
7
 
@@ -18,25 +19,143 @@ Or install it yourself as:
18
19
 
19
20
  ## Usage
20
21
 
21
- Do not forget to describe config options.
22
+ Somwhere in your app:
23
+
24
+ ```ruby
25
+ short_table = GridFu.define do
26
+ cell :id
27
+ cell :name
28
+ end
29
+
30
+ puts short_table.to_html(collection, User)
31
+ ```
32
+
33
+ You will see following:
34
+
35
+ ```html
36
+ # <table>
37
+ # <thead><tr><th>Id</th><th>User name</th></tr></thead>
38
+ # <tbody>
39
+ # <tr><td>1</td><td>John Doe</td></tr>
40
+ # <tr>...</tr>
41
+ # </tbody>
42
+ # </table>
43
+ ```
44
+
45
+ ## Full definition
46
+
47
+ ```ruby
48
+ table = GridFu.define do
49
+ html_options class: 'table'
50
+
51
+ header do
52
+ row do
53
+ cell 'Id', html_options: { colspan: 5 }
54
+ cell do
55
+ 'Doctor strangelove'
56
+ end
57
+ end
58
+ end
59
+
60
+ body do
61
+ html_options class: 'sortable'
62
+ row do
63
+ html_options do |member, index|
64
+ { data: { id: member.id, index: index } }
65
+ end
66
+
67
+ cell html_options: ->(member, _) { { data: { value: member.id } } } do |_, index|
68
+ index
69
+ end
70
+ cell :id
71
+ cell :age do |member, _|
72
+ "Dead at #{member.age}"
73
+ end
74
+ cell do |_, index|
75
+ sample_helper_function(index)
76
+ end
77
+ end
78
+
79
+ row html_options: { class: 'small' } do
80
+ tag 'overriden_tr'
81
+
82
+ cell :test do
83
+ "test"
84
+ end
85
+
86
+ cell :age, formatter: :sample_formatter
87
+ end
88
+ end
89
+
90
+ footer do
91
+ row do
92
+ cell html_options: { rowspan: 3 } do
93
+ "On foot"
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ puts table.to_html(collection)
100
+ ```
101
+
102
+ Every element accepts:
103
+ * html_options - to customize default options.
104
+ * override_html_options - to completely override default html options.
105
+ * tag - to change tag name.
106
+
107
+ Default HTML options are:
108
+ * data-id - for tbody/tr.
109
+ * data-key - for tbody/tr/td.
110
+
111
+ Options which are set by blocks accepts:
112
+ * |member, index| - for row and cell inside body element.
113
+ * |collection, klass = nil| - for table, header and footer (and all nested elements)
114
+ * Same for body.
115
+
116
+ Method called with :formatter option accepts value, member and index.
117
+
118
+ You can override default html options for an element with :override_html_options
119
+ option.
120
+
121
+ You can specify two or more rows in body section. All of this rows will be
122
+ rendered for every collection item.
123
+
124
+ ## Global configuration
125
+
126
+ Table elements can be customized at application level.
127
+
128
+ Somewhere in initializer:
129
+
130
+ ```ruby
131
+ GridFu::Table.config.html_options = { class: 'table' }
132
+ GridFu::HeaderRow.config.html_options = proc { |_, resource_class = nil|
133
+ { class: resource_class.name.underscore }
134
+ }
135
+ ```
136
+
137
+ You can use: Table, Header, Body, Footer, HeaderRow, BodyRow, FooterRow,
138
+ HeaderCell, BodyCell, FooterCell.
139
+
140
+ So, you can replace table with ordered list or something you need.
141
+
142
+ ## Partial rendering
143
+
144
+ Could be useful for twitter-style pagination:
145
+
146
+ ```ruby
147
+ table.element_to_html(:header, collection, User)
148
+ table.element_to_html(:body, collection, User)
149
+ table.element_to_html(:footer, collection, User)
150
+ ```
22
151
 
23
152
  ## TODO
24
153
 
25
- 1. Default header & footer if none present.
26
- 2. Render body, footer and header separately
27
- 3. Specs.
28
- 4. Sort?
29
- 5. Nice output.
30
- 6. Default data attrs for everything.
31
- 7. Rowspan
32
- 8. :span
33
- 9. Footer
34
- 10. Header
35
- 11. Base class for footer, header and tbody.
36
- 12. Avoid body block if there's no header/footer.
37
- 13. value: :function cell param
38
- 14. merge_html_options?
39
- 15. Bypass :value param.
154
+ 1. Think about sorting.
155
+ 2. Formatted output.
156
+ 3. Data attrs for everything.
157
+ 4. Authospan.
158
+ 5. :row as parameter.
40
159
 
41
160
  ## Contributing
42
161
 
@@ -17,8 +17,9 @@ Gem::Specification.new do |gem|
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ["lib"]
19
19
 
20
- gem.add_dependency 'active_support', '~> 3'
20
+ gem.add_dependency 'activesupport', '~> 3'
21
21
 
22
22
  gem.add_development_dependency 'rspec'
23
23
  gem.add_development_dependency 'rake'
24
+ gem.add_development_dependency 'rspec-html-matchers'
24
25
  end
@@ -1,15 +1,21 @@
1
- require 'active_support/core_ext/class/attribute_accessors'
2
1
  require 'active_support/core_ext/object/blank'
2
+ require 'active_support/core_ext/object/inclusion'
3
+ require 'active_support/core_ext/string/inflections'
4
+ require 'active_support/core_ext/object/try'
3
5
  require 'active_support/configurable'
4
6
 
5
7
  require 'grid_fu/version'
6
8
  require 'grid_fu/element'
9
+ require 'grid_fu/element/configuration'
10
+ require 'grid_fu/element/rendering'
11
+ require 'grid_fu/element/nesting'
12
+ require 'grid_fu/cells'
13
+ require 'grid_fu/rows'
14
+ require 'grid_fu/sections'
7
15
  require 'grid_fu/table'
8
- require 'grid_fu/row'
9
- require 'grid_fu/body'
10
- require 'grid_fu/cell'
11
16
 
12
17
  module GridFu
18
+ # TODO: Custom table class
13
19
  def define(*args, &block)
14
20
  Table.new(*args, &block)
15
21
  end
@@ -0,0 +1,54 @@
1
+ module GridFu
2
+ class Cell < Element
3
+ def initialize(*args, &block)
4
+ self.value = block
5
+ self.key = args.first if args.first.is_a?(String) or args.first.is_a?(Symbol)
6
+
7
+ # Bypass block evaling: in this case it's not a config but a value formatter
8
+ super(*args, &nil)
9
+ end
10
+
11
+ protected
12
+ attr_accessor :key, :value
13
+ end
14
+
15
+ class BodyCell < Cell
16
+ config.tag = 'td'
17
+
18
+ protected
19
+ def html_content(member, index)
20
+ value = self.value.call(member, index) if self.value.present?
21
+ value ||= member.send(key) if key.present? and member.respond_to?(key)
22
+
23
+ if config.formatter.present?
24
+ value ||= send(config.formatter, key, member, index)
25
+ end
26
+
27
+ value
28
+ end
29
+ end
30
+
31
+ class HeaderCell < Cell
32
+ config.tag = 'th'
33
+
34
+ protected
35
+ def html_content(collection, resource_class = nil)
36
+ return value.call(collection, resource_class) if value.is_a?(Proc)
37
+ if resource_class.respond_to?(:human_attribute_name)
38
+ resource_class.human_attribute_name(key)
39
+ else
40
+ key
41
+ end
42
+ end
43
+ end
44
+
45
+ class FooterCell < Cell
46
+ config.tag = 'td'
47
+
48
+ protected
49
+ def html_content(*args)
50
+ return value.call(*args) if value.is_a?(Proc)
51
+ key
52
+ end
53
+ end
54
+ end
@@ -2,77 +2,10 @@ module GridFu
2
2
  class Element
3
3
  include ActiveSupport::Configurable
4
4
 
5
- def initialize(*args, &block)
6
- instance_exec(&block) if block_given?
7
-
8
- config.html_options ||= {}
9
-
10
- set_options([:tag, :html_options], *args)
11
- end
12
-
13
- def to_html(*args, &block)
14
- tag, html_options = get_options([:tag, :html_options], *args)
15
-
16
- html_options = _to_html_args(html_options)
17
-
18
- html = []
19
- html << "<#{tag}"
20
- if html_options.present?
21
- html << " #{html_options}"
22
- end
23
- html << '>'
24
- if block_given?
25
- html << yield(*args)
26
- else
27
- html << html_content(*args).to_s
28
- end
29
- html << "</#{tag}>"
30
-
31
- html.join
32
- end
33
-
34
- protected
35
- def html_content(*args)
36
- raise NotImplementedError, "Must implement #html_content for #{self.class.name} or pass a block for #to_html"
37
- end
38
-
39
- def set_options(expected, *args)
5
+ def initialize(*args, &definition)
6
+ instance_exec(&definition) if block_given?
40
7
  options = args.extract_options!
41
-
42
- expected.each do |name|
43
- config[name] = options.delete(name) if options.key?(name)
44
- end
45
- end
46
-
47
- def get_options(expected, *args)
48
- expected.map do |name|
49
- config[name].is_a?(Proc) ? config[name].call(*args) : config[name]
50
- end
51
- end
52
-
53
- def self.option_setter(name)
54
- define_method name do |value = nil, &block|
55
- if value.present? || block.present?
56
- config[name] = value || block
57
- end
58
- end
59
- end
60
-
61
- option_setter :tag
62
- option_setter :html_options
63
-
64
- private
65
- def _to_html_args(options, prepend = nil)
66
- options = options || {}
67
- html_args = options.map do |key, value|
68
- if value.is_a?(Hash)
69
- _to_html_args(value, key)
70
- else
71
- key = "#{prepend}-#{key}" if prepend.present?
72
- %{#{key}="#{value}"}
73
- end
74
- end
75
- html_args.join(' ')
8
+ config.merge!(options)
76
9
  end
77
10
  end
78
- end
11
+ end
@@ -0,0 +1,32 @@
1
+ module GridFu
2
+ class Element
3
+ protected
4
+ # Catches a call to configuration option setter.
5
+ #
6
+ # Example:
7
+ # body do
8
+ # html_options { class: 'test' } # Holds such calls
9
+ # end
10
+ def method_missing(method_name, *args, &block)
11
+ return super unless method_name.to_s.in?(config.allowed_configuration_options)
12
+ config[method_name] = args.first || block
13
+
14
+ class_eval do
15
+ define_method method_name do |value|
16
+ config[method_name] = value
17
+ end
18
+ protected method_name
19
+ end
20
+
21
+ config[method_name]
22
+ end
23
+
24
+ config.allowed_configuration_options = %w(
25
+ tag html_options override_html_options
26
+ )
27
+ config.html_options = {}
28
+ config.override_html_options = {}
29
+ config.render_nested_elements = []
30
+ config.tag = nil
31
+ end
32
+ end
@@ -0,0 +1,70 @@
1
+ module GridFu
2
+ class Element
3
+ class << self
4
+ protected
5
+ # Defines DSL method for configuring nested element.
6
+ # If no args/block passed - returns currently defined elements as array.
7
+ #
8
+ # Example:
9
+ # class Table < Element
10
+ # nest :body, Body
11
+ # end
12
+ #
13
+ # table = Table.new do
14
+ # body do
15
+ # (...)
16
+ # end
17
+ # end
18
+ #
19
+ # table.body.first.to_html # <tbody>...</tbody>
20
+ def nest(accessor_name, klass)
21
+ define_method accessor_name do |*args, &block|
22
+ items = instance_variable_get("@#{accessor_name}") || []
23
+ return items if args.blank? && block.blank?
24
+
25
+ value = klass.new(*args, &block)
26
+ items.push(value)
27
+ instance_variable_set("@#{accessor_name}", items)
28
+ value
29
+ end
30
+ protected accessor_name
31
+ end
32
+
33
+ # Defines top-level shortcut DSL method.
34
+ #
35
+ # Example:
36
+ # class Body < Element
37
+ # nest :row, BodyRow
38
+ # end
39
+ #
40
+ # class Table < Element
41
+ # nest_through :body, :row, :cell # Table#cell calls .body.row.cell
42
+ # end
43
+ #
44
+ # table = Table.new do
45
+ # cell :id
46
+ # end
47
+ #
48
+ # table.body.first.row.first.cell.first.to_html # <td data-name="id">...</td>
49
+ def nest_through(*chain)
50
+ nested_method = chain.last
51
+
52
+ define_method nested_method do |*args, &block|
53
+ _get_chained(self, chain.dup, *args, &block)
54
+ end
55
+ end
56
+ end
57
+
58
+ private
59
+ def _get_chained(context, chain, *args, &block)
60
+ key = chain.shift
61
+ if chain.empty?
62
+ context.send(key, *args, &block)
63
+ else
64
+ # Get last defined element, or define new blank
65
+ nested_item = context.send(key).last || context.send(key) { }
66
+ _get_chained(nested_item, chain, *args, &block)
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,73 @@
1
+ module GridFu
2
+ class Element
3
+ # Translates element to html tag.
4
+ def to_html(*args)
5
+ tag, override_html_options, html_options =
6
+ get_options([:tag, :override_html_options, :html_options], *args)
7
+
8
+ raise "Set tag option for #{self.class.name}" if tag.blank?
9
+
10
+ html_options = override_html_options.merge(html_options)
11
+ html_options = _to_html_args(html_options)
12
+
13
+ html = []
14
+
15
+ html << "<#{tag}"
16
+ html << " #{html_options}" if html_options.present?
17
+ html << '>'
18
+
19
+ html << html_content(*args).to_s
20
+
21
+ html << "</#{tag}>"
22
+ html.join
23
+ end
24
+
25
+ def element_to_html(element, *args)
26
+ send(element).map { |item| item.to_html(*args) }.join
27
+ end
28
+
29
+ protected
30
+ # HTML content for element. Renders elements set by :render_nested_elements
31
+ # wrapped by :tag.
32
+ def html_content(*args)
33
+ nested = get_options(:render_nested_elements, *args).first
34
+
35
+ if nested.blank?
36
+ raise "Set render_nested_elements options or override #html_content/#to_html for #{self.class.name}"
37
+ end
38
+
39
+ html = nested.map do |element|
40
+ self.send(element).map { |element| element.to_html(*args) }.join
41
+ end
42
+ html.join
43
+ end
44
+
45
+ private
46
+ # Translates html_options to HTML attributes string. Accepts nested
47
+ # data-attributes.
48
+ #
49
+ # Example:
50
+ # _to_html_args(ref: true, data: { id: 1 }) # ref="true" data-id="1"
51
+ def _to_html_args(options, prepend = nil)
52
+ options = options || {}
53
+ html_args = options.map do |key, value|
54
+ if value.is_a?(Hash)
55
+ _to_html_args(value, key)
56
+ else
57
+ key = "#{prepend}-#{key}" if prepend.present?
58
+ %{#{key}="#{value}"}
59
+ end
60
+ end
61
+ html_args.join(' ')
62
+ end
63
+
64
+ # Gets given option values. If an option is a block - yields it and
65
+ # returns value.
66
+ def get_options(keys, *args)
67
+ keys = Array.wrap(keys)
68
+ keys.map do |name|
69
+ config[name].is_a?(Proc) ? config[name].call(*args) : config[name]
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,32 @@
1
+ module GridFu
2
+ class Row < Element
3
+ attr_reader :cells
4
+
5
+ config.tag = 'tr'
6
+ config.render_nested_elements = %w(cell)
7
+ end
8
+
9
+ class BodyRow < Row
10
+ config.override_html_options = proc { |member, index|
11
+ { data: { id: member.try(:id) } }
12
+ }
13
+
14
+ nest :cell, BodyCell
15
+
16
+ protected
17
+ def html_content(member, index)
18
+ html = cell.map do |cell|
19
+ cell.to_html(member, index)
20
+ end
21
+ html.join
22
+ end
23
+ end
24
+
25
+ class HeaderRow < Row
26
+ nest :cell, HeaderCell
27
+ end
28
+
29
+ class FooterRow < Row
30
+ nest :cell, FooterCell
31
+ end
32
+ end
@@ -0,0 +1,34 @@
1
+ module GridFu
2
+ class Section < Element
3
+ config.render_nested_elements = %w(row)
4
+ end
5
+
6
+ class Body < Section
7
+ config.tag = 'tbody'
8
+
9
+ nest :row, BodyRow
10
+ nest_through :row, :cell
11
+
12
+ protected
13
+ def html_content(collection, resource_class = nil)
14
+ html = collection.map.with_index do |member, index|
15
+ row.map { |row| row.to_html(member, index) }.join(' ')
16
+ end
17
+ html.join
18
+ end
19
+ end
20
+
21
+ class Header < Section
22
+ config.tag = 'thead'
23
+
24
+ nest :row, HeaderRow
25
+ nest_through :row, :cell
26
+ end
27
+
28
+ class Footer < Section
29
+ config.tag = 'tfoot'
30
+
31
+ nest :row, FooterRow
32
+ nest_through :row, :cell
33
+ end
34
+ end
@@ -1,22 +1,13 @@
1
1
  module GridFu
2
2
  class Table < Element
3
- attr_reader :header_content, :body_content, :footer_content
3
+ config.tag = 'table'
4
+ config.render_nested_elements = %w(header body footer)
5
+ config.allowed_configuration_options = %w(tag html_options)
4
6
 
5
- def initialize(*args, &block)
6
- config.tag ||= 'table'
7
+ nest :header, Header
8
+ nest :body, Body
9
+ nest :footer, Footer
7
10
 
8
- super
9
- end
10
-
11
- protected
12
- def html_content(collection, resource_class = nil)
13
- body_content.to_html(collection, resource_class)
14
- end
15
-
16
- def body(*args, &block)
17
- self.body_content = Body.new(*args, &block)
18
- end
19
-
20
- attr_writer :header_content, :body_content, :footer_content
11
+ nest_through :body, :row, :cell
21
12
  end
22
- end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module GridFu
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -1,15 +1,75 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'Configuration' do
4
- subject { sample_table }
3
+ describe 'Grid' do
4
+ context 'defined fully' do
5
+ subject { sample_table_full_described }
5
6
 
6
- it 'should set provided html options correctly' do
7
- #subject.config.tag.should == 'table'
8
- #subject.config.html_options.should == {}
9
- #subject.body_content.config.tag.should == 'tbody'
10
- #subject.body_content.rows.first.config.html_options.should == { class: 'odd' }
11
- #subject.body_content.rows.last.config.html_options.should be_kind_of(Proc)
7
+ it 'should render correctly' do
8
+ subject.should have_tag 'table', with: { class: 'table' }, count: 1 do
9
+ with_tag 'thead', count: 1 do
10
+ with_tag 'th', text: 'Doctor strangelove', count: 1
11
+ with_tag 'th', text: 'Id', count: 1
12
+ end
12
13
 
13
- # puts subject.to_html(sample_collection)
14
+ with_tag 'tbody', with: { class: 'sortable' }, count: 1 do
15
+ sample_collection.each_with_index do |member, index|
16
+ with_tag "tr[data-id='#{member.id}'][data-index='#{index}']"
17
+
18
+ with_tag 'td', with: { 'data-value' => member.id }, text: index, count: 1
19
+ with_tag 'td', text: member.id, count: 1
20
+ with_tag 'td', text: "Dead at #{member.age}", count: 1
21
+ with_tag 'td', text: "I hope this helps #{index}", count: 1
22
+
23
+ with_tag 'overriden_tr'
24
+
25
+ with_tag 'td', text: member.age
26
+ end
27
+ end
28
+
29
+ with_tag 'tfoot', count: 1 do
30
+ with_tag 'td', text: 'On foot', count: 1
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ context 'partial rendering' do
37
+ subject do
38
+ sample_table_full_described_definition.element_to_html(:body, sample_collection)
39
+ end
40
+
41
+ it 'should render header, footer, body separately' do
42
+ subject.should_not have_tag 'thead'
43
+ subject.should_not have_tag 'tfoot'
44
+
45
+ subject.should have_tag 'tbody'
46
+ subject.should have_tag 'tr'
47
+ subject.should have_tag 'td'
48
+ end
49
+ end
50
+
51
+ context 'defined shortly' do
52
+ subject { sample_table_short }
53
+
54
+ it 'should render correctly' do
55
+ subject.should have_tag 'table', count: 1 do
56
+ with_tag 'tbody', count: 1
57
+ with_tag 'thead', count: 1
58
+ with_tag 'tr', count: 4
59
+ end
60
+ end
61
+ end
62
+
63
+ context 'with active record objects' do
64
+ subject { sample_table_active_record }
65
+
66
+ it 'should get right headings from active record' do
67
+ subject.should have_tag 'thead', count: 1 do
68
+ with_tag 'th', text: 'Humanized id', count: 1
69
+ with_tag 'th', text: 'Humanized age', count: 1
70
+ end
71
+
72
+ subject.should_not have_tag 'tfoot'
73
+ end
14
74
  end
15
75
  end
@@ -3,7 +3,7 @@ require 'bundler/setup'
3
3
 
4
4
  require 'grid_fu'
5
5
  require 'support/sample_table'
6
+ require 'rspec-html-matchers'
6
7
 
7
8
  RSpec.configure do |config|
8
- # some (optional) config here
9
9
  end
@@ -1,41 +1,109 @@
1
1
  require 'ostruct'
2
2
 
3
+ class ActiveRecordMock
4
+ def self.human_attribute_name(name)
5
+ "Humanized #{name.to_s}"
6
+ end
7
+ end
8
+
3
9
  def sample_collection
4
10
  [
5
- OpenStruct.new(id: 1, age: 27, value: 'Jim Morrison'),
6
- OpenStruct.new(id: 1, age: 70, value: 'William Blake'),
7
- OpenStruct.new(id: 1, age: 89, value: 'Robert Lee Frost')
11
+ OpenStruct.new(id: 10, age: 27, value: 'Jim Morrison'),
12
+ OpenStruct.new(id: 20, age: 70, value: 'William Blake'),
13
+ OpenStruct.new(id: 30, age: 89, value: 'Robert Lee Frost')
8
14
  ]
9
15
  end
10
16
 
11
- def sample_helper_function
12
- "I hope this helps"
17
+ def sample_helper_function(arg)
18
+ "I hope this helps #{arg}"
19
+ end
20
+
21
+ def sample_formatter(key, member, index)
22
+ "Formatter for #{member[key]}"
13
23
  end
14
24
 
15
- def sample_table
25
+ def sample_table_full_described_definition
16
26
  GridFu.define do
27
+ html_options class: 'table'
28
+
29
+ header do
30
+ row do
31
+ cell 'Id', html_options: { colspan: 5 }
32
+ cell do
33
+ 'Doctor strangelove'
34
+ end
35
+ end
36
+ end
37
+
17
38
  body do
18
39
  html_options class: 'sortable'
19
40
  row do
20
41
  html_options do |member, index|
21
- { data: { id: member.id } }
42
+ { data: { id: member.id, index: index } }
22
43
  end
23
44
 
24
- cell html_options: ->(value, _, _) { { data: { value: value } } } do |_, _, index|
45
+ cell html_options: ->(member, _) { { data: { value: member.id } } } do |_, index|
25
46
  index
26
47
  end
27
48
  cell :id
28
- cell :age do |value, _, _|
29
- "Dead at #{value}"
49
+ cell :age do |member, _|
50
+ "Dead at #{member.age}"
30
51
  end
31
- cell do
32
- sample_helper_function
52
+ cell do |_, index|
53
+ sample_helper_function(index)
33
54
  end
34
55
  end
35
56
 
36
57
  row html_options: { class: 'small' } do
37
- tag 'div'
58
+ tag 'overriden_tr'
59
+
60
+ cell :test do
61
+ "test"
62
+ end
63
+
64
+ cell :age, formatter: :sample_formatter
65
+ end
66
+ end
67
+
68
+ footer do
69
+ row do
70
+ cell html_options: { rowspan: 3 } do
71
+ "On foot"
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ def sample_table_full_described
79
+ sample_table_full_described_definition.to_html(sample_collection)
80
+ end
81
+
82
+ def sample_table_short
83
+ table = GridFu.define do
84
+ header do
85
+ cell 'Id'
86
+ cell 'Age'
87
+ end
88
+
89
+ cell :id
90
+ cell :age
91
+ end
92
+ table.to_html(sample_collection)
93
+ end
94
+
95
+ def sample_table_active_record
96
+ table = GridFu.define do
97
+ header do
98
+ cell :id
99
+ cell :age
100
+ cell "Custom string"
101
+ cell do
102
+ "Custom block"
38
103
  end
39
104
  end
105
+ cell :id
106
+ cell :age
40
107
  end
108
+ table.to_html(sample_collection, ActiveRecordMock)
41
109
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grid_fu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,10 +9,10 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-04 00:00:00.000000000 Z
12
+ date: 2013-03-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: active_support
15
+ name: activesupport
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
@@ -59,6 +59,22 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec-html-matchers
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
62
78
  description: HTML table generator
63
79
  email:
64
80
  - gzigzigzeo@gmail.com
@@ -68,16 +84,20 @@ extra_rdoc_files: []
68
84
  files:
69
85
  - .gitignore
70
86
  - .rspec
87
+ - .travis.yml
71
88
  - Gemfile
72
89
  - LICENSE.txt
73
90
  - README.md
74
91
  - Rakefile
75
92
  - grid_fu.gemspec
76
93
  - lib/grid_fu.rb
77
- - lib/grid_fu/body.rb
78
- - lib/grid_fu/cell.rb
94
+ - lib/grid_fu/cells.rb
79
95
  - lib/grid_fu/element.rb
80
- - lib/grid_fu/row.rb
96
+ - lib/grid_fu/element/configuration.rb
97
+ - lib/grid_fu/element/nesting.rb
98
+ - lib/grid_fu/element/rendering.rb
99
+ - lib/grid_fu/rows.rb
100
+ - lib/grid_fu/sections.rb
81
101
  - lib/grid_fu/table.rb
82
102
  - lib/grid_fu/version.rb
83
103
  - spec/grid_spec.rb
@@ -97,7 +117,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
97
117
  version: '0'
98
118
  segments:
99
119
  - 0
100
- hash: 4608333944381045103
120
+ hash: -31517031954940795
101
121
  required_rubygems_version: !ruby/object:Gem::Requirement
102
122
  none: false
103
123
  requirements:
@@ -106,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
126
  version: '0'
107
127
  segments:
108
128
  - 0
109
- hash: 4608333944381045103
129
+ hash: -31517031954940795
110
130
  requirements: []
111
131
  rubyforge_project:
112
132
  rubygems_version: 1.8.25
@@ -1,28 +0,0 @@
1
- module GridFu
2
- class Body < Element
3
- attr_reader :rows
4
-
5
- def initialize(*args, &block)
6
- self.rows = []
7
-
8
- config.tag ||= 'tbody'
9
-
10
- super
11
- end
12
-
13
- protected
14
- def html_content(collection, resource_class)
15
- html = collection.map do |member|
16
- rows.map.with_index { |row, index| row.to_html(member, index) }.join(' ')
17
- end
18
- html.join
19
- end
20
-
21
- protected
22
- def row(*args, &block)
23
- self.rows << Row.new(&block)
24
- end
25
-
26
- attr_writer :rows
27
- end
28
- end
@@ -1,32 +0,0 @@
1
- module GridFu
2
- class Cell < Element
3
- def initialize(*args, &block)
4
- self.value = block
5
- self.key = args.first if args.first.is_a?(String) or args.first.is_a?(Symbol)
6
-
7
- config.tag = 'td'
8
- super(*args, &nil) # Bypass block evaling: in this case it's a value formatter
9
- end
10
-
11
- attr_reader :key, :value
12
-
13
- def to_html(member, index, &block)
14
- member_value = member.send(key) if key.present? and member.respond_to?(key)
15
- member_value = if value.is_a?(Proc)
16
- value.call(member_value, member, index)
17
- else
18
- member_value.to_s
19
- end
20
-
21
- super(*[member_value, member, index], &block)
22
- end
23
-
24
- protected
25
- def html_content(value, member, index)
26
- value
27
- end
28
-
29
- attr_writer :value
30
- attr_writer :key
31
- end
32
- end
@@ -1,26 +0,0 @@
1
- module GridFu
2
- class Row < Element
3
- attr_reader :cells
4
-
5
- def initialize(*args, &block)
6
- self.cells = []
7
- config.tag = 'tr'
8
-
9
- super
10
- end
11
-
12
- protected
13
- def html_content(member, index)
14
- html = cells.map do |cell|
15
- cell.to_html(member, index)
16
- end
17
- html.join
18
- end
19
-
20
- def cell(*args, &block)
21
- self.cells << Cell.new(*args, &block)
22
- end
23
-
24
- attr_writer :cells
25
- end
26
- end