Sunday, August 31, 2014

Ruby Date & DateTime class extension

My recent user story demanded me to extend Date and  DateTime classes to support few more methods.

Following is the code and this is done using Ruby's Dynamic Proxy Technique.

=begin
Author: Vigram K
Date: 27th August 2014
Title: Extension for Date & DateTime classes
Adds following methods for date object,
first_monday_of_month, first_tuesday_of_month .. first_sunday_of_month
last_monday_of_month, last_tuesday_of_month .. last_sunday_of_month
monday_of_week, tuesday_of_week .. sunday_of_week
Usages:
date = Date.today #=> Wed, 27 Aug 2014
date.first_monday_of_month #=> Mon, 04 Aug 2014
date.last_friday_of_month #=> Fri, 29 Aug 2014
date.tuesday_of_week #=> Tue, 26 Aug 2014
=end
module InstanceMethods
def self.included(base)
base.class_eval do
def last_date_of_month
@last_date_of_month ||= self.class.new(year, month, -1)
end
def first_date_of_month
@first_date_of_month ||= self.class.new(year, month, 1)
end
# Dynamic Proxy
def method_missing(method, *args, &block)
case
when method.match(/^(first|last)_(.+)_of_month$/)
if $1 == "last"
send("#{$1}_date_of_month").downto(0).find {|day| day.send("#{$2}?") }
else
send("#{$1}_date_of_month").upto(10000000).find {|day| day.send("#{$2}?") }
end
when method.match(/^(monday|tuesday|wednesday|thursday|friday)_of_week$/)
(beginning_of_week .. end_of_week).find{|day| day.send("#{$1}?")}
else
super
end
end
end
end
end
class Date
include InstanceMethods
end
class DateTime
include InstanceMethods
end
view raw date.rb hosted with ❤ by GitHub
Copy above date.rb file and keep it under initializer directory of your Rails application.