aboutsummaryrefslogtreecommitdiffstats
path: root/app/models/concerns/period_support.rb
blob: e17451fe48f773ff35966dcb551e4cc2a4c370b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
module PeriodSupport
  extend ActiveSupport::Concern

  included do
    after_initialize :init_date_ranges

    def init_date_ranges
      self.date_ranges ||= []
    end

    ### Calendar::Period
    # Required by coocon
    def build_period
      Calendar::Period.new
    end

    def periods
      @periods ||= init_periods
    end

    def init_periods
      (date_ranges || [])
        .each_with_index
        .map( &Calendar::Period.method(:from_range) )
    end
    private :init_periods

    validate :validate_periods

    def validate_periods
      periods_are_valid = periods.all?(&:valid?)

      periods.each do |period|
        if period.intersect?(periods)
          period.errors.add(:base, I18n.t('calendars.errors.overlapped_periods'))
          periods_are_valid = false
        end
      end

      unless periods_are_valid
        errors.add(:periods, :invalid)
      end
    end

    def flatten_date_array attributes, key
      date_int = %w(1 2 3).map {|e| attributes["#{key}(#{e}i)"].to_i }
      Date.new(*date_int)
    end

    def periods_attributes=(attributes = {})
      @periods = []
      attributes.each do |index, period_attribute|
        # Convert date_select to date
        ['begin', 'end'].map do |attr|
          period_attribute[attr] = flatten_date_array(period_attribute, attr)
        end
        period = Calendar::Period.new(period_attribute.merge(id: index))
        @periods << period unless period.marked_for_destruction?
      end

      date_ranges_will_change!
    end

    before_validation :fill_date_ranges

    def fill_date_ranges
      if @periods
        self.date_ranges = @periods.map(&:range).compact.sort_by(&:begin)
      end
    end

    after_save :clear_periods

    def clear_periods
      @periods = nil
    end

    private :clear_periods
  end
end