watu_table_builder 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in table_builder.gemspec
4
+ gemspec
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Petrik de Heus
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,165 @@
1
+ {<img src="https://secure.travis-ci.org/watu/table_builder.png" />}[http://travis-ci.org/watu/table_builder]
2
+
3
+ == About this fork
4
+
5
+ I forked https://github.com/jchunky/table_builder to convert it into a gem using Bundler and most importantly, having a
6
+ gemspec so it can easily be added to a Gemfile.
7
+
8
+ Then we also added some features (check the commit history).
9
+
10
+ If you have changes you thing should be merged back into mainstream, feel free to send me a pull request, I'd like to
11
+ try to maintain as complete as possible branch and then maybe release it as a gem (maybe with another name).
12
+
13
+ = TableBuilder
14
+
15
+ Rails builder for creating tables and calendars inspired by ActionView's FormBuilder, updated for Rails 3.0beta
16
+ This is a fork of Petrik de Heus plugin for earlier versions of Rails. Note the new idiomatic use of "<%=" for the
17
+ table_for and calendar_for functions.
18
+
19
+ == Examples
20
+
21
+ table_for has methods for each tag used in a table (<table>, <thead> <tr>, <td>, etc.)
22
+
23
+ A basic example would look like this:
24
+
25
+ @front_men = [FrontMan.new(1, 'David St. Hubbins'), FrontMan.new(2, 'David Lee Roth')]
26
+
27
+ <%= table_for(@front_men) do |t| %>
28
+ <%= t.head do %>
29
+ <%= t.r do %>
30
+ <%= t.h('Id') %>
31
+ <%= t.h('Name') %>
32
+ <% end %>
33
+ <% end %>
34
+ <%= t.body do |front_man| %>
35
+ <%= t.r do %>
36
+ <%= t.d(h(front_man.id)) %>
37
+ <%= t.d(h(front_man.name)) %>
38
+ <% end %>
39
+ <% end %>
40
+ <% end %>
41
+
42
+ You can pass an array to the head method:
43
+
44
+ <%= t.head('Id', 'Name') %>
45
+
46
+
47
+ The body and r method can be combined for easier usage:
48
+
49
+ <%= t.body_r do |front_man| %>
50
+ <%= t.d(h(front_man.id)) %>
51
+ <%= t.d(h(front_man.name)) %>
52
+ <% end %>
53
+
54
+ You can also pass blocks to the d and h methods for more flexibility:
55
+
56
+ <%= t.d(:class => 'name') do %>
57
+ <%= link_to(h(front_man.name), front_man_url(front_man)) %>
58
+ <% end %>
59
+
60
+ All tag methods are rails tag methods, so they can have extra html options.
61
+
62
+ @drummers = [Drummer.new(1, 'John "Stumpy" Pepys'), Drummer.new(2, 'Eric "Stumpy Joe" Childs')]
63
+
64
+ <%= table_for(@drummers, :html => { :id => 'spinal_tap', :class => 'drummers'}) do |t| %>
65
+ <%= t.body_r(:class => 'row') do |e| %>
66
+ <%= t.d(h(e.id), :title => 'id') %>
67
+ <%= t.d(h(e.name)) %>
68
+ <% end %>
69
+ <% end %>
70
+
71
+ ... which produces the following html:
72
+
73
+ <table class="drummers" id="spinal_tap">
74
+ <tbody>
75
+ <tr class="row">
76
+ <td title="id">1</td>
77
+ <td>John &quot;Stumpy&quot; Pepys</td>
78
+ </tr>
79
+ <tr class="row">
80
+ <td title="id">2</td>
81
+ <td>Eric &quot;Stumpy Joe&quot; Childs</td>
82
+ </tr>
83
+ </tbody>
84
+ </table>
85
+
86
+ You can customize the table by creating your own TableBuilder:
87
+
88
+ <%= table_for(@drummers, :builder => PagedTableBuilder) do |t| %>
89
+
90
+
91
+ == Calendar Table
92
+
93
+ calendar_for creates a table like table_for.
94
+ All objects get sorted per day of the month
95
+
96
+ A basic example would look like this:
97
+
98
+ @tasks = Task.this_month
99
+
100
+ <%= calendar_for(@tasks) do |t| %>
101
+ <%= t.head('mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun') %>
102
+ <%= t.day do |day, tasks| %>
103
+ <%= day.day %>
104
+ <% tasks.each do |task| %>
105
+ <%= h(task.name) %>
106
+ <% end %>
107
+ <% end %>
108
+ <% end %>
109
+
110
+ To show a different month you can pass the :year and :month options:
111
+
112
+ <%= calendar_for(@tasks, :year => 2009, :month => 1) do |t| %>
113
+
114
+ To highlight a different day you can pass the :today option:
115
+
116
+ <%= calendar_for(@tasks, :today => Date.civil(2008, 12, 26)) do |t| %>
117
+
118
+ By default the :date method is called on the objects for sorting.
119
+ To use another method you can pass the :day_method option:
120
+
121
+ <%= t.day(:day_method => :calendar_date) do |day, tasks| %>
122
+
123
+ If you want to add id's to your td tag you can pass a pattern:
124
+
125
+ <%= t.day(:id => 'day_%d') do |day, tasks| %>
126
+
127
+ To have a header at the begining of each row:
128
+
129
+ <%= calendar_for(@tasks, :row_header => true) do |t| %>
130
+
131
+ and then in your block you get nil as the list of objects and the first day of thet upcoming week. For example:
132
+
133
+ <%= calendar_for(@tasks) do |t| %>
134
+ <%= t.day do |day, tasks| %>
135
+ <% if tasks.nil? %>
136
+ <%= day.cweek %>
137
+ <% else %>
138
+ <%= day.day %>
139
+ <% tasks.each do |task| %>
140
+ <%= h(task.name) %>
141
+ <% end %>
142
+ <% end %>
143
+ <% end %>
144
+ <% end %>
145
+ == Install
146
+
147
+ Inside your Gemfile:
148
+
149
+ gem "table_builder", :git => "git://github.com/watu/table_builder.git"
150
+
151
+ == Contributing
152
+
153
+ Document any new options and verify the documentation looks correct by running:
154
+
155
+ yard server --reload
156
+
157
+ and going to http://localhos:8808
158
+
159
+ == Contributors
160
+
161
+ Petrik de Heus, Sean Dague, F. Kocherga, John Duff, Andrew C. Greenberg, Jason Cheong-Kee-You, J. Pablo Fernández.
162
+
163
+ Original Work Copyright (c) 2008 Petrik de Heus, released under the MIT license.
164
+ Fork revisions Copyright (c) 2010 Andrew C. Greenberg, released under the MIT license.
165
+ Fork revisions Copyright (c) 2012 Carrousel Apps Ltd (Watu), released under the MIT license.
@@ -0,0 +1,13 @@
1
+ require "rake"
2
+ require "rake/testtask"
3
+ require "bundler/gem_tasks"
4
+
5
+ desc "Default: run unit tests."
6
+ task :default => :test
7
+
8
+ desc "Test the table_builder plugin."
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << "lib"
11
+ t.pattern = "test/**/*_test.rb"
12
+ t.verbose = true
13
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'table_builder'
@@ -0,0 +1,6 @@
1
+ require "table_builder/table_builder.rb"
2
+ require "table_builder/calendar_helper.rb"
3
+ require "table_builder/version.rb"
4
+
5
+ ActionView::Base.send :include, TableHelper
6
+ ActionView::Base.send :include, CalendarHelper
@@ -0,0 +1,169 @@
1
+ module CalendarHelper
2
+ # Generates a calendar (as a table) for an array of objects placing each of them on the corresponding date.
3
+ #
4
+ # **TODO: fully document this method, the current documentation is far from done.**
5
+ #
6
+ # @param [Hash] options extra options
7
+ #
8
+ # :row_header if true, each row will have an extra cell at the beginning, as a row header. A typical usage would be
9
+ # to output week numbers. When the block is called, it will get the date that would normally be passed to the
10
+ # first day of the week (to give you some context) and a nil list of objects (and that's how you recognize it as
11
+ # a header, because empty days get an empty array, not nil).
12
+ def calendar_for(objects, *args)
13
+ raise ArgumentError, "Missing block" unless block_given?
14
+ options = args.last.is_a?(Hash) ? args.pop : {}
15
+ html_options = options[:html]
16
+ builder = options[:builder] || CalendarBuilder
17
+ calendar = options[:calendar] || Calendar
18
+ content_tag(:table, nil, html_options) do
19
+ yield builder.new(objects || [], self, calendar, options)
20
+ end
21
+ end
22
+
23
+ class CalendarBuilder < TableHelper::TableBuilder
24
+ def initialize(objects, template, calendar, options)
25
+ super(objects, template, options)
26
+ @calendar = calendar.new(options)
27
+ @today = options[:today] || Time.now
28
+ @row_header = options[:row_header] || false
29
+ end
30
+
31
+ def day(*args)
32
+ raise ArgumentError, "Missing block" unless block_given?
33
+ options = options_from_hash(args)
34
+ day_method = options.delete(:day_method) || :date
35
+ id_pattern = options.delete(:id)
36
+ tbody do
37
+ @calendar.objects_for_days(@objects, day_method).to_a.sort{|a1, a2| a1.first <=> a2.first }.each do |o|
38
+ key, array = o
39
+ day, objects = array
40
+ concat(tag(:tr, options, true)) if(day.wday == @calendar.first_weekday)
41
+ if @row_header && day.wday == @calendar.first_weekday
42
+ row_header_options = td_options(day, id_pattern)
43
+ row_header_options[:class] ||= ""
44
+ row_header_options[:class] << " row_header"
45
+ concat(tag(:td, row_header_options, true))
46
+ yield(day, nil)
47
+ concat("</td>")
48
+ end
49
+ concat(tag(:td, td_options(day, id_pattern), true))
50
+ yield(day, objects)
51
+ concat('</td>')
52
+ concat('</tr>') if(day.wday == @calendar.last_weekday)
53
+ end
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def objects_for_days
60
+ @calendar.objects_for_days(@objects)
61
+ end
62
+
63
+ def td_options(day, id_pattern)
64
+ options = {}
65
+ css_classes = []
66
+ css_classes << 'today' if day.strftime("%Y-%m-%d") == @today.strftime("%Y-%m-%d")
67
+ css_classes << 'notmonth' if day.month != @calendar.month
68
+ css_classes << 'weekend' if day.wday == 0 or day.wday == 6
69
+ css_classes << 'future' if day > @today.to_date
70
+ options[:class] = css_classes.join(' ') unless css_classes.empty?
71
+ options[:id] = day.strftime(id_pattern) if id_pattern
72
+ options
73
+ end
74
+
75
+ end
76
+
77
+ class Calendar
78
+ attr_accessor :first_weekday, :last_weekday, :month
79
+
80
+ # :first lets you set the first day to start the calendar on (default is the first day of the given :month and :year).
81
+ # :first => :today will use Date.today
82
+ # :last lets you set the last day of the calendar (default is the last day of the given :month and :year).
83
+ # :last => :thirty will show 30 days from :first
84
+ # :last => :week will show one week
85
+ def initialize(options={})
86
+ @year = options[:year] || Time.now.year
87
+ @month = options[:month] || Time.now.month
88
+ @first_day_of_week = options[:first_day_of_week] || 0
89
+ @first_weekday = first_day_of_week(@first_day_of_week)
90
+ @last_weekday = last_day_of_week(@first_day_of_week)
91
+
92
+ @first = options[:first]==:today ? Date.today : options[:first] || Date.civil(@year, @month, 1)
93
+
94
+ if options[:last] == :thirty_days || options[:last] == :thirty
95
+ @last = @first + 30
96
+ elsif options[:last] == :one_week || options[:last] == :week
97
+ @last = @first
98
+ else
99
+ @last = options[:last] || Date.civil(@year, @month, -1)
100
+ end
101
+
102
+ end
103
+
104
+ def each_day
105
+ first_day.upto(last_day) do |day|
106
+ yield(day)
107
+ end
108
+ end
109
+
110
+ def last_day
111
+ last = @last
112
+ while(last.wday % 7 != @last_weekday % 7)
113
+ last = last.next
114
+ end
115
+ last
116
+ end
117
+
118
+ def first_day
119
+ first = @first - 6
120
+ while(first.wday % 7 != (@first_weekday) % 7)
121
+ first = first.next
122
+ end
123
+ first
124
+ end
125
+
126
+ def objects_for_days(objects, day_method)
127
+ unless @objects_for_days
128
+ @objects_for_days = {}
129
+ days.each{|day| @objects_for_days[day.strftime("%Y-%m-%d")] = [day, []]}
130
+ objects.each do |o|
131
+ date = o.send(day_method.to_sym).strftime("%Y-%m-%d")
132
+ if @objects_for_days[date]
133
+ @objects_for_days[date][1] << o
134
+ end
135
+ end
136
+ end
137
+ @objects_for_days
138
+ end
139
+
140
+ def days
141
+ unless @days
142
+ @days = []
143
+ each_day{|day| @days << day}
144
+ end
145
+ @days
146
+ end
147
+
148
+ def mjdays
149
+ unless @mjdays
150
+ @mdays = []
151
+ each_day{|day| @days << day}
152
+ end
153
+ @days
154
+ end
155
+
156
+ def first_day_of_week(day)
157
+ day
158
+ end
159
+
160
+ def last_day_of_week(day)
161
+ if day > 0
162
+ day - 1
163
+ else
164
+ 6
165
+ end
166
+ end
167
+ end
168
+
169
+ end
@@ -0,0 +1,126 @@
1
+ module TableHelper
2
+
3
+ def table_for(objects, *args)
4
+ raise ArgumentError, "Missing block" unless block_given?
5
+ options = args.last.is_a?(Hash) ? args.pop : {}
6
+ html_options = options[:html]
7
+ builder = options[:builder] || TableBuilder
8
+
9
+ content_tag(:table, html_options) do
10
+ yield builder.new(objects || [], self, options)
11
+ end
12
+ end
13
+
14
+ class TableBuilder
15
+ include ::ActionView::Helpers::TagHelper
16
+
17
+ def initialize(objects, template, options)
18
+ raise ArgumentError, "TableBuilder expects an Enumerable object but found #{objects.inspect}" unless objects.respond_to? :each
19
+ @objects, @template, @options = objects, template, options
20
+ end
21
+
22
+ def head(*args)
23
+ if block_given?
24
+ concat(tag(:thead, options_from_hash(args), true))
25
+ yield
26
+ concat('</thead>')
27
+ else
28
+ @num_of_columns = args.size
29
+ content_tag(:thead,
30
+ content_tag(:tr,
31
+ args.collect { |c| content_tag(:th, c.html_safe)}.join('').html_safe
32
+ )
33
+ )
34
+ end
35
+ end
36
+
37
+ def head_r(*args)
38
+ raise ArgumentError, "Missing block" unless block_given?
39
+ options = options_from_hash(args)
40
+ head do
41
+ concat(tag(:tr, options, true))
42
+ yield
43
+ concat('</tr>')
44
+ end
45
+ end
46
+
47
+ def body(*args)
48
+ raise ArgumentError, "Missing block" unless block_given?
49
+ options = options_from_hash(args)
50
+ tbody do
51
+ @objects.each { |c| yield(c) }
52
+ end
53
+ end
54
+
55
+ def body_r(*args)
56
+ raise ArgumentError, "Missing block" unless block_given?
57
+ options = options_from_hash(args)
58
+ tbody do
59
+ @objects.each { |c|
60
+ concat(tag(:tr, options, true))
61
+ yield(c)
62
+ concat('</tr>'.html_safe)
63
+ }
64
+ end
65
+ end
66
+
67
+ def r(*args)
68
+ raise ArgumentError, "Missing block" unless block_given?
69
+ options = options_from_hash(args)
70
+ tr(options) do
71
+ yield
72
+ end
73
+ end
74
+
75
+ def h(*args)
76
+ if block_given?
77
+ concat(tag(:th, options_from_hash(args), true))
78
+ yield
79
+ concat('</th>')
80
+ else
81
+ content = args.shift
82
+ content_tag(:th, content, options_from_hash(args))
83
+ end
84
+ end
85
+
86
+ def d(*args)
87
+ if block_given?
88
+ concat(tag(:td, options_from_hash(args), true))
89
+ yield
90
+ concat('</td>')
91
+ else
92
+ content = args.shift
93
+ content_tag(:td, content, options_from_hash(args))
94
+ end
95
+ end
96
+
97
+
98
+ private
99
+
100
+ def options_from_hash(args)
101
+ args.last.is_a?(Hash) ? args.pop : {}
102
+ end
103
+
104
+ def concat(tag)
105
+ @template.safe_concat(tag)
106
+ ""
107
+ end
108
+
109
+ def content_tag(tag, content, *args)
110
+ options = options_from_hash(args)
111
+ @template.content_tag(tag, content, options)
112
+ end
113
+
114
+ def tbody
115
+ concat('<tbody>')
116
+ yield
117
+ concat('</tbody>')
118
+ end
119
+
120
+ def tr options
121
+ concat(tag(:tr, options, true))
122
+ yield
123
+ concat('</tr>')
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,3 @@
1
+ module TableBuilder
2
+ VERSION = "0.3.0"
3
+ end
@@ -0,0 +1,248 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper.rb')
2
+
3
+ class CalendarHelperTest < ActionView::TestCase
4
+ include ActionView::Helpers::TextHelper
5
+ include ActionView::Helpers::TagHelper
6
+ include CalendarHelper
7
+ attr_accessor :output_buffer
8
+
9
+ def setup
10
+ @events = [Event.new(3, 'Jimmy Page', Date.civil(2008, 12, 26)),
11
+ Event.new(4, 'Robert Plant', Date.civil(2008, 12, 26))]
12
+ end
13
+
14
+ def test_calendar_for
15
+ output = calendar_for(@events, :html => { :id => 'id', :style => 'style', :class => 'class'}) do |t|
16
+ end
17
+ expected = %(<table id="id" style="style" class="class">) <<
18
+ %(</table>)
19
+ assert_dom_equal expected, output
20
+ end
21
+
22
+ def test_calendar_for_without_an_array
23
+ self.output_buffer = ''
24
+ assert_raises(ArgumentError) do
25
+ calendar_for('a') {|t| }
26
+ end
27
+ end
28
+
29
+ def test_calendar_for_with_empty_array
30
+ output = calendar_for([], :year=> 2008, :month => 12) do |c|
31
+ c.day do |day, events|
32
+ concat(events.collect{|e| e.id}.join)
33
+ end
34
+ end
35
+ expected = %(<table>) <<
36
+ %(<tbody>) <<
37
+ %(<tr><td class="notmonth weekend"></td><td></td><td></td><td></td><td></td><td></td><td class="weekend"></td></tr>) <<
38
+ %(<tr><td class="weekend"></td><td></td><td></td><td></td><td></td><td></td><td class="weekend"></td></tr>) <<
39
+ %(<tr><td class="weekend"></td><td></td><td></td><td></td><td></td><td></td><td class="weekend"></td></tr>) <<
40
+ %(<tr><td class="weekend"></td><td></td><td></td><td></td><td></td><td></td><td class="weekend"></td></tr>) <<
41
+ %(<tr><td class="weekend"></td><td></td><td></td><td></td><td class="notmonth"></td><td class="notmonth"></td><td class="notmonth weekend"></td></tr>) <<
42
+ %(</tbody>) <<
43
+ %(</table>)
44
+ assert_dom_equal expected, output
45
+ end
46
+
47
+ def test_calendar_for_with_events
48
+ output = calendar_for(@events, :year=> 2008, :month => 12) do |c|
49
+ c.day do |day, events|
50
+ content = events.collect{|e| e.id}.join
51
+ concat("(#{day.day})#{content}")
52
+ end
53
+ end
54
+ expected = %(<table>) <<
55
+ %(<tbody>) <<
56
+ %(<tr><td class="notmonth weekend">(30)</td><td>(1)</td><td>(2)</td><td>(3)</td><td>(4)</td><td>(5)</td><td class="weekend">(6)</td></tr>) <<
57
+ %(<tr><td class="weekend">(7)</td><td>(8)</td><td>(9)</td><td>(10)</td><td>(11)</td><td>(12)</td><td class="weekend">(13)</td></tr>) <<
58
+ %(<tr><td class="weekend">(14)</td><td>(15)</td><td>(16)</td><td>(17)</td><td>(18)</td><td>(19)</td><td class="weekend">(20)</td></tr>) <<
59
+ %(<tr><td class="weekend">(21)</td><td>(22)</td><td>(23)</td><td>(24)</td><td>(25)</td><td>(26)34</td><td class="weekend">(27)</td></tr>) <<
60
+ %(<tr><td class="weekend">(28)</td><td>(29)</td><td>(30)</td><td>(31)</td><td class="notmonth">(1)</td><td class="notmonth">(2)</td><td class="notmonth weekend">(3)</td></tr>) <<
61
+ %(</tbody>) <<
62
+ %(</table>)
63
+ assert_dom_equal expected, output
64
+ end
65
+
66
+ def test_calendar_for_sets_css_classes
67
+ output = calendar_for([], :year=> 2008, :month => 12, :today => Date.civil(2008, 12, 15)) do |c|
68
+ c.day do |day, events|
69
+ concat(events.collect{|e| e.id}.join)
70
+ end
71
+ end
72
+ expected = %(<table>) <<
73
+ %(<tbody>) <<
74
+ %(<tr><td class="notmonth weekend"></td><td></td><td></td><td></td><td></td><td></td><td class="weekend"></td></tr>) <<
75
+ %(<tr><td class="weekend"></td><td></td><td></td><td></td><td></td><td></td><td class="weekend"></td></tr>) <<
76
+ %(<tr><td class="weekend"></td><td class="today"></td><td class="future"></td><td class="future"></td><td class="future"></td><td class="future"></td><td class="weekend future"></td></tr>) <<
77
+ %(<tr><td class="weekend future"></td><td class="future"></td><td class="future"></td><td class="future"></td><td class="future"></td><td class="future"></td><td class="weekend future"></td></tr>) <<
78
+ %(<tr><td class="weekend future"></td><td class="future"></td><td class="future"></td><td class="future"></td><td class="notmonth future"></td><td class="notmonth future"></td><td class="notmonth weekend future"></td></tr>) <<
79
+ %(</tbody>) <<
80
+ %(</table>)
81
+ assert_dom_equal expected, output
82
+ end
83
+
84
+ def test_calendar_for_thirty_days
85
+ today = Date.civil(2008, 12, 15)
86
+ output = calendar_for([], :today => today, :year=>2008, :month=>12, :first=>today, :last=>:thirty_days) do |c|
87
+ c.day do |day, events|
88
+ concat(events.collect{|e| e.id}.join)
89
+ end
90
+ end
91
+ expected = %(<table>) <<
92
+ %(<tbody>) <<
93
+ %(<tr><td class="weekend"></td><td class="today"></td><td class="future"></td><td class="future"></td><td class="future"></td><td class="future"></td><td class="weekend future"></td></tr>) <<
94
+ %(<tr><td class="weekend future"></td><td class="future"></td><td class="future"></td><td class="future"></td><td class="future"></td><td class="future"></td><td class="weekend future"></td></tr>) <<
95
+ %(<tr><td class="weekend future"></td><td class="future"></td><td class="future"></td><td class="future"></td><td class="notmonth future"></td><td class="notmonth future"></td><td class="notmonth weekend future"></td></tr>) <<
96
+ %(<tr><td class="notmonth weekend future"></td><td class="notmonth future"></td><td class="notmonth future"></td><td class="notmonth future"></td><td class="notmonth future"></td><td class="notmonth future"></td><td class="notmonth weekend future"></td></tr>) <<
97
+ %(<tr><td class="notmonth weekend future"></td><td class="notmonth future"></td><td class="notmonth future"></td><td class="notmonth future"></td><td class="notmonth future"></td><td class="notmonth future"></td><td class="notmonth weekend future"></td></tr>) <<
98
+ %(</tbody>) <<
99
+ %(</table>)
100
+ assert_dom_equal expected, output
101
+ end
102
+
103
+ def test_calendar_for_week
104
+ today = Date.civil(2008, 12, 15)
105
+ output = calendar_for([], :today => today, :year=>2008, :month=>12, :first=>today, :last=>:week) do |c|
106
+ c.day do |day, events|
107
+ concat(events.collect{|e| e.id}.join)
108
+ end
109
+ end
110
+ expected = %(<table>) <<
111
+ %(<tbody>) <<
112
+ %(<tr><td class="weekend"></td><td class="today"></td><td class="future"></td><td class="future"></td><td class="future"></td><td class="future"></td><td class="weekend future"></td></tr>) <<
113
+ %(</tbody>) <<
114
+ %(</table>)
115
+ assert_dom_equal expected, output
116
+ end
117
+
118
+ def test_calendar_for_sets_css_ids
119
+ output = calendar_for([], :year=> 2008, :month => 12, :today => Date.civil(2008, 12, 15)) do |c|
120
+ c.day(:id => 'day_%d') do |day, events|
121
+ concat(events.collect{|e| e.id}.join)
122
+ end
123
+ end
124
+ expected = %(<table>) <<
125
+ %(<tbody>) <<
126
+ %(<tr><td class="notmonth weekend" id="day_30"></td><td id="day_01"></td><td id="day_02"></td><td id="day_03"></td><td id="day_04"></td><td id="day_05"></td><td class="weekend" id="day_06"></td></tr>) <<
127
+ %(<tr><td class="weekend" id="day_07"></td><td id="day_08"></td><td id="day_09"></td><td id="day_10"></td><td id="day_11"></td><td id="day_12"></td><td class="weekend" id="day_13"></td></tr>) <<
128
+ %(<tr><td class="weekend" id="day_14"></td><td class="today"id="day_15"></td><td class="future" id="day_16"></td><td class="future" id="day_17"></td><td class="future" id="day_18"></td><td class="future" id="day_19"></td><td class="future" class="weekend future" id="day_20"></td></tr>) <<
129
+ %(<tr><td class="weekend future" id="day_21"></td><td class="future" id="day_22"></td><td class="future" id="day_23"></td><td class="future" id="day_24"></td><td class="future" id="day_25"></td><td class="future" id="day_26"></td><td class="weekend future" id="day_27"></td></tr>) <<
130
+ %(<tr><td class="weekend future" id="day_28"></td><td class="future" id="day_29"></td><td class="future" id="day_30"></td><td class="future" id="day_31"></td><td class="notmonth future" id="day_01"></td><td class="notmonth future" id="day_02"></td><td class="notmonth weekend future" id="day_03"></td></tr>) <<
131
+ %(</tbody>) <<
132
+ %(</table>)
133
+ assert_dom_equal expected, output
134
+ end
135
+
136
+ def test_calendar_for_with_row_headers
137
+ output = calendar_for([], :year=> 2008, :month => 12, :row_header => true) do |c|
138
+ c.day do |day, events|
139
+ if events.nil?
140
+ concat(day.cweek)
141
+ else
142
+ concat(events.collect{|e| e.id}.join)
143
+ end
144
+ end
145
+ end
146
+ expected = %(<table>) <<
147
+ %(<tbody>) <<
148
+ %(<tr><td class="notmonth weekend row_header">48</td><td class="notmonth weekend"></td><td></td><td></td><td></td><td></td><td></td><td class="weekend"></td></tr>) <<
149
+ %(<tr><td class="weekend row_header">49</td><td class="weekend"></td><td></td><td></td><td></td><td></td><td></td><td class="weekend"></td></tr>) <<
150
+ %(<tr><td class="weekend row_header">50</td><td class="weekend"></td><td></td><td></td><td></td><td></td><td></td><td class="weekend"></td></tr>) <<
151
+ %(<tr><td class="weekend row_header">51</td><td class="weekend"></td><td></td><td></td><td></td><td></td><td></td><td class="weekend"></td></tr>) <<
152
+ %(<tr><td class="weekend row_header">52</td><td class="weekend"></td><td></td><td></td><td></td><td class="notmonth"></td><td class="notmonth"></td><td class="notmonth weekend"></td></tr>) <<
153
+ %(</tbody>) <<
154
+ %(</table>)
155
+ assert_dom_equal expected, output
156
+ end
157
+
158
+ def test_calendar_for_with_enumerable_object
159
+ output = calendar_for(Wrapped.new(@events), :year=> 2008, :month => 12) do |c|
160
+ c.day do |day, events|
161
+ content = events.collect{|e| e.id}.join
162
+ concat("(#{day.day})#{content}")
163
+ end
164
+ end
165
+ expected = %(<table>) <<
166
+ %(<tbody>) <<
167
+ %(<tr><td class="notmonth weekend">(30)</td><td>(1)</td><td>(2)</td><td>(3)</td><td>(4)</td><td>(5)</td><td class="weekend">(6)</td></tr>) <<
168
+ %(<tr><td class="weekend">(7)</td><td>(8)</td><td>(9)</td><td>(10)</td><td>(11)</td><td>(12)</td><td class="weekend">(13)</td></tr>) <<
169
+ %(<tr><td class="weekend">(14)</td><td>(15)</td><td>(16)</td><td>(17)</td><td>(18)</td><td>(19)</td><td class="weekend">(20)</td></tr>) <<
170
+ %(<tr><td class="weekend">(21)</td><td>(22)</td><td>(23)</td><td>(24)</td><td>(25)</td><td>(26)34</td><td class="weekend">(27)</td></tr>) <<
171
+ %(<tr><td class="weekend">(28)</td><td>(29)</td><td>(30)</td><td>(31)</td><td class="notmonth">(1)</td><td class="notmonth">(2)</td><td class="notmonth weekend">(3)</td></tr>) <<
172
+ %(</tbody>) <<
173
+ %(</table>)
174
+ assert_dom_equal expected, output
175
+ end
176
+
177
+ end
178
+
179
+ class CalendarHelperTest < ActionView::TestCase
180
+
181
+ def setup
182
+ @events = [Event.new(3, 'Jimmy Page', Date.civil(2008, 12, 26)),
183
+ Event.new(4, 'Robert Plant', Date.civil(2008, 12, 26))]
184
+ end
185
+
186
+ def test_objects_for_days_with_events
187
+ calendar = CalendarHelper::Calendar.new(:year=> 2008, :month => 12)
188
+ objects_for_days = {}
189
+ Date.civil(2008, 11, 30).upto(Date.civil(2009, 1, 3)){|day| objects_for_days[day.strftime("%Y-%m-%d")] = [day, []]}
190
+ objects_for_days['2008-12-26'][1] = @events
191
+ assert_equal objects_for_days, calendar.objects_for_days(@events, :date)
192
+ end
193
+
194
+ def test_objects_for_days
195
+ calendar = CalendarHelper::Calendar.new(:year=> 2008, :month => 12)
196
+ objects_for_days = {}
197
+ Date.civil(2008, 11, 30).upto(Date.civil(2009, 1, 3)){|day| objects_for_days[day.strftime("%Y-%m-%d")] = [day, []]}
198
+ assert_equal objects_for_days, calendar.objects_for_days([], :date)
199
+ end
200
+
201
+ def test_days
202
+ calendar = CalendarHelper::Calendar.new(:year=> 2008, :month => 12)
203
+ days = []
204
+ Date.civil(2008, 11, 30).upto(Date.civil(2009, 1, 3)){|day| days << day}
205
+ assert_equal days, calendar.days
206
+ end
207
+
208
+ def test_days_with_first_day_of_week_set
209
+ calendar = CalendarHelper::Calendar.new(:year=> 2008, :month => 12, :first_day_of_week => 1)
210
+ days = []
211
+ Date.civil(2008, 12, 1).upto(Date.civil(2009, 1, 4)){|day| days << day}
212
+ assert_equal days, calendar.days
213
+ end
214
+
215
+ def test_first_day
216
+ calendar = CalendarHelper::Calendar.new(:year=> 2008, :month => 12)
217
+ assert_equal Date.civil(2008, 11, 30), calendar.first_day
218
+ end
219
+
220
+ def test_last_day
221
+ calendar = CalendarHelper::Calendar.new(:year=> 2008, :month => 12)
222
+ assert_equal Date.civil(2009, 1, 3), calendar.last_day
223
+ end
224
+
225
+ def test_last_day_with_first_day_of_week_set
226
+ calendar = CalendarHelper::Calendar.new(:year=> 2008, :month => 12, :first_day_of_week => 1)
227
+ assert_equal Date.civil(2009, 1, 4), calendar.last_day
228
+ end
229
+ end
230
+
231
+ class Event < Struct.new(:id, :name, :date); end
232
+
233
+ class Wrapped
234
+ include Enumerable
235
+ attr_accessor :objects
236
+
237
+ def initialize(objects)
238
+ @objects = objects
239
+ end
240
+
241
+ def each
242
+ @objects.each { |item| yield item }
243
+ end
244
+
245
+ def <=>(other)
246
+ @objects <=> other
247
+ end
248
+ end
@@ -0,0 +1,183 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper.rb')
2
+
3
+ class TableBuilderTest < ActionView::TestCase
4
+ include ActionView::Helpers::TextHelper
5
+ include ActionView::Helpers::TagHelper
6
+ include TableHelper
7
+ attr_accessor :output_buffer
8
+
9
+ def setup
10
+ @drummer1 = Drummer.new(1, 'John "Stumpy" Pepys')
11
+ @drummer2 = Drummer.new(2, 'Eric "Stumpy Joe" Childs')
12
+ @drummer3 = Drummer.new(3, 'Peter "James" Bond')
13
+ @drummer4 = Drummer.new(4, 'Mick Shrimpton (R. J. "Ric" Parnell)')
14
+ end
15
+
16
+ def test_table_for
17
+ output = table_for([], :html => { :id => 'id', :style => 'style', :class => 'class'}) do |t|
18
+ end
19
+ expected = %(<table id="id" style="style" class="class">) <<
20
+ %(</table>)
21
+ assert_dom_equal expected, output
22
+ end
23
+
24
+ def test_table_for_without_an_array_raises_error
25
+ assert_raises(ArgumentError) do
26
+ table_for('a') {|t| }
27
+ end
28
+ end
29
+
30
+ def test_head
31
+ output = table_for([]) do |t|
32
+ t.head do
33
+ t.r do
34
+ output_buffer.concat t.h('Id')
35
+ output_buffer.concat t.h('Name')
36
+ end
37
+ end
38
+ end
39
+ expected = %(<table>) <<
40
+ %(<thead>) <<
41
+ %(<tr>) <<
42
+ %(<th>Id</th>) <<
43
+ %(<th>Name</th>) <<
44
+ %(</tr>) <<
45
+ %(</thead>) <<
46
+ %(</table>)
47
+ assert_dom_equal expected, output
48
+ end
49
+
50
+ def test_head_r
51
+ output = table_for([]) do |t|
52
+ t.head_r do
53
+ output_buffer.concat t.h('Id')
54
+ output_buffer.concat t.h('Name')
55
+ end
56
+ end
57
+ expected = %(<table>) <<
58
+ %(<thead>) <<
59
+ %(<tr>) <<
60
+ %(<th>Id</th>) <<
61
+ %(<th>Name</th>) <<
62
+ %(</tr>) <<
63
+ %(</thead>) <<
64
+ %(</table>)
65
+ assert_dom_equal expected, output
66
+ end
67
+
68
+ def test_head_with_array
69
+ output = table_for([@drummer1, @drummer2]) do |t|
70
+ concat t.head('Id', 'Name')
71
+ end
72
+ expected = %(<table>) <<
73
+ %(<thead>) <<
74
+ %(<tr>) <<
75
+ %(<th>Id</th>) <<
76
+ %(<th>Name</th>) <<
77
+ %(</tr>) <<
78
+ %(</thead>) <<
79
+ %(</table>)
80
+ assert_dom_equal expected, output
81
+ end
82
+
83
+ def test_body
84
+ output = table_for([@drummer3, @drummer4]) do |t|
85
+ t.body do |e|
86
+ t.r do
87
+ concat t.d(e.id)
88
+ concat t.d(e.name)
89
+ end
90
+ end
91
+ end
92
+ expected = %(<table>) <<
93
+ %(<tbody>) <<
94
+ %(<tr>) <<
95
+ %(<td>3</td>) <<
96
+ %(<td>Peter &quot;James&quot; Bond</td>) <<
97
+ %(</tr>) <<
98
+ %(<tr>) <<
99
+ %(<td>4</td>) <<
100
+ %(<td>Mick Shrimpton (R. J. &quot;Ric&quot; Parnell)</td>) <<
101
+ %(</tr>) <<
102
+ %(</tbody>) <<
103
+ %(</table>)
104
+ assert_dom_equal expected, output
105
+ end
106
+
107
+ def test_body_r
108
+ output = table_for([@drummer3, @drummer4]) do |t|
109
+ t.body_r do |e|
110
+ concat t.d(e.id)
111
+ concat t.d(e.name)
112
+ end
113
+ end
114
+ expected = %(<table>) <<
115
+ %(<tbody>) <<
116
+ %(<tr>) <<
117
+ %(<td>3</td>) <<
118
+ %(<td>Peter &quot;James&quot; Bond</td>) <<
119
+ %(</tr>) <<
120
+ %(<tr>) <<
121
+ %(<td>4</td>) <<
122
+ %(<td>Mick Shrimpton (R. J. &quot;Ric&quot; Parnell)</td>) <<
123
+ %(</tr>) <<
124
+ %(</tbody>) <<
125
+ %(</table>)
126
+ assert_dom_equal expected, output
127
+ end
128
+
129
+ def test_td_with_options
130
+ output = table_for([@drummer1]) do |t|
131
+ t.body_r do |e|
132
+ output_buffer.concat t.d(e.name, :class => 'class')
133
+ end
134
+ end
135
+ expected = %(<table>) <<
136
+ %(<tbody>) <<
137
+ %(<tr>) <<
138
+ %(<td class="class">John &quot;Stumpy&quot; Pepys</td>) <<
139
+ %(</tr>) <<
140
+ %(</tbody>) <<
141
+ %(</table>)
142
+ assert_dom_equal expected, output
143
+ end
144
+
145
+ def test_td_with_block
146
+ output = table_for([@drummer1]) do |t|
147
+ t.body_r do |e|
148
+ t.d do
149
+ concat 'content'
150
+ end
151
+ end
152
+ end
153
+ expected = %(<table>) <<
154
+ %(<tbody>) <<
155
+ %(<tr>) <<
156
+ %(<td>content</td>) <<
157
+ %(</tr>) <<
158
+ %(</tbody>) <<
159
+ %(</table>)
160
+ assert_dom_equal expected, output
161
+ end
162
+
163
+ def test_td_with_block_and_options
164
+ output = table_for([@drummer1]) do |t|
165
+ t.body_r do |e|
166
+ t.d(:class => 'class') do
167
+ concat 'content'
168
+ end
169
+ end
170
+ end
171
+ expected = %(<table>) <<
172
+ %(<tbody>) <<
173
+ %(<tr>) <<
174
+ %(<td class="class">content</td>) <<
175
+ %(</tr>) <<
176
+ %(</tbody>) <<
177
+ %(</table>)
178
+ assert_dom_equal expected, output
179
+ end
180
+
181
+ end
182
+
183
+ class Drummer < Struct.new(:id, :name); end
@@ -0,0 +1,14 @@
1
+ require 'test/unit'
2
+
3
+ require "rubygems"
4
+ require 'active_support'
5
+ require 'action_pack'
6
+ require 'action_controller'
7
+ require 'action_view'
8
+ require 'action_controller'
9
+ require 'action_view'
10
+ require 'action_view/base'
11
+ require 'action_view/template'
12
+ require 'action_view/test_case'
13
+
14
+ require(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'table_builder')))
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: watu_table_builder
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Petrik de Heus
9
+ - Andrew C. Greenberg
10
+ - Jason Cheong-Kee-You
11
+ - J. Pablo Fernández
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+ date: 2012-02-13 00:00:00.000000000Z
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ name: rake
19
+ requirement: &70327288285800 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ! '>='
23
+ - !ruby/object:Gem::Version
24
+ version: '0'
25
+ type: :development
26
+ prerelease: false
27
+ version_requirements: *70327288285800
28
+ - !ruby/object:Gem::Dependency
29
+ name: test-unit
30
+ requirement: &70327288285380 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: *70327288285380
39
+ - !ruby/object:Gem::Dependency
40
+ name: activesupport
41
+ requirement: &70327288258200 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: *70327288258200
50
+ - !ruby/object:Gem::Dependency
51
+ name: actionpack
52
+ requirement: &70327288257660 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ type: :development
59
+ prerelease: false
60
+ version_requirements: *70327288257660
61
+ description: Rails builder for creating tables and calendars inspired by ActionView's
62
+ FormBuilder.
63
+ email:
64
+ - pupeno@watuhq.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - lib/table_builder/calendar_helper.rb
70
+ - lib/table_builder/table_builder.rb
71
+ - lib/table_builder/version.rb
72
+ - lib/table_builder.rb
73
+ - test/calendar_helper_test.rb
74
+ - test/table_builder_test.rb
75
+ - test/test_helper.rb
76
+ - Gemfile
77
+ - MIT-LICENSE
78
+ - Rakefile
79
+ - README.rdoc
80
+ - init.rb
81
+ homepage: https://github.com/watu/table_builder
82
+ licenses: []
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project: table_builder
101
+ rubygems_version: 1.8.10
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: Rails builder for creating tables and calendars inspired by ActionView's
105
+ FormBuilder.
106
+ test_files:
107
+ - test/calendar_helper_test.rb
108
+ - test/table_builder_test.rb
109
+ - test/test_helper.rb
110
+ has_rdoc: