diff options
Diffstat (limited to 'app/models/calendar.rb')
| -rw-r--r-- | app/models/calendar.rb | 117 |
1 files changed, 99 insertions, 18 deletions
diff --git a/app/models/calendar.rb b/app/models/calendar.rb index 9c228ad69..d616bce10 100644 --- a/app/models/calendar.rb +++ b/app/models/calendar.rb @@ -3,18 +3,23 @@ class Calendar < ActiveRecord::Base validates_presence_of :name, :short_name, :organisation validates_uniqueness_of :short_name - validate :date_not_in_date_ranges, :dates_uniqueness after_initialize :init_dates_and_date_ranges scope :contains_date, ->(date) { where('date ? = any (dates) OR date ? <@ any (date_ranges)', date, date) } + scope :shared, -> { where(shared: true) } + scope :by_organisation(org_id), -> { where(organisation_id: org_id) } def init_dates_and_date_ranges self.dates ||= [] self.date_ranges ||= [] end + def self.ransackable_scopes(auth_object = nil) + [:contains_date] + end + private_class_method :ransackable_scopes class Period include ActiveAttr::Model @@ -23,7 +28,7 @@ class Calendar < ActiveRecord::Base attribute :begin, type: Date attribute :end, type: Date - validates :begin, :end, presence: true + validates_presence_of :begin, :end validate :check_end_greather_than_begin def check_end_greather_than_begin @@ -105,7 +110,7 @@ class Calendar < ActiveRecord::Base periods.each do |period| if period.intersect?(periods) - period.errors.add(:base, I18n.t('calendars.errors.overlapped_period')) + period.errors.add(:base, I18n.t('calendars.errors.overlapped_periods')) periods_are_valid = false end end @@ -141,34 +146,110 @@ class Calendar < ActiveRecord::Base private :clear_periods - def self.new_from from - from.dup.tap do |metadata| - metadata.referential_id = nil +### dates + + class DateValue + include ActiveAttr::Model + + attribute :id, type: Integer + attribute :value, type: Date + + validates_presence_of :value + + def self.from_date(index, date) + DateValue.new id: index, value: date + end + + # Stuff required for coocon + def new_record? + !persisted? end + + def persisted? + id.present? + end + + def mark_for_destruction + self._destroy = true + end + + attribute :_destroy, type: Boolean + alias_method :marked_for_destruction?, :_destroy end - private - def date_not_in_date_ranges - errors.add(:dates, I18n.t('activerecord.errors.models.calendar.attributes.dates.date_in_date_ranges')) if dates && date_ranges && dates_and_date_ranges_overlap? + # Required by coocon + def build_date_value + DateValue.new end - def dates_and_date_ranges_overlap? - overlap = false - dates.each do |date| + def date_values + @date_values ||= init_date_values + end + + def init_date_values + if dates + dates.each_with_index.map { |d, index| DateValue.from_date(index, d) } + else + [] + end + end + private :init_date_values + + validate :validate_date_values + + def validate_date_values + date_values_are_valid = true + + unless date_values.all?(&:valid?) + date_values_are_valid = false + end + + date_values.each do |date_value| + if date_values.count { |d| d.value == date_value.value } > 1 + date_value.errors.add(:base, I18n.t('activerecord.errors.models.calendar.attributes.dates.date_in_dates')) + date_values_are_valid = false + end date_ranges.each do |date_range| - overlap = true if date_range.cover? date + if date_range.cover? date_value.value + date_value.errors.add(:base, I18n.t('activerecord.errors.models.calendar.attributes.dates.date_in_date_ranges')) + date_values_are_valid = false + end end end - overlap + + unless date_values_are_valid + errors.add(:date_values, :invalid) + end end - def dates_uniqueness - errors.add(:dates, I18n.t('activerecord.errors.models.calendar.attributes.dates.date_in_dates')) if dates && dates.length > dates.uniq.length + def date_values_attributes=(attributes = {}) + @date_values = [] + attributes.each do |index, date_value_attribute| + date_value = DateValue.new(date_value_attribute.merge(id: index)) + @date_values << date_value unless date_value.marked_for_destruction? + end + + dates_will_change! end - def self.ransackable_scopes(auth_object = nil) - [:contains_date] + before_validation :fill_dates + + def fill_dates + if @date_values + self.dates = @date_values.map(&:value).compact.sort + end end + + after_save :clear_date_values + + def clear_date_values + @date_values = nil + end + + private :clear_date_values + +### + end class Range |
