Module: EdtfRails

Defined in:
lib/edtf-rails/constants.rb,
lib/edtf-rails/edtf-rails.rb

Constant Summary collapse

EDTF_STRING_FORMAT =
/\A(\d{4})$|^(\d{4}-(0[1-9]|1[012]))$|^(\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]))\z/
USE_ATTRIBUTE_ACCESSIBLE =
Gem::Specification.find_by_name('activerecord').version < Gem::Version.new('4')

Instance Method Summary collapse

Instance Method Details

#edtf(options = {}) ⇒ Object



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
# File 'lib/edtf-rails/edtf-rails.rb', line 3

def edtf options = {}

  admitted_keys = [:attributes]
  check_options(options, admitted_keys)

  class_attribute :edtf_attributes
  self.edtf_attributes = [options[:attributes]].flatten

  validates_format_of edtf_attributes, :with => EDTF_STRING_FORMAT, :allow_nil => true

  edtf_attributes.each do |d|

    attr_accessible(d.to_sym) if USE_ATTRIBUTE_ACCESSIBLE
    
    # getters
    define_method(d) do
      # read_attribute(d) && (EDTF.parse(read_attribute(d)) || read_attribute(d)) #if the format is not EDTF compatible the string will be returned (validation call this getter and need a value)
      EDTF.parse(read_attribute(d)) || read_attribute(d)
    end

    # virtual attributes dob_y, dob_m....
    [:y, :m, :d].each do |xx|
      attr_accessor "#{d}_#{xx}"
      attr_accessible("#{d}_#{xx}".to_sym) if USE_ATTRIBUTE_ACCESSIBLE
    end 

    # setters
    define_method("#{d}=") do |edtf_date|
      edtf_date = edtf_date.edtf if edtf_date.is_a? Date
      transaction do

        write_attribute(d,edtf_date)
        
        # virtual attributes settings after any assignment (including initialization)
        date_array = read_attribute(d).to_s.split('-')
        [:y, :m, :d].each_with_index do |x,i|
          send("#{d}_#{x}=",date_array[i])
        end
      
      end
    end
    
  end

  # virtual attributes utilization to set date before validation (they are used only if at least one of them is defined)
  before_validation do
    edtf_attributes.each do |d|
      date_array = [:y, :m, :d].map{|x| send("#{d}_#{x}")}
      self[d]= if (res = date_array.shift).present? #they are used only if at least one of them is defined
        date_array.each{|x| x.blank? ? break : (res += "-#{x}") }
        res
      else
        nil
      end
    end
  end

  # virtual attributes settings after any initialization
  after_initialize do
    unless new_record?
      edtf_attributes.each do |d|
        date_array = read_attribute(d).to_s.split('-')
        [:y, :m, :d].each_with_index do |x,i|
          send("#{d}_#{x}=",date_array[i])
        end
      end
    end
  end

end