mirror of
https://github.com/TracksApp/tracks.git
synced 2025-12-17 15:50:13 +01:00
move model validation into pattern classes and link from recurring_todo model
This commit is contained in:
parent
776a046465
commit
29b815e998
7 changed files with 201 additions and 77 deletions
|
|
@ -29,86 +29,31 @@ class RecurringTodo < ActiveRecord::Base
|
||||||
validates_length_of :description, :maximum => 100
|
validates_length_of :description, :maximum => 100
|
||||||
validates_length_of :notes, :maximum => 60000, :allow_nil => true
|
validates_length_of :notes, :maximum => 60000, :allow_nil => true
|
||||||
|
|
||||||
validate :period_specific_validations
|
validate :period_validation
|
||||||
validate :starts_and_ends_on_validations
|
validate :pattern_specific_validations
|
||||||
validate :set_recurrence_on_validations
|
|
||||||
|
|
||||||
def period_specific_validations
|
def pattern_specific_validations
|
||||||
if %W[daily weekly monthly yearly].include?(recurring_period)
|
if pattern
|
||||||
self.send("validate_#{recurring_period}")
|
pattern.validate
|
||||||
else
|
else
|
||||||
errors.add(:recurring_period, "is an unknown recurrence pattern: '#{recurring_period}'")
|
errors[:recurring_todo] << "Invalid recurrence period '#{recurring_period}'"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_daily
|
def pattern
|
||||||
if (!only_work_days) && daily_every_x_days.blank?
|
if valid_period?
|
||||||
errors[:base] << "Every other nth day may not be empty for recurrence setting"
|
@pattern = eval("RecurringTodos::#{recurring_period.capitalize}RepeatPattern.new(user)")
|
||||||
|
@pattern.build_from_recurring_todo(self)
|
||||||
end
|
end
|
||||||
|
@pattern
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_weekly
|
def valid_period?
|
||||||
if weekly_every_x_week.blank?
|
%W[daily weekly monthly yearly].include?(recurring_period)
|
||||||
errors[:base] << "Every other nth week may not be empty for recurrence setting"
|
|
||||||
end
|
|
||||||
something_set = false
|
|
||||||
%w{sunday monday tuesday wednesday thursday friday saturday}.each { |day| something_set ||= self.send("on_#{day}") }
|
|
||||||
errors[:base] << "You must specify at least one day on which the todo recurs" unless something_set
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_monthly
|
def period_validation
|
||||||
case recurrence_selector
|
errors.add(:recurring_period, "is an unknown recurrence pattern: '#{recurring_period}'") unless valid_period?
|
||||||
when 0 # 'monthly_every_x_day'
|
|
||||||
errors[:base] << "The day of the month may not be empty for recurrence setting" if monthly_every_x_day.blank?
|
|
||||||
errors[:base] << "Every other nth month may not be empty for recurrence setting" if monthly_every_x_month.blank?
|
|
||||||
when 1 # 'monthly_every_xth_day'
|
|
||||||
errors[:base] <<"Every other nth month may not be empty for recurrence setting" if monthly_every_x_month2.blank?
|
|
||||||
errors[:base] <<"The nth day of the month may not be empty for recurrence setting" if monthly_every_xth_day.blank?
|
|
||||||
errors[:base] <<"The day of the month may not be empty for recurrence setting" if monthly_day_of_week.blank?
|
|
||||||
else
|
|
||||||
raise Exception.new, "unexpected value of recurrence selector '#{recurrence_selector}'"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def validate_yearly
|
|
||||||
case recurrence_selector
|
|
||||||
when 0 # 'yearly_every_x_day'
|
|
||||||
errors[:base] << "The month of the year may not be empty for recurrence setting" if yearly_month_of_year.blank?
|
|
||||||
errors[:base] << "The day of the month may not be empty for recurrence setting" if yearly_every_x_day.blank?
|
|
||||||
when 1 # 'yearly_every_xth_day'
|
|
||||||
errors[:base] << "The month of the year may not be empty for recurrence setting" if yearly_month_of_year2.blank?
|
|
||||||
errors[:base] << "The nth day of the month may not be empty for recurrence setting" if yearly_every_xth_day.blank?
|
|
||||||
errors[:base] << "The day of the week may not be empty for recurrence setting" if yearly_day_of_week.blank?
|
|
||||||
else
|
|
||||||
raise Exception.new, "unexpected value of recurrence selector '#{recurrence_selector}'"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def starts_and_ends_on_validations
|
|
||||||
errors[:base] << "The start date needs to be filled in" if start_from.blank?
|
|
||||||
case ends_on
|
|
||||||
when 'ends_on_number_of_times'
|
|
||||||
errors[:base] << "The number of recurrences needs to be filled in for 'Ends on'" if number_of_occurences.blank?
|
|
||||||
when "ends_on_end_date"
|
|
||||||
errors[:base] << "The end date needs to be filled in for 'Ends on'" if end_date.blank?
|
|
||||||
else
|
|
||||||
errors[:base] << "The end of the recurrence is not selected" unless ends_on == "no_end_date"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
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'
|
|
||||||
errors[:base] << "Please select when to show the action" if show_always.nil?
|
|
||||||
unless show_always
|
|
||||||
errors[:base] << "Please fill in the number of days to show the todo before the due date" if show_from_delta.blank?
|
|
||||||
end
|
|
||||||
else
|
|
||||||
raise Exception.new, "unexpected value of recurrence target selector '#{target}'"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# the following recurrence patterns can be stored:
|
# the following recurrence patterns can be stored:
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,30 @@ module RecurringTodos
|
||||||
@user = user
|
@user = user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def start_from
|
||||||
|
get :start_from
|
||||||
|
end
|
||||||
|
|
||||||
|
def end_date
|
||||||
|
get :end_date
|
||||||
|
end
|
||||||
|
|
||||||
|
def ends_on
|
||||||
|
get :ends_on
|
||||||
|
end
|
||||||
|
|
||||||
|
def target
|
||||||
|
get :target
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_always
|
||||||
|
get :show_always
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_from_delta
|
||||||
|
get :show_from_delta
|
||||||
|
end
|
||||||
|
|
||||||
def build_recurring_todo(attributes)
|
def build_recurring_todo(attributes)
|
||||||
@recurring_todo = @user.recurring_todos.build(attributes)
|
@recurring_todo = @user.recurring_todos.build(attributes)
|
||||||
end
|
end
|
||||||
|
|
@ -17,6 +41,52 @@ module RecurringTodos
|
||||||
recurring_todo
|
recurring_todo
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def build_from_recurring_todo(recurring_todo)
|
||||||
|
@recurring_todo = recurring_todo
|
||||||
|
@attributes = recurring_todo.attributes
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate
|
||||||
|
starts_and_ends_on_validations
|
||||||
|
set_recurrence_on_validations
|
||||||
|
end
|
||||||
|
|
||||||
|
def starts_and_ends_on_validations
|
||||||
|
errors[:base] << "The start date needs to be filled in" if start_from.blank?
|
||||||
|
case ends_on
|
||||||
|
when 'ends_on_number_of_times'
|
||||||
|
errors[:base] << "The number of recurrences needs to be filled in for 'Ends on'" if number_of_occurences.blank?
|
||||||
|
when "ends_on_end_date"
|
||||||
|
errors[:base] << "The end date needs to be filled in for 'Ends on'" if end_date.blank?
|
||||||
|
else
|
||||||
|
errors[:base] << "The end of the recurrence is not selected" unless ends_on == "no_end_date"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
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'
|
||||||
|
errors[:base] << "Please select when to show the action" if show_always.nil?
|
||||||
|
unless show_always
|
||||||
|
errors[:base] << "Please fill in the number of days to show the todo before the due date" if show_from_delta.blank?
|
||||||
|
end
|
||||||
|
else
|
||||||
|
raise Exception.new, "unexpected value of recurrence target selector '#{target}'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def errors
|
||||||
|
@recurring_todo.errors
|
||||||
|
end
|
||||||
|
|
||||||
|
def get attribute
|
||||||
|
# handle attribute as symbol and as string
|
||||||
|
@attributes[attribute] || @attributes[attribute.to_s]
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
@ -7,9 +7,19 @@ module RecurringTodos
|
||||||
end
|
end
|
||||||
|
|
||||||
def every_x_days
|
def every_x_days
|
||||||
@recurring_todo.every_other1
|
get :every_other1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def only_work_days?
|
||||||
|
get :only_work_days
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate
|
||||||
|
super
|
||||||
|
errors[:base] << "Every other nth day may not be empty for this daily recurrence setting" if (!only_work_days?) && every_x_days.blank?
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
@ -6,12 +6,49 @@ module RecurringTodos
|
||||||
super user
|
super user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def recurrence_selector
|
||||||
|
get :recurrence_selector
|
||||||
|
end
|
||||||
|
|
||||||
def every_x_day?
|
def every_x_day?
|
||||||
@recurring_todo.recurrence_selector == 0
|
get(:recurrence_selector) == 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def every_xth_day?
|
def every_xth_day?
|
||||||
@recurring_todo.recurrence_selector == 1
|
get(:recurrence_selector) == 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def every_x_month
|
||||||
|
# in case monthly pattern is every day x, return every_other2 otherwise
|
||||||
|
# return a default value
|
||||||
|
get(:recurrence_selector) == 0 ? get(:every_other2) : 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def every_x_month2
|
||||||
|
# in case monthly pattern is every xth day, return every_other2 otherwise
|
||||||
|
# return a default value
|
||||||
|
get(:recurrence_selector) == 1 ? get(:every_other2) : 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def every_xth_day(default=nil)
|
||||||
|
get(:every_other3) || default
|
||||||
|
end
|
||||||
|
|
||||||
|
def day_of_week
|
||||||
|
get :every_count
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate
|
||||||
|
super
|
||||||
|
case recurrence_selector
|
||||||
|
when 0 # 'monthly_every_x_day'
|
||||||
|
errors[:base] << "Every other nth month may not be empty for recurrence setting" if every_x_month.blank?
|
||||||
|
when 1 # 'every_xth_day'
|
||||||
|
errors[:base] <<"Every other nth month may not be empty for recurrence setting" if every_x_month2.blank?
|
||||||
|
errors[:base] <<"The day of the month may not be empty for recurrence setting" if day_of_week.blank?
|
||||||
|
else
|
||||||
|
raise Exception.new, "unexpected value of recurrence selector '#{recurrence_selector}'"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,27 @@ module RecurringTodos
|
||||||
super user
|
super user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def every_x_week
|
||||||
|
get :every_other1
|
||||||
|
end
|
||||||
|
|
||||||
|
{ monday: 1, tuesday: 2, wednesday: 3, thursday: 4, friday: 5, saturday: 6, sunday: 0 }.each do |day, number|
|
||||||
|
define_method("on_#{day}") do
|
||||||
|
on_xday number
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_xday(n)
|
||||||
|
get(:every_day) && get(:every_day)[n, 1] != ' '
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate
|
||||||
|
super
|
||||||
|
errors[:base] << "Every other nth week may not be empty for weekly recurrence setting" if every_x_week.blank?
|
||||||
|
something_set = %w{sunday monday tuesday wednesday thursday friday saturday}.inject(false) { |set, day| set || self.send("on_#{day}") }
|
||||||
|
errors[:base] << "You must specify at least one day on which the todo recurs" unless something_set
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
@ -6,6 +6,47 @@ module RecurringTodos
|
||||||
super user
|
super user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def recurrence_selector
|
||||||
|
get :recurrence_selector
|
||||||
|
end
|
||||||
|
|
||||||
|
def month_of_year
|
||||||
|
get :every_other2
|
||||||
|
end
|
||||||
|
|
||||||
|
def every_x_day
|
||||||
|
get :every_other1
|
||||||
|
end
|
||||||
|
|
||||||
|
def every_xth_day
|
||||||
|
get :every_other3
|
||||||
|
end
|
||||||
|
|
||||||
|
def day_of_week
|
||||||
|
get :every_count
|
||||||
|
end
|
||||||
|
|
||||||
|
def month_of_year2
|
||||||
|
# if recurrence pattern is every xth day in a month, return month otherwise
|
||||||
|
# return a default value
|
||||||
|
get(:recurrence_selector) == 1 ? get(:every_other2) : Time.zone.now.month
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate
|
||||||
|
super
|
||||||
|
case recurrence_selector
|
||||||
|
when 0 # 'yearly_every_x_day'
|
||||||
|
errors[:base] << "The month of the year may not be empty for recurrence setting" if month_of_year.blank?
|
||||||
|
errors[:base] << "The day of the month may not be empty for recurrence setting" if every_x_day.blank?
|
||||||
|
when 1 # 'yearly_every_xth_day'
|
||||||
|
errors[:base] << "The month of the year may not be empty for recurrence setting" if month_of_year2.blank?
|
||||||
|
errors[:base] << "The nth day of the month may not be empty for recurrence setting" if every_xth_day.blank?
|
||||||
|
errors[:base] << "The day of the week may not be empty for recurrence setting" if day_of_week.blank?
|
||||||
|
else
|
||||||
|
raise "unexpected value of recurrence selector '#{recurrence_selector}'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
@ -277,7 +277,7 @@ class RecurringTodoTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
def test_toggle_completion
|
def test_toggle_completion
|
||||||
assert @yearly.active?
|
assert @yearly.active?
|
||||||
assert @yearly.toggle_completion!
|
assert @yearly.toggle_completion!, "toggle of completion should succeed"
|
||||||
assert @yearly.completed?
|
assert @yearly.completed?
|
||||||
|
|
||||||
# entering completed state should set completed_at
|
# entering completed state should set completed_at
|
||||||
|
|
@ -329,7 +329,7 @@ class RecurringTodoTest < ActiveSupport::TestCase
|
||||||
assert_raise(Exception){ @every_month.valid? }
|
assert_raise(Exception){ @every_month.valid? }
|
||||||
|
|
||||||
@yearly.recurrence_selector = 99
|
@yearly.recurrence_selector = 99
|
||||||
assert_raise(Exception){ @yearly.valid? }
|
assert_raise(RuntimeError){ @yearly.valid? }
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_every_n_the_day_must_be_filled
|
def test_every_n_the_day_must_be_filled
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue