Permalink
Browse files

Introduced the humble beginnings of Year, Month and Day classes, whic…

…h all wrap around ActiveTime:

Year.new(2008).posts
Month.new(2008, 11).posts
Day.new(2008, 11, 14).posts

Year.new(Time.now).posts
Month.new(Time.now).posts
Day.new(Time.now).posts
  • Loading branch information...
1 parent 90a862b commit d3b6b0fe08f2fa59461ca44ead318dff8ab61538 @justinfrench committed Jan 1, 2009
Showing with 343 additions and 1 deletion.
  1. +3 −0 init.rb
  2. +13 −1 lib/active_time.rb
  3. +45 −0 lib/day.rb
  4. +47 −0 lib/month.rb
  5. +45 −0 lib/year.rb
  6. +190 −0 test/active_time_test.rb
View
@@ -1,2 +1,5 @@
require 'active_time'
require 'active_record_in_date_range_scope_extension'
+require 'year'
+require 'month'
+require 'day'
View
@@ -2,7 +2,7 @@ class ActiveTime
COLLECTION_METHOD_NAMES_PATTERN = /[a-z_]+s$/
- attr_accessor :starting, :ending
+ attr_accessor :starting, :ending, :year, :month, :day
alias_method :time, :starting
# Creates an object representing a period of time with a starting and ending
@@ -104,6 +104,18 @@ def description
end
end
+ # Returns true if the +comparison_object+ is the same object, or is of the same type and has the same id.
+ def ==(comparable_object)
+ comparable_object.equal?(self) || (
+ comparable_object.instance_of?(self.class) &&
+ comparable_object.year == year &&
+ comparable_object.month == month &&
+ comparable_object.starting == starting &&
+ comparable_object.ending == ending &&
+ comparable_object.range == range
+ )
+ end
+
protected
def self.class_name_for_method_name(method_name)
View
@@ -0,0 +1,45 @@
+# Day is simply a wrapper around ActiveTime, with a few subtle differences. Just like ActiveTime,
+# there are two ways to initialize, with a Fixnum for the year, month and day, or with a Time instance.
+#
+# Initializing with a year, month and day Fixnum behaves exactly the same as it does in ActiveTime:
+#
+# Year.new(2008, 11, 14) # same as ActiveTime.new(2008, 11, 14)
+#
+# Initializing with a Time instance behaves slightly different to ActiveTime. Our intent is to have
+# an object that represents an entire month, so instead of supplying a starting and ending Time, you
+# can simply pass in any Time object, and it's year and month will be used to infer the correct
+# starting and ending dates.
+#
+# The following all have the same starting time...
+#
+# Month.new(Time.gm(2008, 11, 14, 1)).starting # => Fri Nov 14 00:00:00 UTC 2008
+# Month.new(Time.gm(2008, 11, 14, 3)).starting # => Fri Nov 14 00:00:00 UTC 2008
+# Month.new(Time.gm(2008, 11, 14, 7)).starting # => Fri Nov 14 00:00:00 UTC 2008
+# Month.new(2008, 11, 14).starting # => Fri Nov 14 00:00:00 UTC 2008
+#
+# ... and the same ending time:
+#
+# Month.new(Time.gm(2008, 11, 14, 1)).ending # => Fri Nov 14 23:59:59 UTC 2008
+# Month.new(Time.gm(2008, 11, 14, 3)).ending # => Fri Nov 14 23:59:59 UTC 2008
+# Month.new(Time.gm(2008, 11, 14, 7)).ending # => Fri Nov 14 23:59:59 UTC 2008
+# Month.new(2008, 11, 14).ending # => Fri Nov 14 23:59:59 UTC 2008
+#
+# Because Day is a subclass of ActiveTime, all ActiveTime methods are available (see documentation
+# for more details):
+#
+# Day.new(Time.now).range # => :day
+# Day.new(Time.now).description # => "on January 01, 2009"
+# Day.new(Time.now).posts # => a collection of Posts created on this day
+
+class Day < ActiveTime
+
+ def initialize(*args)
+ if(args.empty?)
+ raise ArgumentError, "arguments must either be (a Time object) or (year Fixnum, month Fixnum, day Fixnum)"
+ elsif(args.size == 1 && args.first.is_a?(Time))
+ args = [args.first.year, args.first.month, args.first.day]
+ end
+ super
+ end
+
+end
View
@@ -0,0 +1,47 @@
+# Month is simply a wrapper around ActiveTime, with a few subtle differences. Just like ActiveTime,
+# there are two ways to initialize, with a Fixnum for the year and month, or with a Time instance.
+#
+# Initializing with a year and month Fixnum behaves exactly the same as it does in ActiveTime:
+#
+# Year.new(2008, 11) # same as ActiveTime.new(2008, 11)
+#
+# Initializing with a Time instance behaves slightly different to ActiveTime. Our intent is to have
+# an object that represents an entire month, so instead of supplying a starting and ending Time, you
+# can simply pass in any Time object, and it's year and month will be used to infer the correct
+# starting and ending dates.
+#
+# The following all have the same starting time...
+#
+# Month.new(Time.gm(2008, 11, 14)).starting # => Sat Nov 01 00:00:00 UTC 2008
+# Month.new(Time.gm(2008, 11, 15)).starting # => Sat Nov 01 00:00:00 UTC 2008
+# Month.new(Time.gm(2008, 11, 16)).starting # => Sat Nov 01 00:00:00 UTC 2008
+# Month.new(2008, 11).starting # => Sat Nov 01 00:00:00 UTC 2008
+#
+# ... and the same ending time:
+#
+# Month.new(Time.gm(2008, 11, 14)).ending # => Sun Nov 30 23:59:59 UTC 2008
+# Month.new(Time.gm(2008, 11, 15)).ending # => Sun Nov 30 23:59:59 UTC 2008
+# Month.new(Time.gm(2008, 11, 16)).ending # => Sun Nov 30 23:59:59 UTC 2008
+# Month.new(2008, 11).ending # => Sun Nov 30 23:59:59 UTC 2008
+#
+# Because Day is a subclass of ActiveTime, all ActiveTime methods are available (see documentation
+# for more details):
+#
+# Month.new(Time.now).range # => :month
+# Month.new(Time.now).description # => "in January 2009"
+# Month.new(Time.now).posts # => a collection of Posts created in this month
+
+class Month < ActiveTime
+
+ def initialize(*args)
+ if(args.empty?)
+ raise ArgumentError, "arguments must either be (a Time object) or (year Fixnum, month Fixnum)"
+ elsif(args.size == 1 && args.first.is_a?(Time))
+ args = [args.first.year, args.first.month]
+ end
+ super
+ end
+
+end
+
+
View
@@ -0,0 +1,45 @@
+# Year is simply a wrapper around ActiveTime, with a few subtle differences. Just like ActiveTime,
+# there are two ways to initialize, with a Fixnum for the year, or with a Time instance.
+#
+# Initializing with a year Fixnum behaves exactly the same as it does in ActiveTime:
+#
+# Year.new(2008) # same as ActiveTime.new(2008)
+#
+# Initializing with a Time instance behaves slightly different to ActiveTime. Our intent is to have
+# an object that represents an entire year, so instead of supplying a starting and ending Time, you
+# can simply pass in any Time object, and it's year will be used to infer the correct starting and
+# ending dates.
+#
+# The following all have the same starting time...
+#
+# Year.new(Time.gm(2008, 11, 14)).starting # => Tue Jan 01 00:00:00 UTC 2008
+# Year.new(Time.gm(2008, 1, 15)).starting # => Tue Jan 01 00:00:00 UTC 2008
+# Year.new(Time.gm(2008, 3, 15)).starting # => Tue Jan 01 00:00:00 UTC 2008
+# Year.new(2008).starting # => Tue Jan 01 00:00:00 UTC 2008
+#
+# ... and the same ending time:
+#
+# Year.new(Time.gm(2008, 11, 14)).ending # => Wed Dec 31 23:59:59 UTC 2008
+# Year.new(Time.gm(2008, 1, 15)).ending # => Wed Dec 31 23:59:59 UTC 2008
+# Year.new(Time.gm(2008, 3, 15)).ending # => Wed Dec 31 23:59:59 UTC 2008
+# Year.new(2008).ending # => Wed Dec 31 23:59:59 UTC 2008
+#
+# Because Day is a subclass of ActiveTime, all ActiveTime methods are available (see documentation
+# for more details):
+#
+# Yeaar.new(Time.now).range # => :year
+# Yeaar.new(Time.now).description # => "in January 2009"
+# Yeaar.new(Time.now).posts # => a collection of Posts created in this year
+
+class Year < ActiveTime
+
+ def initialize(*args)
+ if(args.empty?)
+ raise ArgumentError, "arguments must either be (a Time object) or (year Fixnum)"
+ elsif(args.size == 1 && args.first.is_a?(Time))
+ args = [args.first.year]
+ end
+ super
+ end
+
+end
View
@@ -253,5 +253,195 @@ def ending
end
end
+
+ context "Year" do
+
+ context "when initialized with only one time arg" do
+
+ setup do
+ @object = Year.new(starting)
+ end
+
+ should "be the same as intitializing with a year Fixnum" do
+ assert Year.new(starting.year) == @object
+ end
+
+ end
+
+ context "when initialized with a year Fixnum" do
+
+ setup do
+ @object = Year.new(year)
+ end
+
+ should "have the same starting time as intitializing ActiveTime with a year Fixnum" do
+ assert ActiveTime.new(year).starting == @object.starting
+ end
+
+ end
+
+ context "when initialized with no args" do
+
+ should "raise ArgumentError" do
+ assert_raise ArgumentError do
+ Year.new
+ end
+ end
+
+ end
+
+ context "when initialized correctly" do
+
+ setup do
+ @object = Year.new(year)
+ @active_time = ActiveTime.new(year)
+ end
+
+ should "have a description equal to a similar ActiveTime object" do
+ assert_equal @active_time.description, @object.description
+ end
+
+ should "have a starting time equal to a similar ActiveTime object" do
+ assert_equal @active_time.starting, @object.starting
+ end
+
+ should "have an ending time equal to a similar ActiveTime object" do
+ assert_equal @active_time.ending, @object.ending
+ end
+
+ should "have a range equal to a similar ActiveTime object" do
+ assert_equal @active_time.range, @object.range
+ end
+
+ end
+
+ end
+
+ context "Month" do
+
+ context "when initialized with only one time arg" do
+
+ setup do
+ @object = Month.new(starting)
+ end
+
+ should "be the same as intitializing with year and month Fixnum" do
+ assert Month.new(starting.year, starting.month) == @object
+ end
+
+ end
+
+ context "when initialized with a year and month Fixnum" do
+
+ setup do
+ @object = Year.new(year, month)
+ end
+
+ should "have the same starting time as intitializing ActiveTime with a year Fixnum" do
+ assert ActiveTime.new(year, month).starting == @object.starting
+ end
+ end
+
+ context "when initialized with no args" do
+
+ should "raise ArgumentError" do
+ assert_raise ArgumentError do
+ Month.new
+ end
+ end
+
+ end
+
+ context "when initialized correctly" do
+
+ setup do
+ @object = Month.new(year, month)
+ @active_time = ActiveTime.new(year, month)
+ end
+
+ should "have a description equal to a similar ActiveTime object" do
+ assert_equal @active_time.description, @object.description
+ end
+
+ should "have a starting time equal to a similar ActiveTime object" do
+ assert_equal @active_time.starting, @object.starting
+ end
+
+ should "have an ending time equal to a similar ActiveTime object" do
+ assert_equal @active_time.ending, @object.ending
+ end
+
+ should "have a range equal to a similar ActiveTime object" do
+ assert_equal @active_time.range, @object.range
+ end
+
+ end
+
+ end
+
+ context "Day" do
+
+ context "when initialized with only one time arg" do
+
+ setup do
+ @object = Day.new(starting)
+ end
+
+ should "have the same starting time as intitializing with year, month and Fixnum" do
+ assert Day.new(starting.year, starting.month, starting.day).starting == @object.starting
+ end
+
+ end
+
+ context "when initialized with a year, month and day Fixnum" do
+
+ setup do
+ @object = Year.new(year, month, day)
+ end
+
+ should "be the same starting time as intitializing ActiveTime with a year Fixnum" do
+ assert ActiveTime.new(year, month, day).starting == @object.starting
+ end
+
+ end
+
+ context "when initialized with no args" do
+
+ should "raise ArgumentError" do
+ assert_raise ArgumentError do
+ Day.new
+ end
+ end
+
+ end
+
+ context "when initialized correctly" do
+
+ setup do
+ @object = Day.new(year, month, day)
+ @active_time = ActiveTime.new(year, month, day)
+ end
+
+ should "have a description equal to a similar ActiveTime object" do
+ assert_equal @active_time.description, @object.description
+ end
+
+ should "have a starting time equal to a similar ActiveTime object" do
+ assert_equal @active_time.starting, @object.starting
+ end
+
+ should "have an ending time equal to a similar ActiveTime object" do
+ assert_equal @active_time.ending, @object.ending
+ end
+
+ should "have a range equal to a similar ActiveTime object" do
+ assert_equal @active_time.range, @object.range
+ end
+
+ end
+
+ end
+
+
end

0 comments on commit d3b6b0f

Please sign in to comment.