Class: Streak
- Inherits:
-
Object
- Object
- Streak
- Defined in:
- lib/streakable/streak.rb
Overview
Represents a streak of calendar days as computed by a date column on an association.
So for example if you have a User that has_many :posts, then Streak.new(user, :posts, :created_at).length will tell you how many consecutive days a given user created posts.
Instance Attribute Summary collapse
-
#association ⇒ Object
readonly
the AR association through which we want to grab a column to caculate a streak.
-
#column ⇒ Object
readonly
an AR column resolving to a date.
-
#except_today ⇒ Object
readonly
whether to include today in the streak length calculation or not.
-
#instance ⇒ Object
readonly
the base ActiveRecord object instance for this streak calculation.
Instance Method Summary collapse
-
#initialize(instance, association, column, except_today: false) ⇒ Streak
constructor
Creates a new Streak.
-
#length(longest: false) ⇒ Object
Calculate the length of this calendar day streak.
-
#streaks ⇒ Object
Get a list of all calendar day streaks, sorted descending (from most recent to farthest away) Includes 1-day streaks.
Constructor Details
#initialize(instance, association, column, except_today: false) ⇒ Streak
Creates a new Streak
28 29 30 31 32 33 34 |
# File 'lib/streakable/streak.rb', line 28 def initialize(instance, association, column, except_today: false) @instance = instance @association = association @column = column # Don't penalize the current day being absent when determining streaks @except_today = except_today end |
Instance Attribute Details
#association ⇒ Object (readonly)
the AR association through which we want to grab a column to caculate a streak
12 13 14 |
# File 'lib/streakable/streak.rb', line 12 def association @association end |
#column ⇒ Object (readonly)
an AR column resolving to a date. the column that we want to calculate a calendar date streak against
15 16 17 |
# File 'lib/streakable/streak.rb', line 15 def column @column end |
#except_today ⇒ Object (readonly)
whether to include today in the streak length calculation or not. If this is true, then you are assuming there is still time today for the streak to be extended
20 21 22 |
# File 'lib/streakable/streak.rb', line 20 def except_today @except_today end |
#instance ⇒ Object (readonly)
the base ActiveRecord object instance for this streak calculation
9 10 11 |
# File 'lib/streakable/streak.rb', line 9 def instance @instance end |
Instance Method Details
#length(longest: false) ⇒ Object
Calculate the length of this calendar day streak
not just the current one
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/streakable/streak.rb', line 40 def length(longest: false) # no streaks if streaks.empty? 0 # calculate the longest one? elsif longest streaks.sort do |x, y| y.size <=> x.size end.first.size # default streak calculation else # pull the first streak streak = streaks.first # either the streak includes today, # or we don't care about today and it includes yesterday if streak.include?(Date.current) || except_today && streak.include?(Date.current - 1.day) streak.size else 0 end end end |
#streaks ⇒ Object
Get a list of all calendar day streaks, sorted descending (from most recent to farthest away) Includes 1-day streaks. If you want to filter the results further, for example if you want 2 only include 2+ day streaks, you’ll have to filter on the result
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/streakable/streak.rb', line 71 def streaks return [] if days.empty? streaks = [] streak = [] days.each.with_index do |day, i| # first day if i == 0 # since this is the first one, # push to our new streak streak << day # consecutive day, the previous day was "tomorrow" # relative to day (since we're date descending) elsif days[i-1] == (day+1.day) # push to existing streak streak << day # streak was broken else # push our current streak streaks << streak # start a new streak # and push day to our new streak streak = [] streak << day end # the jig is up, push the current streak if i == (days.size-1) streaks << streak end end streaks end |