sp-validates_timeliness 3.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.rdoc +183 -0
  3. data/LICENSE +20 -0
  4. data/README.md +323 -0
  5. data/Rakefile +30 -0
  6. data/init.rb +1 -0
  7. data/lib/generators/validates_timeliness/install_generator.rb +16 -0
  8. data/lib/generators/validates_timeliness/templates/en.yml +16 -0
  9. data/lib/generators/validates_timeliness/templates/validates_timeliness.rb +40 -0
  10. data/lib/jc-validates_timeliness.rb +1 -0
  11. data/lib/validates_timeliness.rb +70 -0
  12. data/lib/validates_timeliness/attribute_methods.rb +95 -0
  13. data/lib/validates_timeliness/conversion.rb +70 -0
  14. data/lib/validates_timeliness/extensions.rb +14 -0
  15. data/lib/validates_timeliness/extensions/date_time_select.rb +61 -0
  16. data/lib/validates_timeliness/extensions/multiparameter_handler.rb +80 -0
  17. data/lib/validates_timeliness/helper_methods.rb +23 -0
  18. data/lib/validates_timeliness/orm/active_record.rb +53 -0
  19. data/lib/validates_timeliness/orm/mongoid.rb +63 -0
  20. data/lib/validates_timeliness/railtie.rb +15 -0
  21. data/lib/validates_timeliness/validator.rb +117 -0
  22. data/lib/validates_timeliness/version.rb +3 -0
  23. data/spec/spec_helper.rb +109 -0
  24. data/spec/support/config_helper.rb +36 -0
  25. data/spec/support/model_helpers.rb +27 -0
  26. data/spec/support/tag_matcher.rb +35 -0
  27. data/spec/support/test_model.rb +59 -0
  28. data/spec/validates_timeliness/attribute_methods_spec.rb +86 -0
  29. data/spec/validates_timeliness/conversion_spec.rb +234 -0
  30. data/spec/validates_timeliness/extensions/date_time_select_spec.rb +163 -0
  31. data/spec/validates_timeliness/extensions/multiparameter_handler_spec.rb +44 -0
  32. data/spec/validates_timeliness/helper_methods_spec.rb +30 -0
  33. data/spec/validates_timeliness/orm/active_record_spec.rb +244 -0
  34. data/spec/validates_timeliness/orm/mongoid_spec.rb +189 -0
  35. data/spec/validates_timeliness/validator/after_spec.rb +57 -0
  36. data/spec/validates_timeliness/validator/before_spec.rb +57 -0
  37. data/spec/validates_timeliness/validator/is_at_spec.rb +61 -0
  38. data/spec/validates_timeliness/validator/on_or_after_spec.rb +57 -0
  39. data/spec/validates_timeliness/validator/on_or_before_spec.rb +57 -0
  40. data/spec/validates_timeliness/validator_spec.rb +246 -0
  41. data/spec/validates_timeliness_spec.rb +43 -0
  42. data/validates_timeliness.gemspec +25 -0
  43. metadata +157 -0
@@ -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
@@ -0,0 +1,189 @@
1
+ require 'spec_helper'
2
+
3
+ # Try loading mongoid and connecting. Otherwise, abort and skip spec.
4
+ begin
5
+
6
+ require 'mongoid'
7
+ require 'validates_timeliness/orm/mongoid'
8
+
9
+ Mongoid.configure do |config|
10
+ name = "validates_timeliness_test"
11
+ host = "localhost"
12
+ config.master = Mongo::Connection.new.db(name)
13
+ config.persist_in_safe_mode = false
14
+ end
15
+
16
+ describe ValidatesTimeliness, 'Mongoid' do
17
+
18
+ class Article
19
+ include Mongoid::Document
20
+ field :publish_date, :type => Date
21
+ field :publish_time, :type => Time
22
+ field :publish_datetime, :type => DateTime
23
+ validates_date :publish_date, :allow_nil => true
24
+ validates_time :publish_time, :allow_nil => true
25
+ validates_datetime :publish_datetime, :allow_nil => true
26
+ end
27
+
28
+ context "validation methods" do
29
+ let(:record) { Article.new }
30
+
31
+ it 'should be defined on the class' do
32
+ expect(Article).to respond_to(:validates_date)
33
+ expect(Article).to respond_to(:validates_time)
34
+ expect(Article).to respond_to(:validates_datetime)
35
+ end
36
+
37
+ it 'should be defined on the instance' do
38
+ expect(record).to respond_to(:validates_date)
39
+ expect(record).to respond_to(:validates_time)
40
+ expect(record).to respond_to(:validates_datetime)
41
+ end
42
+
43
+ it "should validate a valid value string" do
44
+ record.publish_date = '2012-01-01'
45
+
46
+ record.valid?
47
+ expect(record.errors[:publish_date]).to be_empty
48
+ end
49
+
50
+ it "should validate a invalid value string" do
51
+ begin
52
+ record.publish_date = 'not a date'
53
+ rescue
54
+ end
55
+
56
+ record.valid?
57
+ expect(record.errors[:publish_date]).not_to be_empty
58
+ end
59
+
60
+ it "should validate a nil value" do
61
+ record.publish_date = nil
62
+
63
+ record.valid?
64
+ expect(record.errors[:publish_date]).to be_empty
65
+ end
66
+ end
67
+
68
+ it 'should determine type for attribute' do
69
+ expect(Article.timeliness_attribute_type(:publish_date)).to eq(:date)
70
+ end
71
+
72
+ context "attribute write method" do
73
+ let(:record) { Article.new }
74
+
75
+ it 'should cache attribute raw value' do
76
+ record.publish_datetime = date_string = '2010-01-01'
77
+
78
+ expect(record._timeliness_raw_value_for('publish_datetime')).to eq(date_string)
79
+ end
80
+
81
+ context "with plugin parser" do
82
+ let(:record) { ArticleWithParser.new }
83
+
84
+ class ArticleWithParser
85
+ include Mongoid::Document
86
+ field :publish_date, :type => Date
87
+ field :publish_time, :type => Time
88
+ field :publish_datetime, :type => DateTime
89
+
90
+ ValidatesTimeliness.use_plugin_parser = true
91
+ validates_date :publish_date, :allow_nil => true
92
+ validates_time :publish_time, :allow_nil => true
93
+ validates_datetime :publish_datetime, :allow_nil => true
94
+ ValidatesTimeliness.use_plugin_parser = false
95
+ end
96
+
97
+ context "for a date column" do
98
+ it 'should parse a string value' do
99
+ expect(Timeliness::Parser).to receive(:parse)
100
+
101
+ record.publish_date = '2010-01-01'
102
+ end
103
+
104
+ it 'should parse a invalid string value as nil' do
105
+ expect(Timeliness::Parser).to receive(:parse)
106
+
107
+ record.publish_date = 'not valid'
108
+ end
109
+
110
+ it 'should store a Date value after parsing string' do
111
+ record.publish_date = '2010-01-01'
112
+
113
+ expect(record.publish_date).to be_kind_of(Date)
114
+ expect(record.publish_date).to eq Date.new(2010, 1, 1)
115
+ end
116
+ end
117
+
118
+ context "for a time column" do
119
+ it 'should parse a string value' do
120
+ expect(Timeliness::Parser).to receive(:parse)
121
+
122
+ record.publish_time = '12:30'
123
+ end
124
+
125
+ it 'should parse a invalid string value as nil' do
126
+ expect(Timeliness::Parser).to receive(:parse)
127
+
128
+ record.publish_time = 'not valid'
129
+ end
130
+
131
+ it 'should store a Time value after parsing string' do
132
+ record.publish_time = '12:30'
133
+
134
+ expect(record.publish_time).to be_kind_of(Time)
135
+ expect(record.publish_time).to eq Time.utc(2000, 1, 1, 12, 30)
136
+ end
137
+ end
138
+
139
+ context "for a datetime column" do
140
+ with_config(:default_timezone, 'Australia/Melbourne')
141
+
142
+ it 'should parse a string value' do
143
+ expect(Timeliness::Parser).to receive(:parse)
144
+
145
+ record.publish_datetime = '2010-01-01 12:00'
146
+ end
147
+
148
+ it 'should parse a invalid string value as nil' do
149
+ expect(Timeliness::Parser).to receive(:parse)
150
+
151
+ record.publish_datetime = 'not valid'
152
+ end
153
+
154
+ it 'should parse string into DateTime value' do
155
+ record.publish_datetime = '2010-01-01 12:00'
156
+
157
+ expect(record.publish_datetime).to be_kind_of(DateTime)
158
+ end
159
+
160
+ pending 'should parse string as current timezone' do
161
+ record.publish_datetime = '2010-06-01 12:00'
162
+
163
+ expect(record.publish_datetime.utc_offset).to eq Time.zone.utc_offset
164
+ end
165
+ end
166
+ end
167
+ end
168
+
169
+ context "cached value" do
170
+ it 'should be cleared on reload' do
171
+ record = Article.create!
172
+ record.publish_date = '2010-01-01'
173
+ record.reload
174
+ expect(record._timeliness_raw_value_for('publish_date')).to be_nil
175
+ end
176
+ end
177
+
178
+ context "before_type_cast method" do
179
+ it 'should not be defined if ORM does not support it' do
180
+ expect(Article.new).not_to respond_to(:publish_datetime_before_type_cast)
181
+ end
182
+ end
183
+ end
184
+
185
+ rescue LoadError
186
+ puts "Mongoid specs skipped. Mongoid not installed"
187
+ rescue StandardError => e
188
+ puts "Mongoid specs skipped. MongoDB connection failed with error: #{e.message}"
189
+ end