validates_timeliness 2.2.2 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,33 +1,37 @@
1
+ #TODO remove deprecated option :equal_to
1
2
  module ValidatesTimeliness
2
3
 
3
4
  class Validator
5
+ cattr_accessor :error_value_formats
4
6
  cattr_accessor :ignore_restriction_errors
5
7
  self.ignore_restriction_errors = false
6
8
 
7
9
  RESTRICTION_METHODS = {
10
+ :is_at => :==,
8
11
  :equal_to => :==,
9
- :before => :<,
10
- :after => :>,
12
+ :before => :<,
13
+ :after => :>,
11
14
  :on_or_before => :<=,
12
15
  :on_or_after => :>=,
13
- :between => lambda {|v, r| (r.first..r.last).include?(v) }
16
+ :between => lambda {|v, r| (r.first..r.last).include?(v) }
14
17
  }
15
18
 
16
- VALID_OPTIONS = [
19
+ VALID_OPTION_KEYS = [
17
20
  :on, :if, :unless, :allow_nil, :empty, :allow_blank,
18
21
  :with_time, :with_date, :ignore_usec, :format,
19
22
  :invalid_time_message, :invalid_date_message, :invalid_datetime_message
20
23
  ] + RESTRICTION_METHODS.keys.map {|option| [option, "#{option}_message".to_sym] }.flatten
21
24
 
25
+ DEFAULT_OPTIONS = { :on => :save, :type => :datetime, :allow_nil => false, :allow_blank => false, :ignore_usec => false }
26
+
22
27
  attr_reader :configuration, :type
23
28
 
24
29
  def initialize(configuration)
25
- defaults = { :on => :save, :type => :datetime, :allow_nil => false, :allow_blank => false, :ignore_usec => false }
26
- @configuration = defaults.merge(configuration)
30
+ @configuration = DEFAULT_OPTIONS.merge(configuration)
27
31
  @type = @configuration.delete(:type)
28
32
  validate_options(@configuration)
29
33
  end
30
-
34
+
31
35
  def call(record, attr_name, value)
32
36
  raw_value = raw_value(record, attr_name) || value
33
37
 
@@ -44,7 +48,7 @@ module ValidatesTimeliness
44
48
  end
45
49
 
46
50
  def error_messages
47
- @error_messages ||= self.class.default_error_messages.merge(custom_error_messages)
51
+ @error_messages ||= ::ActiveRecord::Errors.default_error_messages.merge(custom_error_messages)
48
52
  end
49
53
 
50
54
  private
@@ -52,7 +56,7 @@ module ValidatesTimeliness
52
56
  def raw_value(record, attr_name)
53
57
  record.send("#{attr_name}_before_type_cast") rescue nil
54
58
  end
55
-
59
+
56
60
  def validate_restrictions(record, attr_name, value)
57
61
  if configuration[:with_time] || configuration[:with_date]
58
62
  value = combine_date_and_time(value, record)
@@ -81,14 +85,13 @@ module ValidatesTimeliness
81
85
  end
82
86
 
83
87
  def interpolation_values(option, restriction)
84
- format = self.class.error_value_formats[type]
88
+ format = self.class.error_value_format_for(type)
85
89
  restriction = [restriction] unless restriction.is_a?(Array)
86
90
 
87
91
  if defined?(I18n)
88
- message = I18n.t('activerecord.errors.messages')[option]
89
- subs = message.scan(/\{\{([^\}]*)\}\}/)
90
92
  interpolations = {}
91
- subs.each_with_index {|s, i| interpolations[s[0].to_sym] = restriction[i].strftime(format) }
93
+ keys = restriction.size == 1 ? [:restriction] : [:earliest, :latest]
94
+ keys.each_with_index {|key, i| interpolations[key] = restriction[i].strftime(format) }
92
95
  interpolations
93
96
  else
94
97
  restriction.map {|r| r.strftime(format) }
@@ -105,21 +108,20 @@ module ValidatesTimeliness
105
108
  comparator.call(value, restriction)
106
109
  end
107
110
  end
108
-
111
+
109
112
  def add_error(record, attr_name, message, interpolate=nil)
110
113
  if defined?(I18n)
111
114
  custom = custom_error_messages[message]
112
115
  record.errors.add(attr_name, message, { :default => custom }.merge(interpolate || {}))
113
116
  else
114
117
  message = error_messages[message] if message.is_a?(Symbol)
115
- message = message % interpolate
116
- record.errors.add(attr_name, message)
118
+ record.errors.add(attr_name, message % interpolate)
117
119
  end
118
120
  end
119
121
 
120
122
  def custom_error_messages
121
123
  @custom_error_messages ||= configuration.inject({}) {|msgs, (k, v)|
122
- if md = /(.*)_message$/.match(k.to_s)
124
+ if md = /(.*)_message$/.match(k.to_s)
123
125
  msgs[md[1].to_sym] = v
124
126
  end
125
127
  msgs
@@ -140,39 +142,34 @@ module ValidatesTimeliness
140
142
  end
141
143
 
142
144
  def validate_options(options)
145
+ if options.key?(:equal_to)
146
+ ::ActiveSupport::Deprecation.warn("ValidatesTimeliness :equal_to option is deprecated due to clash with a default Rails option. Use :is_at instead. You will need to fix any I18n error message references to this option date/time attributes now.")
147
+ options[:is_at] = options.delete(:equal_to)
148
+ options[:is_at_message] = options.delete(:equal_to_message)
149
+ end
150
+
143
151
  invalid_for_type = ([:time, :date, :datetime] - [type]).map {|k| "invalid_#{k}_message".to_sym }
144
152
  invalid_for_type << :with_date unless type == :time
145
153
  invalid_for_type << :with_time unless type == :date
146
- options.assert_valid_keys(VALID_OPTIONS - invalid_for_type)
154
+ options.assert_valid_keys(VALID_OPTION_KEYS - invalid_for_type)
147
155
  end
148
156
 
149
157
  def implied_type
150
- @implied_type ||= configuration[:with_date] || configuration[:with_time] ? :datetime : type
158
+ @implied_type ||= configuration[:with_date] || configuration[:with_time] ? :datetime : type
151
159
  end
152
160
 
153
161
  # class methods
154
162
  class << self
155
163
 
156
- def default_error_messages
164
+ def error_value_format_for(type)
157
165
  if defined?(I18n)
158
- I18n.t('activerecord.errors.messages')
166
+ # work around for syntax check in vendored I18n for Rails <= 2.3.3
167
+ I18n.t('validates_timeliness.error_value_formats')[type] || error_value_formats[type]
159
168
  else
160
- ::ActiveRecord::Errors.default_error_messages
169
+ error_value_formats[type]
161
170
  end
162
171
  end
163
172
 
164
- def error_value_formats
165
- if defined?(I18n)
166
- I18n.t('validates_timeliness.error_value_formats')
167
- else
168
- @@error_value_formats
169
- end
170
- end
171
-
172
- def error_value_formats=(formats)
173
- @@error_value_formats = formats
174
- end
175
-
176
173
  def evaluate_option_value(value, type, record)
177
174
  case value
178
175
  when Time, Date
@@ -1,3 +1,3 @@
1
1
  module ValidatesTimeliness
2
- VERSION = "2.2.2"
2
+ VERSION = "2.3.0"
3
3
  end
@@ -1,42 +1,194 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
- ValidatesTimeliness.enable_datetime_select_extension!
4
-
5
3
  describe 'ValidatesTimeliness::ActionView::InstanceTag' do
6
4
  include ActionView::Helpers::DateHelper
7
5
  include ActionController::Assertions::SelectorAssertions
8
-
6
+
9
7
  before do
10
8
  @person = Person.new
11
9
  end
12
-
13
- it "should display invalid datetime as datetime_select values" do
14
- @person.birth_date_and_time = "2008-02-30 12:00:22"
15
- output = datetime_select(:person, :birth_date_and_time, :include_blank => true, :include_seconds => true)
16
-
17
- output.should have_tag('select[id=person_birth_date_and_time_1i]') do
18
- with_tag('option[selected=selected]', '2008')
10
+
11
+ def params
12
+ @params ||= {}
13
+ end
14
+
15
+ describe "datetime_select" do
16
+ it "should use param values when attribute is nil" do
17
+ params["person"] = {
18
+ "birth_date_and_time(1i)" => 2009,
19
+ "birth_date_and_time(2i)" => 2,
20
+ "birth_date_and_time(3i)" => 29,
21
+ "birth_date_and_time(4i)" => 12,
22
+ "birth_date_and_time(5i)" => 13,
23
+ "birth_date_and_time(6i)" => 14,
24
+ }
25
+ @person.birth_date_and_time = nil
26
+ output = datetime_select(:person, :birth_date_and_time, :include_blank => true, :include_seconds => true)
27
+ output.should have_tag('select[id=person_birth_date_and_time_1i] option[selected=selected]', '2009')
28
+ output.should have_tag('select[id=person_birth_date_and_time_2i] option[selected=selected]', 'February')
29
+ output.should have_tag('select[id=person_birth_date_and_time_3i] option[selected=selected]', '29')
30
+ output.should have_tag('select[id=person_birth_date_and_time_4i] option[selected=selected]', '12')
31
+ output.should have_tag('select[id=person_birth_date_and_time_5i] option[selected=selected]', '13')
32
+ output.should have_tag('select[id=person_birth_date_and_time_6i] option[selected=selected]', '14')
33
+ end
34
+
35
+ it "should override object values and use params if present" do
36
+ params["person"] = {
37
+ "birth_date_and_time(1i)" => 2009,
38
+ "birth_date_and_time(2i)" => 2,
39
+ "birth_date_and_time(3i)" => 29,
40
+ "birth_date_and_time(4i)" => 13,
41
+ "birth_date_and_time(5i)" => 14,
42
+ "birth_date_and_time(6i)" => 15,
43
+ }
44
+ @person.birth_date_and_time = "2009-03-01 13:14:15"
45
+ output = datetime_select(:person, :birth_date_and_time, :include_blank => true, :include_seconds => true)
46
+ output.should have_tag('select[id=person_birth_date_and_time_1i] option[selected=selected]', '2009')
47
+ output.should have_tag('select[id=person_birth_date_and_time_2i] option[selected=selected]', 'February')
48
+ output.should have_tag('select[id=person_birth_date_and_time_3i] option[selected=selected]', '29')
49
+ output.should have_tag('select[id=person_birth_date_and_time_4i] option[selected=selected]', '13')
50
+ output.should have_tag('select[id=person_birth_date_and_time_5i] option[selected=selected]', '14')
51
+ output.should have_tag('select[id=person_birth_date_and_time_6i] option[selected=selected]', '15')
19
52
  end
20
- output.should have_tag('select[id=person_birth_date_and_time_2i]') do
21
- with_tag('option[selected=selected]', 'February')
53
+
54
+ it "should select attribute values from object if no params" do
55
+ @person.birth_date_and_time = "2009-01-02 13:14:15"
56
+ output = datetime_select(:person, :birth_date_and_time, :include_blank => true, :include_seconds => true)
57
+ output.should have_tag('select[id=person_birth_date_and_time_1i] option[selected=selected]', '2009')
58
+ output.should have_tag('select[id=person_birth_date_and_time_2i] option[selected=selected]', 'January')
59
+ output.should have_tag('select[id=person_birth_date_and_time_3i] option[selected=selected]', '2')
60
+ output.should have_tag('select[id=person_birth_date_and_time_4i] option[selected=selected]', '13')
61
+ output.should have_tag('select[id=person_birth_date_and_time_5i] option[selected=selected]', '14')
62
+ output.should have_tag('select[id=person_birth_date_and_time_6i] option[selected=selected]', '15')
63
+ end
64
+
65
+ it "should select attribute values if params does not contain attribute params" do
66
+ @person.birth_date_and_time = "2009-01-02 13:14:15"
67
+ params["person"] = { }
68
+ output = datetime_select(:person, :birth_date_and_time, :include_blank => true, :include_seconds => true)
69
+ output.should have_tag('select[id=person_birth_date_and_time_1i] option[selected=selected]', '2009')
70
+ output.should have_tag('select[id=person_birth_date_and_time_2i] option[selected=selected]', 'January')
71
+ output.should have_tag('select[id=person_birth_date_and_time_3i] option[selected=selected]', '2')
72
+ output.should have_tag('select[id=person_birth_date_and_time_4i] option[selected=selected]', '13')
73
+ output.should have_tag('select[id=person_birth_date_and_time_5i] option[selected=selected]', '14')
74
+ output.should have_tag('select[id=person_birth_date_and_time_6i] option[selected=selected]', '15')
75
+ end
76
+
77
+ it "should not select values when attribute value is nil and has no param values" do
78
+ @person.birth_date_and_time = nil
79
+ output = datetime_select(:person, :birth_date_and_time, :include_blank => true, :include_seconds => true)
80
+ output.should_not have_tag('select[id=person_birth_date_and_time_1i] option[selected=selected]')
81
+ output.should_not have_tag('select[id=person_birth_date_and_time_2i] option[selected=selected]')
82
+ output.should_not have_tag('select[id=person_birth_date_and_time_3i] option[selected=selected]')
83
+ output.should_not have_tag('select[id=person_birth_date_and_time_4i] option[selected=selected]')
84
+ output.should_not have_tag('select[id=person_birth_date_and_time_5i] option[selected=selected]')
85
+ output.should_not have_tag('select[id=person_birth_date_and_time_6i] option[selected=selected]')
86
+ end
87
+ end
88
+
89
+ describe "date_select" do
90
+ it "should use param values when attribute is nil" do
91
+ params["person"] = {
92
+ "birth_date(1i)" => 2009,
93
+ "birth_date(2i)" => 2,
94
+ "birth_date(3i)" => 29,
95
+ }
96
+ @person.birth_date = nil
97
+ output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true)
98
+ output.should have_tag('select[id=person_birth_date_1i] option[selected=selected]', '2009')
99
+ output.should have_tag('select[id=person_birth_date_2i] option[selected=selected]', 'February')
100
+ output.should have_tag('select[id=person_birth_date_3i] option[selected=selected]', '29')
22
101
  end
23
- output.should have_tag('select[id=person_birth_date_and_time_3i]') do
24
- with_tag('option[selected=selected]', '30')
102
+
103
+ it "should override object values and use params if present" do
104
+ params["person"] = {
105
+ "birth_date(1i)" => 2009,
106
+ "birth_date(2i)" => 2,
107
+ "birth_date(3i)" => 29,
108
+ }
109
+ @person.birth_date = "2009-03-01"
110
+ output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true)
111
+ output.should have_tag('select[id=person_birth_date_1i] option[selected=selected]', '2009')
112
+ output.should have_tag('select[id=person_birth_date_2i] option[selected=selected]', 'February')
113
+ output.should have_tag('select[id=person_birth_date_3i] option[selected=selected]', '29')
25
114
  end
26
- output.should have_tag('select[id=person_birth_date_and_time_4i]') do
27
- with_tag('option[selected=selected]', '12')
115
+
116
+ it "should select attribute values from object if no params" do
117
+ @person.birth_date = "2009-01-02"
118
+ output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true)
119
+ output.should have_tag('select[id=person_birth_date_1i] option[selected=selected]', '2009')
120
+ output.should have_tag('select[id=person_birth_date_2i] option[selected=selected]', 'January')
121
+ output.should have_tag('select[id=person_birth_date_3i] option[selected=selected]', '2')
28
122
  end
29
- output.should have_tag('select[id=person_birth_date_and_time_5i]') do
30
- with_tag('option[selected=selected]', '00')
123
+
124
+ it "should select attribute values if params does not contain attribute params" do
125
+ @person.birth_date = "2009-01-02"
126
+ params["person"] = { }
127
+ output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true)
128
+ output.should have_tag('select[id=person_birth_date_1i] option[selected=selected]', '2009')
129
+ output.should have_tag('select[id=person_birth_date_2i] option[selected=selected]', 'January')
130
+ output.should have_tag('select[id=person_birth_date_3i] option[selected=selected]', '2')
31
131
  end
32
- output.should have_tag('select[id=person_birth_date_and_time_6i]') do
33
- with_tag('option[selected=selected]', '22')
132
+
133
+ it "should not select values when attribute value is nil and has no param values" do
134
+ @person.birth_date = nil
135
+ output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true)
136
+ output.should_not have_tag('select[id=person_birth_date_1i] option[selected=selected]')
137
+ output.should_not have_tag('select[id=person_birth_date_2i] option[selected=selected]')
138
+ output.should_not have_tag('select[id=person_birth_date_3i] option[selected=selected]')
34
139
  end
35
140
  end
36
-
37
- it "should display datetime_select when datetime value is nil" do
38
- @person.birth_date_and_time = nil
39
- output = datetime_select(:person, :birth_date_and_time, :include_blank => true, :include_seconds => true)
40
- output.should have_tag('select', 6)
141
+
142
+ describe "time_select" do
143
+ before :all do
144
+ Time.now = Time.mktime(2009,1,1)
145
+ end
146
+
147
+ it "should use param values when attribute is nil" do
148
+ params["person"] = {
149
+ "birth_time(1i)" => 2000,
150
+ "birth_time(2i)" => 1,
151
+ "birth_time(3i)" => 1,
152
+ "birth_time(4i)" => 12,
153
+ "birth_time(5i)" => 13,
154
+ "birth_time(6i)" => 14,
155
+ }
156
+ @person.birth_time = nil
157
+ output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true)
158
+ output.should have_tag('input[id=person_birth_time_1i][value=2000]')
159
+ output.should have_tag('input[id=person_birth_time_2i][value=1]')
160
+ output.should have_tag('input[id=person_birth_time_3i][value=1]')
161
+ output.should have_tag('select[id=person_birth_time_4i] option[selected=selected]', '12')
162
+ output.should have_tag('select[id=person_birth_time_5i] option[selected=selected]', '13')
163
+ output.should have_tag('select[id=person_birth_time_6i] option[selected=selected]', '14')
164
+ end
165
+
166
+ it "should select attribute values from object if no params" do
167
+ @person.birth_time = "13:14:15"
168
+ output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true)
169
+ output.should have_tag('input[id=person_birth_time_1i][value=2000]')
170
+ output.should have_tag('input[id=person_birth_time_2i][value=1]')
171
+ output.should have_tag('input[id=person_birth_time_3i][value=1]')
172
+ output.should have_tag('select[id=person_birth_time_4i] option[selected=selected]', '13')
173
+ output.should have_tag('select[id=person_birth_time_5i] option[selected=selected]', '14')
174
+ output.should have_tag('select[id=person_birth_time_6i] option[selected=selected]', '15')
175
+ end
176
+
177
+ it "should not select values when attribute value is nil and has no param values" do
178
+ @person.birth_time = nil
179
+ output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true)
180
+ output.should have_tag('input[id=person_birth_time_1i][value=""]')
181
+ # Annoyingly these may or not have value attribute depending on rails version.
182
+ # output.should have_tag('input[id=person_birth_time_2i][value=""]')
183
+ # output.should have_tag('input[id=person_birth_time_3i][value=""]')
184
+ output.should_not have_tag('select[id=person_birth_time_4i] option[selected=selected]')
185
+ output.should_not have_tag('select[id=person_birth_time_5i] option[selected=selected]')
186
+ output.should_not have_tag('select[id=person_birth_time_6i] option[selected=selected]')
187
+ end
188
+
189
+ after :all do
190
+ Time.now = nil
191
+ end
41
192
  end
193
+
42
194
  end
@@ -5,7 +5,9 @@ describe ValidatesTimeliness::ActiveRecord::AttributeMethods do
5
5
  @person = Person.new
6
6
  end
7
7
 
8
- it "should call write_date_time_attribute when date attribute assigned value" do
8
+ it "should define and call write method on first assign" do
9
+ Person.class_eval { @generated_methods = Set.new }
10
+ Person.send(:undef_method, :birth_date=)
9
11
  @person.should_receive(:write_date_time_attribute)
10
12
  @person.birth_date = "2000-01-01"
11
13
  end
@@ -40,7 +42,7 @@ describe ValidatesTimeliness::ActiveRecord::AttributeMethods do
40
42
  @person.birth_date_and_time = time_string
41
43
  @person.birth_date_and_time_before_type_cast.should == time_string
42
44
  end
43
-
45
+
44
46
  it "should return Time object for attribute_before_type_cast when written as Time" do
45
47
  @person.birth_date_and_time = Time.mktime(2000, 1, 1, 2, 3, 4)
46
48
  @person.birth_date_and_time_before_type_cast.should be_kind_of(Time)
@@ -59,24 +61,24 @@ describe ValidatesTimeliness::ActiveRecord::AttributeMethods do
59
61
  it "should return Time object for datetime attribute read method when assigned string" do
60
62
  @person.birth_date_and_time = "2000-01-01 02:03:04"
61
63
  @person.birth_date_and_time.should be_kind_of(Time)
62
- end
63
-
64
+ end
65
+
64
66
  it "should return Date object for date attribute read method when assigned Date object" do
65
67
  @person.birth_date = Date.today
66
68
  @person.birth_date.should be_kind_of(Date)
67
- end
68
-
69
+ end
70
+
69
71
  it "should return Date object for date attribute read method when assigned string" do
70
72
  @person.birth_date = '2000-01-01'
71
73
  @person.birth_date.should be_kind_of(Date)
72
- end
73
-
74
+ end
75
+
74
76
  it "should return nil when time is invalid" do
75
77
  @person.birth_date_and_time = "2000-01-32 02:03:04"
76
78
  @person.birth_date_and_time.should be_nil
77
79
  end
78
80
 
79
- it "should not save invalid date value to database" do
81
+ it "should not save invalid date value to database" do
80
82
  time_string = "2000-01-32 02:03:04"
81
83
  @person = Person.new
82
84
  @person.birth_date_and_time = time_string
@@ -84,7 +86,7 @@ describe ValidatesTimeliness::ActiveRecord::AttributeMethods do
84
86
  @person.reload
85
87
  @person.birth_date_and_time_before_type_cast.should be_nil
86
88
  end
87
-
89
+
88
90
  if RAILS_VER < '2.1'
89
91
 
90
92
  it "should return time object from database in default timezone" do
@@ -94,7 +96,7 @@ describe ValidatesTimeliness::ActiveRecord::AttributeMethods do
94
96
  @person.birth_date_and_time = time_string
95
97
  @person.save
96
98
  @person.reload
97
- @person.birth_date_and_time.strftime('%Y-%m-%d %H:%M:%S %Z').should == time_string + ' GMT'
99
+ @person.birth_date_and_time.strftime('%Y-%m-%d %H:%M:%S %Z').should == time_string + ' UTC'
98
100
  end
99
101
 
100
102
  else
@@ -106,7 +108,7 @@ describe ValidatesTimeliness::ActiveRecord::AttributeMethods do
106
108
  @person.birth_date_and_time.strftime('%Y-%m-%d %H:%M:%S %Z %z').should == time_string + ' EST +1000'
107
109
  end
108
110
 
109
- it "should return time object from database in correct timezone" do
111
+ it "should return time object from database in correct timezone" do
110
112
  Time.zone = 'Melbourne'
111
113
  time_string = "2000-06-01 09:00:00"
112
114
  @person = Person.new
@@ -115,19 +117,19 @@ describe ValidatesTimeliness::ActiveRecord::AttributeMethods do
115
117
  @person.reload
116
118
  @person.birth_date_and_time.strftime('%Y-%m-%d %H:%M:%S %Z %z').should == time_string + ' EST +1000'
117
119
  end
118
-
120
+
119
121
  end
120
-
122
+
121
123
  it "should return correct date value after new value assigned" do
122
124
  today = Date.today
123
- tomorrow = Date.today + 1.day
125
+ tomorrow = Date.today + 1.day
124
126
  @person = Person.new
125
127
  @person.birth_date = today
126
128
  @person.birth_date.should == today
127
129
  @person.birth_date = tomorrow
128
130
  @person.birth_date.should == tomorrow
129
131
  end
130
-
132
+
131
133
  it "should update date attribute on existing object" do
132
134
  today = Date.today
133
135
  tomorrow = Date.today + 1.day