watu_table_builder 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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: