sp-validates_timeliness 3.1.2

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.
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