jc-validates_timeliness 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +14 -0
  3. data/CHANGELOG.rdoc +183 -0
  4. data/LICENSE +20 -0
  5. data/README.rdoc +301 -0
  6. data/Rakefile +30 -0
  7. data/gemfiles/mongoid_2_1.gemfile +16 -0
  8. data/gemfiles/mongoid_2_2.gemfile +16 -0
  9. data/gemfiles/mongoid_2_3.gemfile +16 -0
  10. data/gemfiles/mongoid_2_4.gemfile +16 -0
  11. data/gemfiles/rails_3_0.gemfile +15 -0
  12. data/gemfiles/rails_3_1.gemfile +15 -0
  13. data/gemfiles/rails_3_2.gemfile +15 -0
  14. data/init.rb +1 -0
  15. data/lib/generators/validates_timeliness/install_generator.rb +16 -0
  16. data/lib/generators/validates_timeliness/templates/en.yml +16 -0
  17. data/lib/generators/validates_timeliness/templates/validates_timeliness.rb +40 -0
  18. data/lib/validates_timeliness.rb +70 -0
  19. data/lib/validates_timeliness/attribute_methods.rb +92 -0
  20. data/lib/validates_timeliness/conversion.rb +70 -0
  21. data/lib/validates_timeliness/extensions.rb +14 -0
  22. data/lib/validates_timeliness/extensions/date_time_select.rb +61 -0
  23. data/lib/validates_timeliness/extensions/multiparameter_handler.rb +80 -0
  24. data/lib/validates_timeliness/helper_methods.rb +23 -0
  25. data/lib/validates_timeliness/orm/active_record.rb +53 -0
  26. data/lib/validates_timeliness/orm/mongoid.rb +63 -0
  27. data/lib/validates_timeliness/railtie.rb +15 -0
  28. data/lib/validates_timeliness/validator.rb +117 -0
  29. data/lib/validates_timeliness/version.rb +3 -0
  30. data/spec/spec_helper.rb +100 -0
  31. data/spec/support/config_helper.rb +36 -0
  32. data/spec/support/model_helpers.rb +27 -0
  33. data/spec/support/tag_matcher.rb +35 -0
  34. data/spec/support/test_model.rb +60 -0
  35. data/spec/validates_timeliness/attribute_methods_spec.rb +86 -0
  36. data/spec/validates_timeliness/conversion_spec.rb +234 -0
  37. data/spec/validates_timeliness/extensions/date_time_select_spec.rb +163 -0
  38. data/spec/validates_timeliness/extensions/multiparameter_handler_spec.rb +44 -0
  39. data/spec/validates_timeliness/helper_methods_spec.rb +30 -0
  40. data/spec/validates_timeliness/orm/active_record_spec.rb +244 -0
  41. data/spec/validates_timeliness/orm/mongoid_spec.rb +189 -0
  42. data/spec/validates_timeliness/validator/after_spec.rb +57 -0
  43. data/spec/validates_timeliness/validator/before_spec.rb +57 -0
  44. data/spec/validates_timeliness/validator/is_at_spec.rb +61 -0
  45. data/spec/validates_timeliness/validator/on_or_after_spec.rb +57 -0
  46. data/spec/validates_timeliness/validator/on_or_before_spec.rb +57 -0
  47. data/spec/validates_timeliness/validator_spec.rb +246 -0
  48. data/spec/validates_timeliness_spec.rb +43 -0
  49. data/validates_timeliness.gemspec +20 -0
  50. metadata +128 -0
@@ -0,0 +1,163 @@
1
+ require 'spec_helper'
2
+
3
+ describe ValidatesTimeliness::Extensions::DateTimeSelect do
4
+ include ActionView::Helpers::DateHelper
5
+ attr_reader :person, :params
6
+
7
+ with_config(:use_plugin_parser, true)
8
+
9
+ before do
10
+ @person = Person.new
11
+ @params = {}
12
+ end
13
+
14
+ describe "datetime_select" do
15
+ it "should use param values when attribute is nil" do
16
+ @params["person"] = {
17
+ "birth_datetime(1i)" => '2009',
18
+ "birth_datetime(2i)" => '2',
19
+ "birth_datetime(3i)" => '29',
20
+ "birth_datetime(4i)" => '12',
21
+ "birth_datetime(5i)" => '13',
22
+ "birth_datetime(6i)" => '14',
23
+ }
24
+ person.birth_datetime = nil
25
+ @output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
26
+ should_have_datetime_selected(:birth_datetime, :year => 2009, :month => 'February', :day => 29, :hour => 12, :min => 13, :sec => 14)
27
+ end
28
+
29
+ it "should override object values and use params if present" do
30
+ @params["person"] = {
31
+ "birth_datetime(1i)" => '2009',
32
+ "birth_datetime(2i)" => '2',
33
+ "birth_datetime(3i)" => '29',
34
+ "birth_datetime(4i)" => '12',
35
+ "birth_datetime(5i)" => '13',
36
+ "birth_datetime(6i)" => '14',
37
+ }
38
+ person.birth_datetime = "2010-01-01 15:16:17"
39
+ @output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
40
+ should_have_datetime_selected(:birth_datetime, :year => 2009, :month => 'February', :day => 29, :hour => 12, :min => 13, :sec => 14)
41
+ end
42
+
43
+ it "should use attribute values from object if no params" do
44
+ person.birth_datetime = "2009-01-02 12:13:14"
45
+ @output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
46
+ should_have_datetime_selected(:birth_datetime, :year => 2009, :month => 'January', :day => 2, :hour => 12, :min => 13, :sec => 14)
47
+ end
48
+
49
+ it "should use attribute values if params does not contain attribute params" do
50
+ person.birth_datetime = "2009-01-02 12:13:14"
51
+ @params["person"] = { }
52
+ @output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
53
+ should_have_datetime_selected(:birth_datetime, :year => 2009, :month => 'January', :day => 2, :hour => 12, :min => 13, :sec => 14)
54
+ end
55
+
56
+ it "should not select values when attribute value is nil and has no param values" do
57
+ person.birth_datetime = nil
58
+ @output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
59
+ should_not_have_datetime_selected(:birth_datetime, :year, :month, :day, :hour, :min, :sec)
60
+ end
61
+ end
62
+
63
+ describe "date_select" do
64
+ it "should use param values when attribute is nil" do
65
+ @params["person"] = {
66
+ "birth_date(1i)" => '2009',
67
+ "birth_date(2i)" => '2',
68
+ "birth_date(3i)" => '29',
69
+ }
70
+ person.birth_date = nil
71
+ @output = date_select(:person, :birth_date, :include_blank => true)
72
+ should_have_datetime_selected(:birth_date, :year => 2009, :month => 'February', :day => 29)
73
+ end
74
+
75
+ it "should override object values and use params if present" do
76
+ @params["person"] = {
77
+ "birth_date(1i)" => '2009',
78
+ "birth_date(2i)" => '2',
79
+ "birth_date(3i)" => '29',
80
+ }
81
+ person.birth_date = "2009-03-01"
82
+ @output = date_select(:person, :birth_date, :include_blank => true)
83
+ should_have_datetime_selected(:birth_date, :year => 2009, :month => 'February', :day => 29)
84
+ end
85
+
86
+ it "should select attribute values from object if no params" do
87
+ person.birth_date = "2009-01-02"
88
+ @output = date_select(:person, :birth_date, :include_blank => true)
89
+ should_have_datetime_selected(:birth_date, :year => 2009, :month => 'January', :day => 2)
90
+ end
91
+
92
+ it "should select attribute values if params does not contain attribute params" do
93
+ person.birth_date = "2009-01-02"
94
+ @params["person"] = { }
95
+ @output = date_select(:person, :birth_date, :include_blank => true)
96
+ should_have_datetime_selected(:birth_date, :year => 2009, :month => 'January', :day => 2)
97
+ end
98
+
99
+ it "should not select values when attribute value is nil and has no param values" do
100
+ person.birth_date = nil
101
+ @output = date_select(:person, :birth_date, :include_blank => true)
102
+ should_not_have_datetime_selected(:birth_time, :year, :month, :day)
103
+ end
104
+
105
+ it "should allow the day part to be discarded" do
106
+ @params["person"] = {
107
+ "birth_date(1i)" => '2009',
108
+ "birth_date(2i)" => '2',
109
+ }
110
+
111
+ @output = date_select(:person, :birth_date, :include_blank => true, :discard_day => true)
112
+ should_have_datetime_selected(:birth_date, :year => 2009, :month => 'February')
113
+ should_not_have_datetime_selected(:birth_time, :day)
114
+ expect(@output).to have_tag("input[id=person_birth_date_3i][type=hidden][value='1']")
115
+ end
116
+ end
117
+
118
+ describe "time_select" do
119
+ before do
120
+ Timecop.freeze Time.mktime(2009,1,1)
121
+ end
122
+
123
+ it "should use param values when attribute is nil" do
124
+ @params["person"] = {
125
+ "birth_time(1i)" => '2000',
126
+ "birth_time(2i)" => '1',
127
+ "birth_time(3i)" => '1',
128
+ "birth_time(4i)" => '12',
129
+ "birth_time(5i)" => '13',
130
+ "birth_time(6i)" => '14',
131
+ }
132
+ person.birth_time = nil
133
+ @output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true)
134
+ should_have_datetime_selected(:birth_time, :hour => 12, :min => 13, :sec => 14)
135
+ end
136
+
137
+ it "should select attribute values from object if no params" do
138
+ person.birth_time = "2000-01-01 12:13:14"
139
+ @output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true)
140
+ should_have_datetime_selected(:birth_time, :hour => 12, :min => 13, :sec => 14)
141
+ end
142
+
143
+ it "should not select values when attribute value is nil and has no param values" do
144
+ person.birth_time = nil
145
+ @output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true)
146
+ should_not_have_datetime_selected(:birth_time, :hour, :min, :sec)
147
+ end
148
+ end
149
+
150
+ def should_have_datetime_selected(field, datetime_hash)
151
+ datetime_hash.each do |key, value|
152
+ index = {:year => 1, :month => 2, :day => 3, :hour => 4, :min => 5, :sec => 6}[key]
153
+ expect(@output).to have_tag("select[id=person_#{field}_#{index}i] option[selected=selected]").with_inner_text(value.to_s)
154
+ end
155
+ end
156
+
157
+ def should_not_have_datetime_selected(field, *attributes)
158
+ attributes.each do |attribute|
159
+ index = {:year => 1, :month => 2, :day => 3, :hour => 4, :min => 5, :sec => 6}[attribute]
160
+ expect(@output).not_to have_tag("select[id=person_#{attribute}_#{index}i] option[selected=selected]")
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe ValidatesTimeliness::Extensions::MultiparameterHandler do
4
+
5
+ context "time column" do
6
+ it 'should assign a string value for invalid date portion' do
7
+ employee = record_with_multiparameter_attribute(:birth_datetime, [2000, 2, 31, 12, 0, 0])
8
+ expect(employee.birth_datetime_before_type_cast).to eq '2000-02-31 12:00:00'
9
+ end
10
+
11
+ it 'should assign a Time value for valid datetimes' do
12
+ employee = record_with_multiparameter_attribute(:birth_datetime, [2000, 2, 28, 12, 0, 0])
13
+ expect(employee.birth_datetime_before_type_cast).to eq Time.zone.local(2000, 2, 28, 12, 0, 0)
14
+ end
15
+
16
+ it 'should assign a string value for incomplete time' do
17
+ employee = record_with_multiparameter_attribute(:birth_datetime, [2000, nil, nil])
18
+ expect(employee.birth_datetime_before_type_cast).to eq '2000-00-00'
19
+ end
20
+ end
21
+
22
+ context "date column" do
23
+ it 'should assign a string value for invalid date' do
24
+ employee = record_with_multiparameter_attribute(:birth_date, [2000, 2, 31])
25
+ expect(employee.birth_date_before_type_cast).to eq '2000-02-31'
26
+ end
27
+
28
+ it 'should assign a Date value for valid date' do
29
+ employee = record_with_multiparameter_attribute(:birth_date, [2000, 2, 28])
30
+ expect(employee.birth_date_before_type_cast).to eq Date.new(2000, 2, 28)
31
+ end
32
+
33
+ it 'should assign a string value for incomplete date' do
34
+ employee = record_with_multiparameter_attribute(:birth_date, [2000, nil, nil])
35
+ expect(employee.birth_date_before_type_cast).to eq '2000-00-00'
36
+ end
37
+ end
38
+
39
+ def record_with_multiparameter_attribute(name, values)
40
+ hash = {}
41
+ values.each_with_index {|value, index| hash["#{name}(#{index+1}i)"] = value.to_s }
42
+ Employee.new(hash)
43
+ end
44
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe ValidatesTimeliness, 'HelperMethods' do
4
+ let(:record) { Person.new }
5
+
6
+ it 'should define class validation methods' do
7
+ expect(Person).to respond_to(:validates_date)
8
+ expect(Person).to respond_to(:validates_time)
9
+ expect(Person).to respond_to(:validates_datetime)
10
+ end
11
+
12
+ it 'should define instance validation methods' do
13
+ expect(record).to respond_to(:validates_date)
14
+ expect(record).to respond_to(:validates_time)
15
+ expect(record).to respond_to(:validates_datetime)
16
+ end
17
+
18
+ it 'should validate instance using class validation defined' do
19
+ Person.validates_date :birth_date
20
+ record.valid?
21
+
22
+ expect(record.errors[:birth_date]).not_to be_empty
23
+ end
24
+
25
+ it 'should validate instance using instance valiation method' do
26
+ record.validates_date :birth_date
27
+
28
+ expect(record.errors[:birth_date]).not_to be_empty
29
+ end
30
+ end
@@ -0,0 +1,244 @@
1
+ require 'spec_helper'
2
+
3
+ describe ValidatesTimeliness, 'ActiveRecord' do
4
+
5
+ context "validation methods" do
6
+ let(:record) { Employee.new }
7
+
8
+ it 'should be defined for the class' do
9
+ expect(ActiveRecord::Base).to respond_to(:validates_date)
10
+ expect(ActiveRecord::Base).to respond_to(:validates_time)
11
+ expect(ActiveRecord::Base).to respond_to(:validates_datetime)
12
+ end
13
+
14
+ it 'should defines for the instance' do
15
+ expect(record).to respond_to(:validates_date)
16
+ expect(record).to respond_to(:validates_time)
17
+ expect(record).to respond_to(:validates_datetime)
18
+ end
19
+
20
+ it "should validate a valid value string" do
21
+ record.birth_date = '2012-01-01'
22
+
23
+ record.valid?
24
+ expect(record.errors[:birth_date]).to be_empty
25
+ end
26
+
27
+ it "should validate a invalid value string" do
28
+ record.birth_date = 'not a date'
29
+
30
+ record.valid?
31
+ expect(record.errors[:birth_date]).not_to be_empty
32
+ end
33
+
34
+ it "should validate a nil value" do
35
+ record.birth_date = nil
36
+
37
+ record.valid?
38
+ expect(record.errors[:birth_date]).to be_empty
39
+ end
40
+ end
41
+
42
+ it 'should determine type for attribute' do
43
+ expect(Employee.timeliness_attribute_type(:birth_date)).to eq :date
44
+ end
45
+
46
+ context 'attribute timezone awareness' do
47
+ let(:klass) {
48
+ Class.new(ActiveRecord::Base) do
49
+ self.table_name = 'employees'
50
+ attr_accessor :some_date
51
+ attr_accessor :some_time
52
+ attr_accessor :some_datetime
53
+ validates_date :some_date
54
+ validates_time :some_time
55
+ validates_datetime :some_datetime
56
+ end
57
+ }
58
+
59
+ context 'for column attribute' do
60
+ it 'should be detected from column type' do
61
+ expect(klass.timeliness_attribute_timezone_aware?(:birth_date)).to be_falsey
62
+ expect(klass.timeliness_attribute_timezone_aware?(:birth_time)).to be_falsey
63
+ expect(klass.timeliness_attribute_timezone_aware?(:birth_datetime)).to be_truthy
64
+ end
65
+ end
66
+
67
+ context 'for non-column attribute' do
68
+ it 'should be detected from the validation type' do
69
+ expect(klass.timeliness_attribute_timezone_aware?(:some_date)).to be_falsey
70
+ expect(klass.timeliness_attribute_timezone_aware?(:some_time)).to be_falsey
71
+ expect(klass.timeliness_attribute_timezone_aware?(:some_datetime)).to be_truthy
72
+ end
73
+ end
74
+ end
75
+
76
+ context "attribute write method" do
77
+ class EmployeeWithCache < ActiveRecord::Base
78
+ self.table_name = 'employees'
79
+ validates_date :birth_date, :allow_blank => true
80
+ validates_time :birth_time, :allow_blank => true
81
+ validates_datetime :birth_datetime, :allow_blank => true
82
+ end
83
+
84
+ context 'value cache' do
85
+ let(:record) { EmployeeWithCache.new }
86
+
87
+ context 'for datetime column' do
88
+ it 'should store raw value' do
89
+ record.birth_datetime = datetime_string = '2010-01-01 12:30'
90
+
91
+ expect(record._timeliness_raw_value_for('birth_datetime')).to eq datetime_string
92
+ end
93
+ end
94
+
95
+ context 'for date column' do
96
+ it 'should store raw value' do
97
+ record.birth_date = date_string = '2010-01-01'
98
+
99
+ expect(record._timeliness_raw_value_for('birth_date')).to eq date_string
100
+ end
101
+ end
102
+
103
+ context 'for time column' do
104
+ it 'should store raw value' do
105
+ record.birth_time = time_string = '12:12'
106
+
107
+ expect(record._timeliness_raw_value_for('birth_time')).to eq time_string
108
+ end
109
+ end
110
+ end
111
+
112
+ context "with plugin parser" do
113
+ with_config(:use_plugin_parser, true)
114
+ let(:record) { EmployeeWithParser.new }
115
+
116
+ class EmployeeWithParser < ActiveRecord::Base
117
+ self.table_name = 'employees'
118
+ validates_date :birth_date, :allow_blank => true
119
+ validates_time :birth_time, :allow_blank => true
120
+ validates_datetime :birth_datetime, :allow_blank => true
121
+ end
122
+
123
+ context "for a date column" do
124
+ it 'should parse a string value' do
125
+ expect(Timeliness::Parser).to receive(:parse)
126
+
127
+ record.birth_date = '2010-01-01'
128
+ end
129
+
130
+ it 'should parse a invalid string value as nil' do
131
+ expect(Timeliness::Parser).to receive(:parse)
132
+
133
+ record.birth_date = 'not valid'
134
+ end
135
+
136
+ it 'should store a Date value after parsing string' do
137
+ record.birth_date = '2010-01-01'
138
+
139
+ expect(record.birth_date).to be_kind_of(Date)
140
+ expect(record.birth_date).to eq Date.new(2010, 1, 1)
141
+ end
142
+ end
143
+
144
+ context "for a time column" do
145
+ it 'should parse a string value' do
146
+ expect(Timeliness::Parser).to receive(:parse)
147
+
148
+ record.birth_time = '12:30'
149
+ end
150
+
151
+ it 'should parse a invalid string value as nil' do
152
+ expect(Timeliness::Parser).to receive(:parse)
153
+
154
+ record.birth_time = 'not valid'
155
+ end
156
+
157
+ it 'should store a Time value after parsing string' do
158
+ record.birth_time = '12:30'
159
+
160
+ expect(record.birth_time).to be_kind_of(Time)
161
+ expect(record.birth_time).to eq Time.utc(2000, 1, 1, 12, 30)
162
+ end
163
+ end
164
+
165
+ context "for a datetime column" do
166
+ with_config(:default_timezone, 'Australia/Melbourne')
167
+
168
+ it 'should parse a string value' do
169
+ expect(Timeliness::Parser).to receive(:parse)
170
+
171
+ record.birth_datetime = '2010-01-01 12:00'
172
+ end
173
+
174
+ it 'should parse a invalid string value as nil' do
175
+ expect(Timeliness::Parser).to receive(:parse)
176
+
177
+ record.birth_datetime = 'not valid'
178
+ end
179
+
180
+ it 'should parse string into Time value' do
181
+ record.birth_datetime = '2010-01-01 12:00'
182
+
183
+ expect(record.birth_datetime).to be_kind_of(Time)
184
+ end
185
+
186
+ it 'should parse string as current timezone' do
187
+ record.birth_datetime = '2010-06-01 12:00'
188
+
189
+ expect(record.birth_datetime.utc_offset).to eq Time.zone.utc_offset
190
+ end
191
+ end
192
+ end
193
+ end
194
+
195
+ context "reload" do
196
+ it 'should clear cache value' do
197
+ record = Employee.create!
198
+ record.birth_date = '2010-01-01'
199
+
200
+ record.reload
201
+
202
+ expect(record._timeliness_raw_value_for('birth_date')).to be_nil
203
+ end
204
+ end
205
+
206
+ context "before_type_cast method" do
207
+ let(:record) { Employee.new }
208
+
209
+ it 'should be defined on class if ORM supports it' do
210
+ expect(record).to respond_to(:birth_datetime_before_type_cast)
211
+ end
212
+
213
+ it 'should return original value' do
214
+ record.birth_datetime = date_string = '2010-01-01'
215
+
216
+ expect(record.birth_datetime_before_type_cast).to eq date_string
217
+ end
218
+
219
+ it 'should return attribute if no attribute assignment has been made' do
220
+ datetime = Time.zone.local(2010,01,01)
221
+ Employee.create(:birth_datetime => datetime)
222
+
223
+ record = Employee.last
224
+ expect(record.birth_datetime_before_type_cast).to match(/#{datetime.utc.to_s[0...-4]}/)
225
+ end
226
+
227
+ context "with plugin parser" do
228
+ with_config(:use_plugin_parser, true)
229
+
230
+ it 'should return original value' do
231
+ record.birth_datetime = date_string = '2010-01-31'
232
+
233
+ expect(record.birth_datetime_before_type_cast).to eq date_string
234
+ end
235
+ end
236
+
237
+ end
238
+
239
+ context "define_attribute_methods" do
240
+ it "returns a falsy value if the attribute methods have already been generated" do
241
+ expect(Employee.define_attribute_methods).to be_falsey
242
+ end
243
+ end
244
+ end