W jednym z poprzednich postów pokazywałem przykład zastosowania obiektu Range w Ruby. Ruby on Rails posiada własne rozszerzenie klasy Date, dzięki czemu bardzo wygodnie pracuje się z datami. Zero parsowania, zero konwersji, piszemy nasze helpery do obsługi dat, jak język naturalny, przez co kod możemy czytać płynnym angielski i momentami zapomnieć, że mamy do czynienia z językiem programowania. Dzisiaj pokażę Ci jak wykorzystać kombinację klas Range i Date w Ruby on Rails, żeby stworzyć czytelne sprawdzanie dat.
Specyfika Ruby pozwala na jeszcze jedną super rzecz – rozszerzanie corowych klas. W tym przykładzie rozszerzymy klasę Date dostarczaną przez Ruby on Rails.
Case:
W różnego rodzaju modułach raportowych lub dashboardach można spotkać się z operacjami polegającymi na porównywaniu dat, filtrowaniu dat z poprzedniego roku, miesiąca, tygodnia. Praca z datami w RoR i tak jest super przyjemna, ale poniższy snippet sprawi, że staje się jeszcze przyjemniejsza.
class Date
def is_in? range
range.include? self
end
class << self
def today
Date.current
end
def previous_year
today.prev_year.beginning_of_year..today.prev_year.end_of_year
end
def current_year
today.beginning_of_year..today.end_of_year
end
def previous_month
today.prev_month.beginning_of_month..today.prev_month.end_of_month
end
def current_month
today.beginning_of_month..today.end_of_month
end
def previous_week
today.prev_week.beginning_of_week..today.prev_week.end_of_week
end
def current_week
today.beginning_of_week..today.end_of_week
end
end
end
Rozszerzamy tutaj klasę Date
.
W pierwszej kolejności deklaruję metodę instancji, która będzie sprawdzać czy data zawiera się w podanym zakresie. Jest to metoda instancji, czyli będzie wywoływania na instancji lub mówiąc prościej – bezpośrednio na dacie.
def is_in? range
range.include? self
end
Następnie rozszerzam klasę Date
o metody statyczne.
Nadpisuję metodę today
.
def today
Date.current
end
Tworzę metodę previous_year
z wykorzystaniem Range, która zwraca zakres dat dla poprzedniego roku.
def previous_year
today.prev_year.beginning_of_year..today.prev_year.end_of_year
end
Następnie tworzę metodę current_year
, która zwraca zakres dat dla bieżącego roku.
def current_year
today.beginning_of_year..today.end_of_year
end
W dalszej kolejności metody previous_month
, current_month
, previous_week
i current_week
.
def previous_month
today.prev_month.beginning_of_month..today.prev_month.end_of_month
end
def current_month
today.beginning_of_month..today.end_of_month
end
def previous_week
today.prev_week.beginning_of_week..today.prev_week.end_of_week
end
def current_week
today.beginning_of_week..today.end_of_week
end
Po stworzeniu tych pomocniczych metod możemy z łatwością pisać warunki sprawdzające daty.
Date.today.is_in?(Date.current_week)
invoice.date.is_in?(Date.previous_year)
Date.current_week.include?(report.date)
Połączenie klas Range
i Date
w Ruby on Rails to dobry pomysł na poprawę czytelności kodu.
W dokumentacji przeczytasz o klasie Range i o klasie Date.