calorie 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/README.md +69 -0
- data/Rakefile +1 -0
- data/calorie.gemspec +24 -0
- data/lib/calorie.rb +15 -0
- data/lib/calorie/calendar.rb +78 -0
- data/lib/calorie/day.rb +46 -0
- data/lib/calorie/version.rb +3 -0
- data/lib/calorie/week.rb +12 -0
- data/lib/calorie/weeks_in_month.rb +9 -0
- data/spec/calendar_spec.rb +42 -0
- data/spec/calorie_spec.rb +13 -0
- data/spec/day_spec.rb +53 -0
- data/spec/week_spec.rb +24 -0
- data/spec/weeks_in_month_spec.rb +95 -0
- metadata +84 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# Calorie
|
2
|
+
|
3
|
+
A calendar is a calendar is a calendar.
|
4
|
+
|
5
|
+
Motivated by the frustration of solving the same problem in a dozen different ugly ways in a dozen different applications.
|
6
|
+
|
7
|
+
## Requirements
|
8
|
+
|
9
|
+
This uses the ruby core `Date` library.
|
10
|
+
|
11
|
+
In other words, rails is *not* required.
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
Create a hash that uses the day of the month as the key.
|
16
|
+
The data can be anything, and only your code will be interacting with it.
|
17
|
+
|
18
|
+
data = {
|
19
|
+
1 => thing,
|
20
|
+
2 => different_thing,
|
21
|
+
3 => nil,
|
22
|
+
4 => medium_sized_thing,
|
23
|
+
5 => complicated_thing,
|
24
|
+
6 => nil,
|
25
|
+
# ... etc
|
26
|
+
}
|
27
|
+
|
28
|
+
Create a presenter for a month by sending in `year`, `month`, and the data:
|
29
|
+
|
30
|
+
cal = Calorie.new(2010, 6, data)
|
31
|
+
|
32
|
+
In your view, you can style it however you wish, e.g.:
|
33
|
+
|
34
|
+
cal.days_of_the_week do |label|
|
35
|
+
if day.weekend?
|
36
|
+
# label styled as a weekend
|
37
|
+
else
|
38
|
+
# label styled as a weekday
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
cal.each_week do |week|
|
43
|
+
week.each_day do |day|
|
44
|
+
unless day.blank?
|
45
|
+
# the day of the month is day.number
|
46
|
+
# do stuff with day.data
|
47
|
+
if day.today?
|
48
|
+
# omg, it's RIGHT NOW
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
If you don't need to lay it out by week, you can also iterate straight through the days:
|
56
|
+
|
57
|
+
cal.each_day do |day|
|
58
|
+
# the day of the month is day.number
|
59
|
+
# do stuff with day.data
|
60
|
+
if day.today?
|
61
|
+
# omg, it's RIGHT NOW
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
## TODO
|
66
|
+
|
67
|
+
* configurable week start
|
68
|
+
* i18n for days of the week
|
69
|
+
* add labels for current, previous, and next month (with i18n support)
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/calorie.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "calorie/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "calorie"
|
7
|
+
s.version = Calorie::VERSION
|
8
|
+
s.authors = ["Katrina Owen"]
|
9
|
+
s.email = ["katrina.owen@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{A calendar is a calendar is a calendar.}
|
12
|
+
s.description = %q{A simple, ruby calendar presenter.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "calorie"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "rspec"
|
22
|
+
s.add_development_dependency "timecop"
|
23
|
+
# s.add_runtime_dependency "rest-client"
|
24
|
+
end
|
data/lib/calorie.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "calorie/version"
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
require 'calorie/weeks_in_month'
|
6
|
+
require 'calorie/calendar'
|
7
|
+
require 'calorie/week'
|
8
|
+
require 'calorie/day'
|
9
|
+
|
10
|
+
module Calorie
|
11
|
+
|
12
|
+
def self.new(year, month, data)
|
13
|
+
Calendar.new(year, month, data)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Calorie
|
2
|
+
|
3
|
+
class Calendar
|
4
|
+
include WeeksInMonth
|
5
|
+
|
6
|
+
attr_reader :days, :weeks, :year, :month, :data
|
7
|
+
def initialize(year, month, data)
|
8
|
+
@data = data
|
9
|
+
@year = year
|
10
|
+
@month = month
|
11
|
+
initialize_days
|
12
|
+
initialize_weeks
|
13
|
+
end
|
14
|
+
|
15
|
+
def first_day
|
16
|
+
@first_day ||= Date.new(year, month, 1)
|
17
|
+
@first_day
|
18
|
+
end
|
19
|
+
|
20
|
+
def last_day
|
21
|
+
@last_day ||= first_day.next_month.prev_day
|
22
|
+
@last_day
|
23
|
+
end
|
24
|
+
|
25
|
+
def days_in_month
|
26
|
+
days.size
|
27
|
+
end
|
28
|
+
|
29
|
+
def first_day_falls_on
|
30
|
+
first_day.wday
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize_days
|
34
|
+
@days = []
|
35
|
+
(first_day.mday..last_day.mday).map do |i|
|
36
|
+
date = Date.new(year, month, i)
|
37
|
+
@days << Calorie::Day.new(date, data[i])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize_weeks
|
42
|
+
@weeks = []
|
43
|
+
padded_days = days_for_slicing
|
44
|
+
number_of_weeks.times do
|
45
|
+
@weeks << Calorie::Week.new(padded_days.slice!(0..6))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def days_for_slicing
|
50
|
+
slices = days.clone
|
51
|
+
|
52
|
+
blank_days_at_start.times { slices.unshift(Calorie::Day.new) }
|
53
|
+
blank_days_at_end.times { slices.push(Calorie::Day.new) }
|
54
|
+
|
55
|
+
slices
|
56
|
+
end
|
57
|
+
|
58
|
+
def blank_days_at_start
|
59
|
+
first_day.wday
|
60
|
+
end
|
61
|
+
|
62
|
+
def blank_days_at_end
|
63
|
+
(blank_days_at_start + days_in_month) % 7
|
64
|
+
end
|
65
|
+
|
66
|
+
def days_in_month
|
67
|
+
last_day.mday
|
68
|
+
end
|
69
|
+
|
70
|
+
def each_day(&block)
|
71
|
+
days.each {|day| block.call(day) }
|
72
|
+
end
|
73
|
+
|
74
|
+
def days_of_the_week
|
75
|
+
%w(Su Mo Tu We Th Fr Sa)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/calorie/day.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
module Calorie
|
2
|
+
class Day
|
3
|
+
|
4
|
+
def initialize(date = nil, data = nil)
|
5
|
+
if date
|
6
|
+
@date = date
|
7
|
+
else
|
8
|
+
@date = NullDate.new
|
9
|
+
end
|
10
|
+
@data = data
|
11
|
+
end
|
12
|
+
|
13
|
+
def weekend?
|
14
|
+
@date.sunday? || @date.saturday?
|
15
|
+
end
|
16
|
+
|
17
|
+
def number
|
18
|
+
@date.mday
|
19
|
+
end
|
20
|
+
|
21
|
+
def data
|
22
|
+
@data
|
23
|
+
end
|
24
|
+
|
25
|
+
def blank?
|
26
|
+
@date.is_a?(NullDate)
|
27
|
+
end
|
28
|
+
|
29
|
+
def today?
|
30
|
+
@date == Date.today
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class NullDate
|
35
|
+
def sunday?
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
def saturday?
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
def mday
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/calorie/week.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'calorie'
|
2
|
+
|
3
|
+
describe Calorie::Calendar do
|
4
|
+
subject { Calorie::Calendar.new(2010, 12, {25 => 'Christmas'}) }
|
5
|
+
|
6
|
+
it "creates all the days" do
|
7
|
+
numbers = []
|
8
|
+
subject.each_day do |day|
|
9
|
+
numbers << day.number
|
10
|
+
end
|
11
|
+
|
12
|
+
numbers.should eq((1..31).to_a)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "hands out the data" do
|
16
|
+
subject.each_day do |day|
|
17
|
+
if day.number == 25
|
18
|
+
day.data.should eq('Christmas')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "gets the first week right" do
|
24
|
+
numbers = []
|
25
|
+
subject.weeks.first.each_day do |day|
|
26
|
+
numbers << day.number
|
27
|
+
end
|
28
|
+
numbers.should eq([nil, nil, nil] + (1..4).to_a)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "gets the last week right" do
|
32
|
+
numbers = []
|
33
|
+
subject.weeks.last.each_day do |day|
|
34
|
+
numbers << day.number
|
35
|
+
end
|
36
|
+
numbers.should eq((26..31).to_a + [nil])
|
37
|
+
end
|
38
|
+
|
39
|
+
it "has labels for the days of the week" do
|
40
|
+
subject.days_of_the_week.should eq(%w(Su Mo Tu We Th Fr Sa))
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'calorie'
|
2
|
+
|
3
|
+
describe Calorie do
|
4
|
+
it "provides a simple presenter for a monthly calendar" do
|
5
|
+
cal = Calorie.new(2010, 12, {25 => 'Christmas'})
|
6
|
+
|
7
|
+
cal.each_day do |day|
|
8
|
+
if day.number == 25
|
9
|
+
day.data.should eq('Christmas')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/spec/day_spec.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'calorie/day'
|
2
|
+
require 'timecop'
|
3
|
+
|
4
|
+
describe Calorie::Day do
|
5
|
+
|
6
|
+
context "during the weekend" do
|
7
|
+
subject { Calorie::Day.new(Date.new(2010, 6, 13), "hello, world") }
|
8
|
+
|
9
|
+
its(:number) { should eq(13) }
|
10
|
+
its(:data) { should eq("hello, world") }
|
11
|
+
its(:weekend?) { should be_true }
|
12
|
+
its(:blank?) { should be_false}
|
13
|
+
|
14
|
+
context "on that particular day" do
|
15
|
+
before :each do
|
16
|
+
Timecop.freeze(Time.new(2010, 6, 13, 11, 40, 17))
|
17
|
+
end
|
18
|
+
|
19
|
+
its(:today?) { should be_true }
|
20
|
+
end
|
21
|
+
|
22
|
+
context "on a different day" do
|
23
|
+
before :each do
|
24
|
+
Timecop.freeze(Time.new(2010, 6, 14, 20, 15, 47))
|
25
|
+
end
|
26
|
+
|
27
|
+
its(:today?) { should be_false }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "midweek" do
|
32
|
+
subject { Calorie::Day.new(Date.new(2010, 6, 17), "so long, folks") }
|
33
|
+
|
34
|
+
its(:number) { should eq(17) }
|
35
|
+
its(:data) { should eq("so long, folks") }
|
36
|
+
its(:weekend?) { should be_false }
|
37
|
+
its(:blank?) { should be_false}
|
38
|
+
end
|
39
|
+
|
40
|
+
context "a null day" do
|
41
|
+
subject { Calorie::Day.new }
|
42
|
+
its(:blank?) { should be_true }
|
43
|
+
its(:number) { should be_nil }
|
44
|
+
its(:weekend?) { should be_false }
|
45
|
+
its(:data) { should be_nil }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe Calorie::NullDate do
|
50
|
+
its(:mday) { should be_nil }
|
51
|
+
its(:sunday?) { should be_false }
|
52
|
+
its(:saturday?) { should be_false }
|
53
|
+
end
|
data/spec/week_spec.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'calorie/day'
|
2
|
+
require 'calorie/week'
|
3
|
+
|
4
|
+
describe Calorie::Week do
|
5
|
+
|
6
|
+
it "loops through the days" do
|
7
|
+
days = [
|
8
|
+
Calorie::Day.new,
|
9
|
+
Calorie::Day.new,
|
10
|
+
Calorie::Day.new(Date.new(2010, 6, 1), "the first"),
|
11
|
+
Calorie::Day.new(Date.new(2010, 6, 2), "the second"),
|
12
|
+
Calorie::Day.new(Date.new(2010, 6, 3), "the third"),
|
13
|
+
Calorie::Day.new(Date.new(2010, 6, 4), "the fourth"),
|
14
|
+
Calorie::Day.new(Date.new(2010, 6, 5), "the fifth"),
|
15
|
+
]
|
16
|
+
|
17
|
+
numbers = []
|
18
|
+
Calorie::Week.new(days).each_day do |day|
|
19
|
+
numbers << day.number
|
20
|
+
end
|
21
|
+
|
22
|
+
numbers.should eq([nil, nil, 1, 2, 3, 4, 5])
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'calorie/weeks_in_month'
|
2
|
+
|
3
|
+
describe Calorie::WeeksInMonth do
|
4
|
+
let(:cal) { stub.extend(Calorie::WeeksInMonth) }
|
5
|
+
|
6
|
+
context "with a 28 day month" do
|
7
|
+
before :each do
|
8
|
+
cal.stub(:days_in_month => 28)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "has 4 weeks when first day is Sunday" do
|
12
|
+
cal.stub(:first_day_falls_on => 0)
|
13
|
+
cal.number_of_weeks.should eq(4)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "has 5 weeks when first day is Monday" do
|
17
|
+
cal.stub(:first_day_falls_on => 1)
|
18
|
+
cal.number_of_weeks.should eq(5)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "has 5 weeks when first day is Saturday" do
|
22
|
+
cal.stub(:first_day_falls_on => 6)
|
23
|
+
cal.number_of_weeks.should eq(5)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "with a 29 day month" do
|
28
|
+
before :each do
|
29
|
+
cal.stub(:days_in_month => 29)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "has 5 weeks when first day is Sunday" do
|
33
|
+
cal.stub(:first_day_falls_on => 0)
|
34
|
+
cal.number_of_weeks.should eq(5)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "has 5 weeks when first day is Monday" do
|
38
|
+
cal.stub(:first_day_falls_on => 1)
|
39
|
+
cal.number_of_weeks.should eq(5)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "has 5 weeks when first day is Saturday" do
|
43
|
+
cal.stub(:first_day_falls_on => 6)
|
44
|
+
cal.number_of_weeks.should eq(5)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
context "with a 30 day month" do
|
50
|
+
before :each do
|
51
|
+
cal.stub(:days_in_month => 30)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "has 5 weeks when first day is Sunday" do
|
55
|
+
cal.stub(:first_day_falls_on => 0)
|
56
|
+
cal.number_of_weeks.should eq(5)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "has 5 weeks when first day is Friday" do
|
60
|
+
cal.stub(:first_day_falls_on => 5)
|
61
|
+
cal.number_of_weeks.should eq(5)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "has 6 weeks when first day is Saturday" do
|
65
|
+
cal.stub(:first_day_falls_on => 6)
|
66
|
+
cal.number_of_weeks.should eq(6)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "with a 31 day month" do
|
71
|
+
before :each do
|
72
|
+
cal.stub(:days_in_month => 31)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "has 5 weeks when first day is Sunday" do
|
76
|
+
cal.stub(:first_day_falls_on => 0)
|
77
|
+
cal.number_of_weeks.should eq(5)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "has 5 weeks when first day is Thursday" do
|
81
|
+
cal.stub(:first_day_falls_on => 4)
|
82
|
+
cal.number_of_weeks.should eq(5)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "has 6 weeks when first day is Friday" do
|
86
|
+
cal.stub(:first_day_falls_on => 5)
|
87
|
+
cal.number_of_weeks.should eq(6)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "has 6 weeks when first day is Saturday" do
|
91
|
+
cal.stub(:first_day_falls_on => 6)
|
92
|
+
cal.number_of_weeks.should eq(6)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: calorie
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Katrina Owen
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-11-27 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &2153896240 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2153896240
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: timecop
|
27
|
+
requirement: &2153895820 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2153895820
|
36
|
+
description: A simple, ruby calendar presenter.
|
37
|
+
email:
|
38
|
+
- katrina.owen@gmail.com
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- .rspec
|
45
|
+
- Gemfile
|
46
|
+
- README.md
|
47
|
+
- Rakefile
|
48
|
+
- calorie.gemspec
|
49
|
+
- lib/calorie.rb
|
50
|
+
- lib/calorie/calendar.rb
|
51
|
+
- lib/calorie/day.rb
|
52
|
+
- lib/calorie/version.rb
|
53
|
+
- lib/calorie/week.rb
|
54
|
+
- lib/calorie/weeks_in_month.rb
|
55
|
+
- spec/calendar_spec.rb
|
56
|
+
- spec/calorie_spec.rb
|
57
|
+
- spec/day_spec.rb
|
58
|
+
- spec/week_spec.rb
|
59
|
+
- spec/weeks_in_month_spec.rb
|
60
|
+
homepage: ''
|
61
|
+
licenses: []
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ! '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubyforge_project: calorie
|
80
|
+
rubygems_version: 1.8.10
|
81
|
+
signing_key:
|
82
|
+
specification_version: 3
|
83
|
+
summary: A calendar is a calendar is a calendar.
|
84
|
+
test_files: []
|