Class: RecurringTodos::AbstractRecurrencePattern

Inherits:
Object
  • Object
show all
Defined in:
app/models/recurring_todos/abstract_recurrence_pattern.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(user) ⇒ AbstractRecurrencePattern

Returns a new instance of AbstractRecurrencePattern.



5
6
7
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 5

def initialize(user)
  @user = user
end

Instance Attribute Details

#attributesObject

Returns the value of attribute attributes.



3
4
5
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 3

def attributes
  @attributes
end

Instance Method Details

#build_from_recurring_todo(recurring_todo) ⇒ Object



73
74
75
76
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 73

def build_from_recurring_todo(recurring_todo)
  @recurring_todo = recurring_todo
  @attributes = Tracks::AttributeHandler.new(@user, recurring_todo.attributes)
end

#build_recurring_todo(attribute_handler) ⇒ Object



64
65
66
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 64

def build_recurring_todo(attribute_handler)
  @recurring_todo = @user.recurring_todos.build(attribute_handler.safe_attributes)
end

#continues_recurring?(previous) ⇒ Boolean

Returns:

  • (Boolean)


159
160
161
162
163
164
165
166
167
168
169
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 159

def continues_recurring?(previous)
  return @recurring_todo.occurrences_count < @recurring_todo.number_of_occurrences unless @recurring_todo.number_of_occurrences.nil?
  return true if end_date.nil? || ends_on == 'no_end_date'

  case target
  when 'due_date'
    get_due_date(previous) <= end_date
  when 'show_from_date'
    get_show_from_date(previous) <= end_date
  end
end

#day_of_week_as_text(day) ⇒ Object



56
57
58
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 56

def day_of_week_as_text(day)
  day.nil? ? '??' : I18n.t('todos.recurrence.pattern.day_names')[day]
end

#determine_start(previous, offset = 0.day) ⇒ Object (private)

Determine start date to calculate next date for recurring todo which takes start_from and previous into account. offset needs to be 1.day for daily patterns or the start will be the same day as the previous



177
178
179
180
181
182
183
184
185
186
187
188
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 177

def determine_start(previous, offset = 0.day)
  start = start_from || NullTime.new
  if previous
    # check if the start_from date is later than previous. If so, use
    # start_from as start to search for next date
    start > previous ? start : previous + offset
  else
    # skip to present
    now = Time.zone.now
    start > now ? start : now
  end
end

#end_dateObject



13
14
15
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 13

def end_date
  get :end_date
end

#ends_onObject



17
18
19
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 17

def ends_on
  get :ends_on
end

#errorsObject



120
121
122
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 120

def errors
  @recurring_todo.errors
end

#find_last_day_x_of_month(weekday, month, year) ⇒ Object (private)



203
204
205
206
207
208
209
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 203

def find_last_day_x_of_month(weekday, month, year)
  last_day = Time.zone.local(year, month, Time.days_in_month(month))
  while last_day.wday != weekday
    last_day -= 1.day
  end
  last_day
end

#find_xth_day_of_month(x, weekday, month, year) ⇒ Object (private)



211
212
213
214
215
216
217
218
219
220
221
222
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 211

def find_xth_day_of_month(x, weekday, month, year)
  start = Time.zone.local(year, month, 1)
  n = x
  while n > 0
    while start.wday() != weekday
      start += 1.day
    end
    n -= 1
    start += 1.day unless n == 0
  end
  start
end

#get(attribute) ⇒ Object



124
125
126
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 124

def get(attribute)
  @attributes[attribute]
end

#get_due_date(previous) ⇒ Object

gets the next due date. returns nil if recurrence_target is not ‘due_date’



129
130
131
132
133
134
135
136
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 129

def get_due_date(previous)
  case target
  when 'due_date'
    get_next_date(previous).at_midnight
  when 'show_from_date'
    nil
  end
end

#get_next_date(previous) ⇒ Object



155
156
157
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 155

def get_next_date(previous)
  raise "Should not call AbstractRecurrencePattern.get_next_date directly. Override in subclass"
end

#get_show_from_date(previous) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 138

def get_show_from_date(previous)
  case target
  when 'due_date'
    # so set show from date relative to due date unless show_always is true or show_from_delta is nil
    return nil unless put_in_tickler?
    get_due_date(previous) - show_from_delta.days
  when 'show_from_date'
    # Leave due date empty
    get_next_date(previous).at_midnight
  end
end

#get_xth_day_of_month(x, weekday, month, year) ⇒ Object (private)

Example: get 3rd (x) wednesday (weekday) of december (month) 2014 (year) 5th means last, so it will return the 4th if there is no 5th



192
193
194
195
196
197
198
199
200
201
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 192

def get_xth_day_of_month(x, weekday, month, year)
  raise "Weekday should be between 0 and 6 with 0=sunday. You supplied #{weekday}" unless (0..6).cover?(weekday)
  raise "x should be 1-4 for first-fourth or 5 for last. You supplied #{x}" unless (0..5).cover?(x)

  if x == 5
    return find_last_day_x_of_month(weekday, month, year)
  else
    return find_xth_day_of_month(x, weekday, month, year)
  end
end

#month_of_year_as_text(month) ⇒ Object



60
61
62
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 60

def month_of_year_as_text(month)
  month.nil? ? '??' : I18n.t('todos.recurrence.pattern.month_names')[month]
end

#number_of_occurrencesObject



33
34
35
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 33

def number_of_occurrences
  get :number_of_occurrences
end

#put_in_tickler?Boolean

checks if the next todos should be put in the tickler for recurrence_target == ‘due_date’

Returns:

  • (Boolean)


151
152
153
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 151

def put_in_tickler?
  !(show_always? || show_from_delta.nil?)
end

#recurrence_patternObject



41
42
43
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 41

def recurrence_pattern
  raise "Should not call AbstractRecurrencePattern.recurrence_pattern directly. Overwrite in subclass"
end

#recurring_target_as_textObject



37
38
39
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 37

def recurring_target_as_text
  target == 'due_date' ? I18n.t("todos.recurrence.pattern.due") : I18n.t("todos.recurrence.pattern.show")
end

#set_recurrence_on_validationsObject



107
108
109
110
111
112
113
114
115
116
117
118
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 107

def set_recurrence_on_validations
  # show always or x days before due date. x not null
  case target
  when 'show_from_date'
    # no validations
  when 'due_date'
    validate_not_nil(show_always?, "Please select when to show the action")
    validate_not_blank(show_from_delta, "Please fill in the number of days to show the todo before the due date") unless show_always?
  else
    errors.add(:base, "Unexpected value of recurrence target selector '#{target}'")
  end
end

#show_always?Boolean

Returns:

  • (Boolean)


25
26
27
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 25

def show_always?
  get :show_always
end

#show_from_deltaObject



29
30
31
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 29

def show_from_delta
  get :show_from_delta
end

#start_fromObject



9
10
11
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 9

def start_from
  get :start_from
end

#starts_and_ends_on_validationsObject



95
96
97
98
99
100
101
102
103
104
105
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 95

def starts_and_ends_on_validations
  validate_not_blank(start_from, "The start date needs to be filled in")
  case ends_on
  when 'ends_on_number_of_times'
    validate_not_blank(number_of_occurrences, "The number of recurrences needs to be filled in for 'Ends on'")
  when "ends_on_end_date"
    validate_not_blank(end_date, "The end date needs to be filled in for 'Ends on'")
  else
    errors.add(:base, "The end of the recurrence is not selected") unless ends_on == "no_end_date"
  end
end

#targetObject



21
22
23
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 21

def target
  get :target
end

#update_recurring_todo(recurring_todo, attribute_handler) ⇒ Object



68
69
70
71
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 68

def update_recurring_todo(recurring_todo, attribute_handler)
  recurring_todo.assign_attributes(attribute_handler.safe_attributes)
  recurring_todo
end

#valid?Boolean

Returns:

  • (Boolean)


78
79
80
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 78

def valid?
  @recurring_todo.valid?
end

#validateObject



90
91
92
93
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 90

def validate
  starts_and_ends_on_validations
  set_recurrence_on_validations
end

#validate_not_blank(object, msg) ⇒ Object



82
83
84
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 82

def validate_not_blank(object, msg)
  errors.add(:base, msg) if object.blank?
end

#validate_not_nil(object, msg) ⇒ Object



86
87
88
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 86

def validate_not_nil(object, msg)
  errors.add(:base, msg) if object.nil?
end

#xth(x) ⇒ Object



45
46
47
48
49
50
51
52
53
54
# File 'app/models/recurring_todos/abstract_recurrence_pattern.rb', line 45

def xth(x)
  xth_day = [
    I18n.t('todos.recurrence.pattern.first'),
    I18n.t('todos.recurrence.pattern.second'),
    I18n.t('todos.recurrence.pattern.third'),
    I18n.t('todos.recurrence.pattern.fourth'),
    I18n.t('todos.recurrence.pattern.last'),
  ]
  x.nil? ? '??' : xth_day[x - 1]
end