diff options
| -rw-r--r-- | app/models/calendar.rb | 13 | ||||
| -rw-r--r-- | app/models/calendar/calendar_date.rb | 25 | ||||
| -rw-r--r-- | app/models/calendar/date_value.rb | 13 | ||||
| -rw-r--r-- | app/models/calendar/period.rb | 16 | ||||
| -rw-r--r-- | config/locales/calendars.en.yml | 1 | ||||
| -rw-r--r-- | config/locales/calendars.fr.yml | 1 | ||||
| -rw-r--r-- | spec/models/calendar/calendar_date_spec.rb | 38 |
7 files changed, 90 insertions, 17 deletions
diff --git a/app/models/calendar.rb b/app/models/calendar.rb index 215b13bb7..3307cfe2f 100644 --- a/app/models/calendar.rb +++ b/app/models/calendar.rb @@ -1,5 +1,8 @@ require 'range_ext' class Calendar < ActiveRecord::Base + + NullDate = Date.new + belongs_to :organisation has_many :time_tables @@ -51,11 +54,7 @@ class Calendar < ActiveRecord::Base validate :validate_periods def validate_periods - periods_are_valid = true - - unless periods.all?(&:valid?) - periods_are_valid = false - end + periods_are_valid = periods.all?(&:valid?) periods.each do |period| if period.intersect?(periods) @@ -71,9 +70,9 @@ class Calendar < ActiveRecord::Base def flatten_date_array attributes, key date_int = %w(1 2 3).map {|e| attributes["#{key}(#{e}i)"].to_i } - Date.new(*date_int) + ::Date.new(*date_int) rescue - nil + Calendar::CalendarDate.new(*date_int) end def periods_attributes=(attributes = {}) diff --git a/app/models/calendar/calendar_date.rb b/app/models/calendar/calendar_date.rb new file mode 100644 index 000000000..b7c080db2 --- /dev/null +++ b/app/models/calendar/calendar_date.rb @@ -0,0 +1,25 @@ +class Calendar + class CalendarDate < ::Date + + module IllegalDate + attr_reader :year, :month, :day + def to_s + "%d-%02d-%02d" % [year, month, day] + end + end + + def self.new(*args) + super(*args) + rescue + o = allocate() + o.instance_exec do + @illegal = true + @year, @month, @day = args + extend IllegalDate + end + o + end + + def legal?; !!!@illegal end + end +end diff --git a/app/models/calendar/date_value.rb b/app/models/calendar/date_value.rb index 9dfa7e5f3..1bfa34c0e 100644 --- a/app/models/calendar/date_value.rb +++ b/app/models/calendar/date_value.rb @@ -4,14 +4,9 @@ class Calendar::DateValue attribute :id, type: Integer attribute :value, type: Date - validate :validate + validates_presence_of :value + validate :validate_date - def initialize(atts={}) - super( atts.slice(:id, :value) ) - # date stored for error message - @date = atts.slice(*%w{value(3i) value(2i) value(1i)}).values.join("/") - end - def self.from_date(index, date) DateValue.new id: index, value: date end @@ -29,8 +24,8 @@ class Calendar::DateValue self._destroy = true end - def validate - errors.add(:value, "Illegal Date #{@date}") if value.blank? + def validate_date + errors.add(:value, I18n.t('activerecord.errors.models.calendar.attributes.dates.illegal_date', date: value.to_s)) unless value.legal? end attribute :_destroy, type: Boolean diff --git a/app/models/calendar/period.rb b/app/models/calendar/period.rb index 0f1902e59..5078f2db3 100644 --- a/app/models/calendar/period.rb +++ b/app/models/calendar/period.rb @@ -5,8 +5,9 @@ class Calendar::Period attribute :begin, type: Date attribute :end, type: Date - validates_presence_of :begin, :end validate :check_end_greather_than_begin + validates_presence_of :begin, :end + validate :validate_dates def check_end_greather_than_begin if self.begin and self.end and self.begin > self.end @@ -37,6 +38,19 @@ class Calendar::Period end end + def validate_dates + validate_begin + validate_end + end + + def validate_begin + errors.add(:begin, I18n.t('activerecord.errors.models.calendar.attributes.dates.illegal_date', date: self.begin.to_s)) unless self.begin.legal? + end + + def validate_end + errors.add(:end, I18n.t('activerecord.errors.models.calendar.attributes.dates.illegal_date', date: self.end.to_s)) unless self.end.legal? + end + def cover? date range.cover? date end diff --git a/config/locales/calendars.en.yml b/config/locales/calendars.en.yml index 26ca913b6..456501b48 100644 --- a/config/locales/calendars.en.yml +++ b/config/locales/calendars.en.yml @@ -57,3 +57,4 @@ en: dates: date_in_date_ranges: A date can not be in Dates and in Date ranges. date_in_dates: A date can appear only once in the list of dates. + illegal_date: The date %{date} does not exist. diff --git a/config/locales/calendars.fr.yml b/config/locales/calendars.fr.yml index fe16cbfed..44b474045 100644 --- a/config/locales/calendars.fr.yml +++ b/config/locales/calendars.fr.yml @@ -70,3 +70,4 @@ fr: dates: date_in_date_ranges: Une même date ne peut pas être incluse à la fois dans la liste et dans les intervalles de dates. date_in_dates: Une même date ne peut pas être incluse plusieurs fois dans la liste. + illegal_date: La date %{date} n'existe pas. diff --git a/spec/models/calendar/calendar_date_spec.rb b/spec/models/calendar/calendar_date_spec.rb new file mode 100644 index 000000000..25fe8ba8d --- /dev/null +++ b/spec/models/calendar/calendar_date_spec.rb @@ -0,0 +1,38 @@ +RSpec.describe Calendar::CalendarDate do + + subject { described_class.new(year, month, day) } + let( :year ){ 2000 } + let( :month ){ 2 } + + let( :str_repr ){ %r{#{year}-0?#{month}-0?#{day}} } + + + + shared_examples_for "date accessors" do + it "accesses year" do + expect( subject.year ).to eq(year) + end + it "accesses month" do + expect( subject.month ).to eq(month) + end + it "accesses day" do + expect( subject.day ).to eq(day) + end + it "converts to a string" do + expect( subject.to_s ).to match(str_repr) + end + end + + context 'legal' do + let( :day ){ 29 } + it { expect_it.to be_legal } + it_should_behave_like "date accessors" + end + + context 'illegal' do + let( :day ){ 30 } + it { expect_it.not_to be_legal } + it_should_behave_like "date accessors" + end + +end |
