validates_timeliness 5.0.0 → 6.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,319 @@
1
+ # ValidatesTimeliness [![build](https://github.com/adzap/validates_timeliness/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/adzap/validates_timeliness/actions/workflows/ci.yml)
2
+
3
+ - Source: https://github.com/adzap/validates_timeliness
4
+ - Issues: https://github.com/adzap/validates_timeliness/issues
5
+
6
+
7
+ ## Description
8
+
9
+ Complete validation of dates, times and datetimes for Rails 6.x and
10
+ ActiveModel.
11
+
12
+ Old Rails versions:
13
+
14
+ - Rails 4.x: [https://github.com/adzap/validates_timeliness/tree/4-0-stable]
15
+ - Rails 5.x: [https://github.com/adzap/validates_timeliness/tree/5-0-stable]
16
+
17
+
18
+ ## Features
19
+
20
+ - Adds validation for dates, times and datetimes to ActiveModel
21
+ - Handles timezones and type casting of values for you
22
+ - Only Rails date/time validation plugin offering complete validation (See ORM/ODM support)
23
+ - Uses extensible date/time parser (Using [timeliness gem](https://github.com/adzap/timeliness). See Plugin Parser)
24
+ - Adds extensions to fix Rails date/time select issues (See Extensions)
25
+ - Supports I18n for the error messages. For multi-language support try [timeliness-i18n gem](https://github.com/pedrofurtado/timeliness-i18n).
26
+ - Supports all the Rubies (that any sane person would be using in production).
27
+
28
+
29
+ ## Installation
30
+
31
+ In Gemfile
32
+ ```ruby
33
+ gem 'validates_timeliness', '~> 6.0.0'
34
+ ```
35
+
36
+ Run bundler:
37
+ ```bash
38
+ $ bundle install
39
+ ```
40
+
41
+ Then run
42
+ ```bash
43
+ $ rails generate validates_timeliness:install
44
+ ```
45
+
46
+ This creates configuration initializer and locale files. In the initializer, there are a number of config options to customize the plugin.
47
+
48
+ **NOTE**: You may wish to enable the plugin parser and the extensions to start.
49
+ Please read those sections first.
50
+
51
+ ## Examples
52
+
53
+ ```ruby
54
+ validates_datetime :occurred_at
55
+
56
+ validates_date :date_of_birth, before: lambda { 18.years.ago },
57
+ before_message: "must be at least 18 years old"
58
+
59
+ validates_datetime :finish_time, after: :start_time # Method symbol
60
+
61
+ validates_date :booked_at, on: :create, on_or_after: :today # See Restriction Shorthand.
62
+
63
+ validates_time :booked_at, between: ['9:00am', '5:00pm'] # On or after 9:00AM and on or before 5:00PM
64
+ validates_time :booked_at, between: '9:00am'..'5:00pm' # The same as previous example
65
+ validates_time :booked_at, between: '9:00am'...'5:00pm' # On or after 9:00AM and strictly before 5:00PM
66
+
67
+ validates_time :breakfast_time, on_or_after: '6:00am',
68
+ on_or_after_message: 'must be after opening time',
69
+ before: :lunchtime,
70
+ before_message: 'must be before lunch time'
71
+ ```
72
+
73
+ ## Usage
74
+
75
+ To validate a model with a date, time or datetime attribute you just use the
76
+ validation method:
77
+
78
+ ```ruby
79
+ class Person < ActiveRecord::Base
80
+ validates_date :date_of_birth, on_or_before: lambda { Date.current }
81
+ # or
82
+ validates :date_of_birth, timeliness: { on_or_before: lambda { Date.current }, type: :date }
83
+ end
84
+ ```
85
+
86
+ or even on a specific record, per ActiveModel API.
87
+ ```ruby
88
+ @person.validates_date :date_of_birth, on_or_before: lambda { Date.current }
89
+ ```
90
+
91
+ The list of validation methods available are as follows:
92
+ - `validates_date` - validate value as date
93
+ - `validates_time` - validate value as time only i.e. '12:20pm'
94
+ - `validates_datetime` - validate value as a full date and time
95
+ - `validates` - use the :timeliness key and set the type in the hash.
96
+
97
+ The validation methods take the usual options plus some specific ones to
98
+ restrict the valid range of dates or times allowed
99
+
100
+ Temporal options (or restrictions):
101
+ - `:is_at` - Attribute must be equal to value to be valid
102
+ - `:before` - Attribute must be before this value to be valid
103
+ - `:on_or_before` - Attribute must be equal to or before this value to be valid
104
+ - `:after` - Attribute must be after this value to be valid
105
+ - `:on_or_after` - Attribute must be equal to or after this value to be valid
106
+ - `:between` - Attribute must be between the values to be valid. Range or Array of 2 values.
107
+
108
+ Regular validation options:
109
+ - `:allow_nil` - Allow a nil value to be valid
110
+ - `:allow_blank` - Allows a nil or empty string value to be valid
111
+ - `:if` - Execute validation when :if evaluates true
112
+ - `:unless` - Execute validation when :unless evaluates false
113
+ - `:on` - Specify validation context e.g :save, :create or :update. Default is :save.
114
+
115
+ Special options:
116
+ - `:ignore_usec` - Ignores microsecond value on datetime restrictions
117
+ - `:format` - Limit validation to a single format for special cases. Requires plugin parser.
118
+
119
+ The temporal restrictions can take 4 different value types:
120
+ - Date, Time, or DateTime object value
121
+ - Proc or lambda object which may take an optional parameter, being the record object
122
+ - A symbol matching a method name in the model
123
+ - String value
124
+
125
+
126
+ When an attribute value is compared to temporal restrictions, they are
127
+ compared as the same type as the validation method type. So using
128
+ validates_date means all values are compared as dates.
129
+
130
+ ## Configuration
131
+
132
+ ### ORM/ODM Support
133
+
134
+ The plugin adds date/time validation to ActiveModel for any ORM/ODM that
135
+ supports the ActiveModel validations component. However, there is an issue
136
+ with most ORM/ODMs which does not allow 100% date/time validation by default.
137
+ Specifically, when you assign an invalid date/time value to an attribute, most
138
+ ORM/ODMs will only store a nil value for the attribute. This causes an issue
139
+ for date/time validation, since we need to know that a value was assigned but
140
+ was invalid. To fix this, we need to cache the original invalid value to know
141
+ that the attribute is not just nil.
142
+
143
+ Each ORM/ODM requires a specific shim to fix it. The plugin includes a shim
144
+ for ActiveRecord and Mongoid. You can activate them like so
145
+ ```ruby
146
+ ValidatesTimeliness.setup do |config|
147
+ # Extend ORM/ODMs for full support (:active_record).
148
+ config.extend_orms = [ :active_record ]
149
+ end
150
+ ```
151
+
152
+ By default the plugin extends ActiveRecord if loaded. If you wish to extend
153
+ another ORM then look at the [wiki page](https://github.com/adzap/validates_timeliness/wiki/ORM-Support) for more
154
+ information.
155
+
156
+ It is not required that you use a shim, but you will not catch errors when the
157
+ attribute value is invalid and evaluated to nil.
158
+
159
+ ### Error Messages
160
+
161
+ Using the I18n system to define new defaults:
162
+ ```yml
163
+ en:
164
+ errors:
165
+ messages:
166
+ invalid_date: "is not a valid date"
167
+ invalid_time: "is not a valid time"
168
+ invalid_datetime: "is not a valid datetime"
169
+ is_at: "must be at %{restriction}"
170
+ before: "must be before %{restriction}"
171
+ on_or_before: "must be on or before %{restriction}"
172
+ after: "must be after %{restriction}"
173
+ on_or_after: "must be on or after %{restriction}"
174
+ ```
175
+
176
+ The `%{restriction}` signifies where the interpolation value for the restriction will be inserted.
177
+
178
+ You can also use validation options for custom error messages. The following
179
+ option keys are available:
180
+ ```ruby
181
+ :invalid_date_message
182
+ :invalid_time_message
183
+ :invalid_datetime_message
184
+ :is_at_message
185
+ :before_message
186
+ :on_or_before_message
187
+ :after_message
188
+ :on_or_after_message
189
+ ```
190
+
191
+ **Note**: There is no `:between_message` option. The between error message should be
192
+ defined using the `:on_or_after` and `:on_or_before` (`:before` in case when
193
+ `:between` argument is a `Range` with excluded high value, see Examples) messages.
194
+
195
+ It is highly recommended you use the `I18n` system for error messages.
196
+
197
+ ### Plugin Parser
198
+
199
+ The plugin uses the [timeliness gem](https://github.com/adzap/timeliness) as a
200
+ fast, configurable and extensible date and time parser. You can add or remove
201
+ valid formats for `dates`, `times`, and `datetimes`. It is also more strict than the
202
+ Ruby parser, which means it won't accept day of the month if it's not a valid
203
+ number for the month.
204
+
205
+ By default the parser is disabled. To enable it:
206
+ ```ruby
207
+ # in the setup block
208
+ config.use_plugin_parser = true
209
+ ```
210
+
211
+ Enabling the parser will mean that strings assigned to attributes validated
212
+ with the plugin will be parsed using the gem. See the
213
+ [wiki](https://github.com/adzap/validates_timeliness/wiki/Plugin-Parser) for
214
+ more details about the parser configuration.
215
+
216
+ ### Restriction Shorthand
217
+
218
+ It is common to restrict an attribute to being on or before the current time
219
+ or current day. To specify this you need to use a lambda as an option value
220
+ e.g. `lambda { Time.current }`. This can be tedious noise amongst your
221
+ validations for something so common. To combat this the plugin allows you to
222
+ use shorthand symbols for often used relative times or dates.
223
+
224
+ Just provide the symbol as the option value like so:
225
+ ```ruby
226
+ validates_date :birth_date, on_or_before: :today
227
+ ```
228
+
229
+ The `:today` symbol is evaluated as `lambda { Date.current }`. The `:now` and
230
+ `:today` symbols are pre-configured. Configure your own like so:
231
+ ```ruby
232
+ # in the setup block
233
+ config.restriction_shorthand_symbols.update(yesterday: lambda { 1.day.ago })
234
+ ```
235
+
236
+ ### Default Timezone
237
+
238
+ The plugin needs to know the default timezone you are using when parsing or
239
+ type casting values. If you are using ActiveRecord then the default is
240
+ automatically set to the same default zone as ActiveRecord. If you are using
241
+ another ORM you may need to change this setting.
242
+ ```ruby
243
+ # in the setup block
244
+ config.default_timezone = :utc
245
+ ```
246
+
247
+ By default it will be `UTC` if ActiveRecord is not loaded.
248
+
249
+ ### Dummy Date For Time Types
250
+
251
+ Given that Ruby has no support for a time-only type, all time type columns are
252
+ evaluated as a regular Time class objects with a dummy date value set. Rails
253
+ defines the dummy date as 2000-01-01. So a time of '12:30' is evaluated as a
254
+ Time value of '2000-01-01 12:30'. If you need to customize this for some
255
+ reason you can do so as follows:
256
+ ```ruby
257
+ # in the setup block
258
+ config.dummy_date_for_time_type = [2009, 1, 1]
259
+ ```
260
+
261
+ The value should be an array of 3 values being year, month and day in that order.
262
+
263
+ ### Temporal Restriction Errors
264
+
265
+ When using the validation temporal restrictions there are times when the
266
+ restriction option value itself may be invalid. This will add an error to the
267
+ model such as 'Error occurred validating birth_date for :before restriction'.
268
+ These can be annoying in development or production as you most likely just
269
+ want to skip the option if no valid value was returned. By default these
270
+ errors are displayed in Rails test mode.
271
+
272
+ To turn them on/off:
273
+ ```ruby
274
+ # in the setup block
275
+ config.ignore_restriction_errors = true
276
+ ```
277
+
278
+ ## Extensions
279
+
280
+ ### Strict Parsing for Select Helpers
281
+
282
+ When using date/time select helpers, the component values are handled by
283
+ ActiveRecord using the Time class to instantiate them into a time value. This
284
+ means that some invalid dates, such as 31st June, are shifted forward and
285
+ treated as valid. To handle these cases in a strict way, you can enable the
286
+ plugin extension to treat them as invalid dates.
287
+
288
+ To activate it, uncomment this line in the initializer:
289
+ ```ruby
290
+ # in the setup block
291
+ config.enable_multiparameter_extension!
292
+ ```
293
+
294
+ ### Display Invalid Values in Select Helpers
295
+
296
+ The plugin offers an extension for ActionView to allowing invalid date and
297
+ time values to be redisplayed to the user as feedback, instead of a blank
298
+ field which happens by default in Rails. Though the date helpers make this a
299
+ pretty rare occurrence, given the select dropdowns for each date/time
300
+ component, but it may be something of interest.
301
+
302
+ To activate it, uncomment this line in the initializer:
303
+ ```ruby
304
+ # in the setup block
305
+ config.enable_date_time_select_extension!
306
+ ```
307
+
308
+ ## Contributors
309
+
310
+ To see the generous people who have contributed code, take a look at the
311
+ [contributors list](https://github.com/adzap/validates_timeliness/contributors).
312
+
313
+ ## Maintainers
314
+
315
+ * [Adam Meehan](https://github.com/adzap)
316
+
317
+ ## License
318
+
319
+ Copyright (c) 2021 Adam Meehan, released under the MIT license.
data/Rakefile CHANGED
@@ -5,7 +5,6 @@ require 'appraisal'
5
5
 
6
6
  Bundler::GemHelper.install_tasks
7
7
 
8
- require 'rdoc/task'
9
8
  require 'rspec/core/rake_task'
10
9
 
11
10
  desc "Run specs"
@@ -17,14 +16,5 @@ RSpec::Core::RakeTask.new(:coverage) do |t|
17
16
  t.rcov_opts = ['--exclude', 'spec']
18
17
  end
19
18
 
20
- desc 'Generate documentation for plugin.'
21
- Rake::RDocTask.new(:rdoc) do |rdoc|
22
- rdoc.rdoc_dir = 'rdoc'
23
- rdoc.title = 'ValidatesTimeliness'
24
- rdoc.options << '--line-numbers' << '--inline-source'
25
- rdoc.rdoc_files.include('README')
26
- rdoc.rdoc_files.include('lib/**/*.rb')
27
- end
28
-
29
19
  desc 'Default: run specs.'
30
20
  task :default => :spec
@@ -2,13 +2,12 @@
2
2
 
3
3
  source "http://rubygems.org"
4
4
 
5
- gem "rails", "~> 5.2.0"
5
+ gem "rails", "~> 6.0.0"
6
6
  gem "rspec"
7
7
  gem "rspec-rails", "~> 3.7"
8
- gem "timecop"
8
+ gem "sqlite3"
9
9
  gem "byebug"
10
10
  gem "appraisal"
11
- gem "sqlite3", "~> 1.3.6"
12
11
  gem "nokogiri", "~> 1.8"
13
12
 
14
13
  gemspec path: "../"
@@ -2,13 +2,13 @@
2
2
 
3
3
  source "http://rubygems.org"
4
4
 
5
- gem "rails", "~> 5.1.0"
5
+ gem "rails", "~> 6.1.0"
6
6
  gem "rspec"
7
7
  gem "rspec-rails", "~> 3.7"
8
+ gem "sqlite3"
8
9
  gem "timecop"
9
10
  gem "byebug"
10
11
  gem "appraisal"
11
- gem "sqlite3", "~> 1.3.6"
12
12
  gem "nokogiri", "~> 1.8"
13
13
 
14
14
  gemspec path: "../"
@@ -19,12 +19,13 @@ module ValidatesTimeliness
19
19
  when :date
20
20
  value.to_date
21
21
  when :datetime
22
- value.is_a?(Time) ? value : value.to_time
22
+ value.is_a?(Time) ? value : (time_zone_aware? ? value.in_time_zone : value.to_time)
23
23
  else
24
24
  value
25
25
  end
26
+
26
27
  if ignore_usec && value.is_a?(Time)
27
- Timeliness::Parser.make_time(Array(value).reverse[4..9], (:current if time_zone_aware?))
28
+ value.change(usec: 0)
28
29
  else
29
30
  value
30
31
  end
@@ -43,7 +43,7 @@ module ValidatesTimeliness
43
43
  values[POSITION.key(position.to_i)] = value.to_i
44
44
  end
45
45
 
46
- DateTimeValue.new(values)
46
+ DateTimeValue.new(**values)
47
47
  end
48
48
  end
49
49
  end
@@ -20,7 +20,7 @@ module ActiveModel
20
20
 
21
21
  def timeliness_validation_for(attr_names, type=nil)
22
22
  options = _merge_attributes(attr_names)
23
- options.update(:type => type) if type
23
+ options.update(type: type) if type
24
24
  validates_with TimelinessValidator, options
25
25
  end
26
26
  end
@@ -85,12 +85,12 @@ module ValidatesTimeliness
85
85
 
86
86
  def add_error(record, attr_name, message, value=nil)
87
87
  value = format_error_value(value) if value
88
- message_options = { :message => options.fetch(:"#{message}_message", options[:message]), :restriction => value }
89
- record.errors.add(attr_name, message, message_options)
88
+ message_options = { message: options.fetch(:"#{message}_message", options[:message]), restriction: value }
89
+ record.errors.add(attr_name, message, **message_options)
90
90
  end
91
91
 
92
92
  def format_error_value(value)
93
- format = I18n.t(@type, :default => DEFAULT_ERROR_VALUE_FORMATS[@type], :scope => 'validates_timeliness.error_value_formats')
93
+ format = I18n.t(@type, default: DEFAULT_ERROR_VALUE_FORMATS[@type], scope: 'validates_timeliness.error_value_formats')
94
94
  value.strftime(format)
95
95
  end
96
96
 
@@ -1,3 +1,3 @@
1
1
  module ValidatesTimeliness
2
- VERSION = '5.0.0'
2
+ VERSION = '6.0.1'
3
3
  end
data/spec/spec_helper.rb CHANGED
@@ -5,7 +5,7 @@ require 'active_model'
5
5
  require 'active_model/validations'
6
6
  require 'active_record'
7
7
  require 'action_view'
8
- require 'timecop'
8
+ require 'active_support/testing/time_helpers'
9
9
 
10
10
  require 'validates_timeliness'
11
11
  require 'validates_timeliness/orm/active_model'
@@ -89,6 +89,7 @@ RSpec.configure do |c|
89
89
  c.include(TagMatcher)
90
90
  c.include(ModelHelpers)
91
91
  c.include(ConfigHelper)
92
+ c.include(ActiveSupport::Testing::TimeHelpers)
92
93
  c.before do
93
94
  reset_validation_setup_for(Person)
94
95
  reset_validation_setup_for(PersonWithShim)
@@ -15,11 +15,11 @@ module TestModel
15
15
  self.model_attributes[name] = type
16
16
  end
17
17
 
18
- def define_method_attribute=(attr_name)
18
+ def define_method_attribute=(attr_name, owner: nil)
19
19
  generated_attribute_methods.module_eval("def #{attr_name}=(new_value); @attributes['#{attr_name}']=self.class.type_cast('#{attr_name}', new_value); end", __FILE__, __LINE__)
20
20
  end
21
21
 
22
- def define_method_attribute(attr_name)
22
+ def define_method_attribute(attr_name, owner: nil)
23
23
  generated_attribute_methods.module_eval("def #{attr_name}; @attributes['#{attr_name}']; end", __FILE__, __LINE__)
24
24
  end
25
25
 
@@ -7,7 +7,11 @@ RSpec.describe ValidatesTimeliness::Converter do
7
7
  let(:ignore_usec) { false }
8
8
 
9
9
  before do
10
- Timecop.freeze(Time.mktime(2010, 1, 1, 0, 0, 0))
10
+ travel_to Time.mktime(2010, 1, 1, 0, 0, 0)
11
+ end
12
+
13
+ after do
14
+ travel_back
11
15
  end
12
16
 
13
17
  delegate :type_cast_value, :evaluate, :parse, :dummy_time, to: :converter
@@ -59,30 +63,61 @@ RSpec.describe ValidatesTimeliness::Converter do
59
63
 
60
64
  describe "for datetime type" do
61
65
  let(:type) { :datetime }
62
- let(:time_zone_aware) { true }
63
66
 
64
- it "should return Date as Time value" do
65
- expect(type_cast_value(Date.new(2010, 1, 1))).to eq(Time.local(2010, 1, 1, 0, 0, 0))
67
+ it 'should return nil for invalid value types' do
68
+ expect(type_cast_value(12)).to eq(nil)
66
69
  end
67
70
 
68
- it "should return same Time value" do
69
- value = Time.utc(2010, 1, 1, 12, 34, 56)
70
- expect(type_cast_value(Time.utc(2010, 1, 1, 12, 34, 56))).to eq(value)
71
- end
71
+ context "time zone aware" do
72
+ let(:time_zone_aware) { true }
72
73
 
73
- it "should return as Time with same component values" do
74
- expect(type_cast_value(DateTime.civil_from_format(:utc, 2010, 1, 1, 12, 34, 56))).to eq(Time.utc(2010, 1, 1, 12, 34, 56))
75
- end
74
+ around { |example|
75
+ Time.use_zone("Perth", &example)
76
+ }
77
+
78
+ it "should return Date as Time value" do
79
+ Time.use_zone('London') do
80
+ result = type_cast_value(Date.new(2010, 1, 1))
81
+ expected = Time.zone.local(2010, 1, 1, 0, 0, 0)
82
+
83
+ expect(result).to eq(expected)
84
+ expect(result.zone).to eq(expected.zone)
85
+ end
86
+ end
87
+
88
+ it "should return same Time value" do
89
+ value = Time.utc(2010, 1, 1, 12, 34, 56)
90
+ expect(type_cast_value(value)).to eq(value)
91
+ end
92
+
93
+ it "should return as Time with same component values" do
94
+ expect(type_cast_value(DateTime.civil_from_format(:utc, 2010, 1, 1, 12, 34, 56))).to eq(Time.utc(2010, 1, 1, 12, 34, 56))
95
+ end
76
96
 
77
- it "should return same Time in correct zone if timezone aware" do
78
- value = Time.utc(2010, 1, 1, 12, 34, 56)
79
- result = type_cast_value(value)
80
- expect(result).to eq(Time.zone.local(2010, 1, 1, 23, 34, 56))
81
- expect(result.zone).to eq('AEDT')
97
+ it "should return same Time in correct zone if timezone aware" do
98
+ value = Time.utc(2010, 1, 1, 12, 34, 56)
99
+ result = type_cast_value(value)
100
+
101
+ expect(result).to eq(Time.zone.local(2010, 1, 1, 20, 34, 56))
102
+ expect(result.zone).to eq('AWST')
103
+ end
82
104
  end
83
105
 
84
- it 'should return nil for invalid value types' do
85
- expect(type_cast_value(12)).to eq(nil)
106
+ context "not time zone aware" do
107
+ let(:time_zone_aware) { false }
108
+
109
+ it "should return Date as Time value" do
110
+ expect(type_cast_value(Date.new(2010, 1, 1))).to eq(Time.local(2010, 1, 1, 0, 0, 0))
111
+ end
112
+
113
+ it "should return same Time value" do
114
+ value = Time.utc(2010, 1, 1, 12, 34, 56)
115
+ expect(type_cast_value(Time.utc(2010, 1, 1, 12, 34, 56))).to eq(value)
116
+ end
117
+
118
+ it "should return as Time with same component values" do
119
+ expect(type_cast_value(DateTime.civil_from_format(:utc, 2010, 1, 1, 12, 34, 56))).to eq(Time.utc(2010, 1, 1, 12, 34, 56))
120
+ end
86
121
  end
87
122
  end
88
123
 
@@ -195,10 +230,6 @@ RSpec.describe ValidatesTimeliness::Converter do
195
230
  end
196
231
 
197
232
  context "restriction shorthand" do
198
- before do
199
- Timecop.freeze(Time.mktime(2010, 1, 1, 0, 0, 0))
200
- end
201
-
202
233
  it 'should evaluate :now as current time' do
203
234
  expect(evaluate(:now, person)).to eq(Time.now)
204
235
  end
@@ -115,7 +115,11 @@ RSpec.describe 'ValidatesTimeliness::Extensions::DateTimeSelect' do
115
115
 
116
116
  describe "time_select" do
117
117
  before do
118
- Timecop.freeze Time.mktime(2009,1,1)
118
+ travel_to Time.mktime(2009,1,1)
119
+ end
120
+
121
+ after do
122
+ travel_back
119
123
  end
120
124
 
121
125
  it "should use param values when attribute is nil" do
@@ -158,5 +162,5 @@ RSpec.describe 'ValidatesTimeliness::Extensions::DateTimeSelect' do
158
162
  expect(@output).not_to have_tag("select[id=person_#{attribute}_#{index}i] option[selected=selected]")
159
163
  end
160
164
  end
161
-
165
+
162
166
  end
@@ -1,6 +1,10 @@
1
1
  RSpec.describe ValidatesTimeliness::Validator, ":is_at option" do
2
2
  before do
3
- Timecop.freeze(Time.local(2010, 1, 1, 0, 0, 0))
3
+ travel_to Time.local(2010, 1, 1, 0, 0, 0)
4
+ end
5
+
6
+ after do
7
+ travel_back
4
8
  end
5
9
 
6
10
  describe "for date type" do
@@ -1,6 +1,10 @@
1
1
  RSpec.describe ValidatesTimeliness::Validator do
2
2
  before do
3
- Timecop.freeze(Time.local(2010, 1, 1, 0, 0, 0))
3
+ travel_to Time.local(2010, 1, 1, 0, 0, 0)
4
+ end
5
+
6
+ after do
7
+ travel_back
4
8
  end
5
9
 
6
10
  describe "Model.validates with :timeliness option" do
@@ -3,19 +3,30 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
  require "validates_timeliness/version"
4
4
 
5
5
  Gem::Specification.new do |s|
6
+
7
+ github_url = 'https://github.com/adzap/validates_timeliness'
8
+
6
9
  s.name = "validates_timeliness"
7
10
  s.version = ValidatesTimeliness::VERSION
8
11
  s.authors = ["Adam Meehan"]
9
12
  s.summary = %q{Date and time validation plugin for Rails which allows custom formats}
10
13
  s.description = %q{Adds validation methods to ActiveModel for validating dates and times. Works with multiple ORMS.}
11
14
  s.email = %q{adam.meehan@gmail.com}
12
- s.homepage = %q{http://github.com/adzap/validates_timeliness}
15
+ s.homepage = github_url
13
16
  s.license = "MIT"
14
17
 
15
18
  s.require_paths = ["lib"]
16
- s.files = `git ls-files`.split("\n") - %w{ .gitignore .rspec Gemfile Gemfile.lock autotest/discover.rb Appraisals Travis.yml } - Dir['gemsfiles/*']
19
+ s.files = `git ls-files`.split("\n") - %w{ .gitignore .rspec Gemfile Gemfile.lock autotest/discover.rb Appraisals } - Dir['gemsfiles/*']
17
20
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
- s.extra_rdoc_files = ["README.rdoc", "CHANGELOG.rdoc", "LICENSE"]
21
+ s.extra_rdoc_files = ["README.md", "CHANGELOG.md", "LICENSE"]
22
+
23
+ s.metadata = {
24
+ "bug_tracker_uri" => "#{github_url}/issues",
25
+ "changelog_uri" => "#{github_url}/blob/master/CHANGELOG.md",
26
+ "source_code_uri" => "#{github_url}",
27
+ "wiki_uri" => "#{github_url}/wiki",
28
+ }
19
29
 
20
- s.add_runtime_dependency(%q<timeliness>, [">= 0.3.10", "< 1"])
30
+ s.add_runtime_dependency("activemodel", [">= 6.0.0", "< 7"])
31
+ s.add_runtime_dependency("timeliness", [">= 0.3.10", "< 1"])
21
32
  end