ae-validates_timeliness 4.0.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.
@@ -0,0 +1,23 @@
1
+ module ActiveModel
2
+ module Validations
3
+
4
+ module HelperMethods
5
+ def validates_date(*attr_names)
6
+ timeliness_validation_for attr_names, :date
7
+ end
8
+
9
+ def validates_time(*attr_names)
10
+ timeliness_validation_for attr_names, :time
11
+ end
12
+
13
+ def validates_datetime(*attr_names)
14
+ timeliness_validation_for attr_names, :datetime
15
+ end
16
+
17
+ def timeliness_validation_for(attr_names, type)
18
+ validates_with TimelinessValidator, _merge_attributes(attr_names).merge(:type => type)
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,94 @@
1
+ module ValidatesTimeliness
2
+ module ORM
3
+ module ActiveRecord
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ public
8
+
9
+ def timeliness_attribute_timezone_aware?(attr_name)
10
+ create_time_zone_conversion_attribute?(attr_name, timeliness_column_for_attribute(attr_name))
11
+ end
12
+
13
+ def timeliness_attribute_type(attr_name)
14
+ timeliness_column_for_attribute(attr_name).type
15
+ end
16
+
17
+ def timeliness_column_for_attribute(attr_name)
18
+ if ::ActiveRecord.version < ::Gem::Version.new('4.2')
19
+ columns_hash.fetch(attr_name.to_s) do |attr_name|
20
+ validation_type = _validators[attr_name.to_sym].find {|v| v.kind == :timeliness }.type
21
+ ::ActiveRecord::ConnectionAdapters::Column.new(attr_name, nil, validation_type.to_s)
22
+ end
23
+ else
24
+ columns_hash.fetch(attr_name.to_s) do |attr_name|
25
+ validation_type = _validators[attr_name.to_sym].find {|v| v.kind == :timeliness }.type
26
+ connection = ::ActiveRecord::Base.connection
27
+ connection.new_column(attr_name, nil, connection.lookup_cast_type(validation_type.to_s), validation_type.to_s)
28
+ end
29
+ end
30
+ end
31
+
32
+ def define_attribute_methods
33
+ super.tap do |attribute_methods_generated|
34
+ define_timeliness_methods(true) if attribute_methods_generated
35
+ end
36
+ end
37
+
38
+ protected
39
+
40
+ def timeliness_type_cast_code(attr_name, var_name)
41
+ type = timeliness_attribute_type(attr_name)
42
+
43
+ method_body = super
44
+ method_body << "\n#{var_name} = #{var_name}.to_date if #{var_name}" if type == :date
45
+ method_body
46
+ end
47
+ end
48
+
49
+ def reload(*args)
50
+ _clear_timeliness_cache
51
+ super
52
+ end
53
+
54
+ end
55
+
56
+ module ActiveRecordLessThan42
57
+ module ClassMethods
58
+ def allocate
59
+ define_attribute_methods
60
+ super
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def init_internals
67
+ self.class.define_attribute_methods
68
+ super
69
+ end
70
+ end
71
+
72
+ end
73
+ end
74
+
75
+ class ActiveRecord::Base
76
+ include ValidatesTimeliness::AttributeMethods
77
+ include ValidatesTimeliness::ORM::ActiveRecord
78
+
79
+ if ActiveRecord.version < Gem::Version.new('4.2')
80
+ # Rails 4.0 / 4.1 are lazy and wait until method_missing / respond_to? is called before
81
+ # calling define_attribute_methods. This is now quite complex and no longer works with
82
+ # validates timeliness when the first attribute access for a AR model is to a
83
+ # validates_timeliness attribute.
84
+ #
85
+ # In Rails 4.2, this has changes to be less lazy and probably more robust. These patches
86
+ # match Rails 4.2.
87
+
88
+ prepend ValidatesTimeliness::ORM::ActiveRecordLessThan42
89
+
90
+ class << self
91
+ prepend ValidatesTimeliness::ORM::ActiveRecordLessThan42::ClassMethods
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,63 @@
1
+ module ValidatesTimeliness
2
+ module ORM
3
+ module Mongoid
4
+ extend ActiveSupport::Concern
5
+ # You need define the fields before you define the validations.
6
+ # It is best to use the plugin parser to avoid errors on a bad
7
+ # field value in Mongoid. Parser will return nil rather than error.
8
+
9
+ module ClassMethods
10
+ public
11
+
12
+ # Mongoid has no bulk attribute method definition hook. It defines
13
+ # them with each field definition. So we likewise define them after
14
+ # each validation is defined.
15
+ #
16
+ def timeliness_validation_for(attr_names, type)
17
+ super
18
+ attr_names.each { |attr_name| define_timeliness_write_method(attr_name) }
19
+ end
20
+
21
+ def timeliness_attribute_type(attr_name)
22
+ {
23
+ Date => :date,
24
+ Time => :time,
25
+ DateTime => :datetime
26
+ }[fields[attr_name.to_s].type] || :datetime
27
+ end
28
+
29
+ protected
30
+
31
+ def timeliness_type_cast_code(attr_name, var_name)
32
+ type = timeliness_attribute_type(attr_name)
33
+
34
+ "#{var_name} = Timeliness::Parser.parse(value, :#{type})"
35
+ end
36
+
37
+ end
38
+
39
+ module Reload
40
+ def reload(*args)
41
+ _clear_timeliness_cache
42
+ super
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ module Mongoid::Document
50
+ include ValidatesTimeliness::AttributeMethods
51
+ include ValidatesTimeliness::ORM::Mongoid
52
+
53
+ # Pre-2.3 reload
54
+ if (instance_methods & ['reload', :reload]).present?
55
+ def reload_with_timeliness
56
+ _clear_timeliness_cache
57
+ reload_without_timeliness
58
+ end
59
+ alias_method_chain :reload, :timeliness
60
+ else
61
+ include ValidatesTimeliness::ORM::Mongoid::Reload
62
+ end
63
+ end
@@ -0,0 +1,15 @@
1
+ module ValidatesTimeliness
2
+ class Railtie < Rails::Railtie
3
+ initializer "validates_timeliness.initialize_active_record", :after => 'active_record.initialize_timezone' do
4
+ ActiveSupport.on_load(:active_record) do
5
+ ValidatesTimeliness.default_timezone = ActiveRecord::Base.default_timezone
6
+ ValidatesTimeliness.extend_orms << :active_record
7
+ ValidatesTimeliness.load_orms
8
+ end
9
+ end
10
+
11
+ initializer "validates_timeliness.initialize_restriction_errors" do
12
+ ValidatesTimeliness.ignore_restriction_errors = !Rails.env.test?
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,117 @@
1
+ require 'active_model'
2
+ require 'active_model/validator'
3
+
4
+ module ValidatesTimeliness
5
+ class Validator < ActiveModel::EachValidator
6
+ include Conversion
7
+
8
+ attr_reader :type
9
+
10
+ RESTRICTIONS = {
11
+ :is_at => :==,
12
+ :before => :<,
13
+ :after => :>,
14
+ :on_or_before => :<=,
15
+ :on_or_after => :>=,
16
+ }.freeze
17
+
18
+ DEFAULT_ERROR_VALUE_FORMATS = {
19
+ :date => '%Y-%m-%d',
20
+ :time => '%H:%M:%S',
21
+ :datetime => '%Y-%m-%d %H:%M:%S'
22
+ }.freeze
23
+
24
+ RESTRICTION_ERROR_MESSAGE = "Error occurred validating %s for %s restriction:\n%s"
25
+
26
+ # Prior to version 4.1, Rails will call `#setup`, if defined. This method is deprecated in Rails 4.1 and removed
27
+ # altogether in 4.2.
28
+ SETUP_DEPRECATED = ActiveModel.respond_to?(:version) && ActiveModel.version >= Gem::Version.new('4.1')
29
+
30
+ def self.kind
31
+ :timeliness
32
+ end
33
+
34
+ def initialize(options)
35
+ @type = options.delete(:type) || :datetime
36
+ @allow_nil, @allow_blank = options.delete(:allow_nil), options.delete(:allow_blank)
37
+
38
+ if range = options.delete(:between)
39
+ raise ArgumentError, ":between must be a Range or an Array" unless range.is_a?(Range) || range.is_a?(Array)
40
+ options[:on_or_after] = range.first
41
+ if range.is_a?(Range) && range.exclude_end?
42
+ options[:before] = range.last
43
+ else
44
+ options[:on_or_before] = range.last
45
+ end
46
+ end
47
+
48
+ @restrictions_to_check = RESTRICTIONS.keys & options.keys
49
+ super
50
+ setup_timeliness_validated_attributes(options[:class]) if options[:class]
51
+ end
52
+
53
+ def setup_timeliness_validated_attributes(model)
54
+ if model.respond_to?(:timeliness_validated_attributes)
55
+ model.timeliness_validated_attributes ||= []
56
+ model.timeliness_validated_attributes |= @attributes
57
+ end
58
+ end
59
+
60
+ # Provide backwards compatibility for Rails < 4.1, which expects `#setup` to be defined.
61
+ alias_method :setup, :setup_timeliness_validated_attributes unless SETUP_DEPRECATED
62
+
63
+ def validate_each(record, attr_name, value)
64
+ raw_value = attribute_raw_value(record, attr_name) || value
65
+ return if (@allow_nil && raw_value.nil?) || (@allow_blank && raw_value.blank?)
66
+
67
+ @timezone_aware = timezone_aware?(record, attr_name)
68
+ value = parse(raw_value) if value.is_a?(String) || options[:format]
69
+ value = type_cast_value(value, @type)
70
+
71
+ add_error(record, attr_name, :"invalid_#{@type}") and return if value.blank?
72
+
73
+ validate_restrictions(record, attr_name, value)
74
+ end
75
+
76
+ def validate_restrictions(record, attr_name, value)
77
+ @restrictions_to_check.each do |restriction|
78
+ begin
79
+ restriction_value = type_cast_value(evaluate_option_value(options[restriction], record), @type)
80
+ unless value.send(RESTRICTIONS[restriction], restriction_value)
81
+ add_error(record, attr_name, restriction, restriction_value) and break
82
+ end
83
+ rescue => e
84
+ unless ValidatesTimeliness.ignore_restriction_errors
85
+ message = RESTRICTION_ERROR_MESSAGE % [ attr_name, restriction.inspect, e.message ]
86
+ add_error(record, attr_name, message) and break
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ def add_error(record, attr_name, message, value=nil)
93
+ value = format_error_value(value) if value
94
+ message_options = { :message => options[:"#{message}_message"], :restriction => value }
95
+ record.errors.add(attr_name, message, message_options)
96
+ end
97
+
98
+ def format_error_value(value)
99
+ format = I18n.t(@type, :default => DEFAULT_ERROR_VALUE_FORMATS[@type], :scope => 'validates_timeliness.error_value_formats')
100
+ value.strftime(format)
101
+ end
102
+
103
+ def attribute_raw_value(record, attr_name)
104
+ record.respond_to?(:_timeliness_raw_value_for) &&
105
+ record._timeliness_raw_value_for(attr_name.to_s)
106
+ end
107
+
108
+ def timezone_aware?(record, attr_name)
109
+ record.class.respond_to?(:timeliness_attribute_timezone_aware?) &&
110
+ record.class.timeliness_attribute_timezone_aware?(attr_name)
111
+ end
112
+
113
+ end
114
+ end
115
+
116
+ # Compatibility with ActiveModel validates method which matches option keys to their validator class
117
+ ActiveModel::Validations::TimelinessValidator = ValidatesTimeliness::Validator
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ae-validates_timeliness
3
+ version: !ruby/object:Gem::Version
4
+ version: 4.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Paul Kmiec
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: timeliness
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.3.7
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.3.7
41
+ - !ruby/object:Gem::Dependency
42
+ name: coveralls
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-collection_matchers
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Adds validation methods to ActiveModel for validating dates and times.
98
+ Works with multiple ORMS.
99
+ email: paul.kmiec@appfolio.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - Appraisals
105
+ - CHANGELOG.rdoc
106
+ - Gemfile
107
+ - Gemfile.lock
108
+ - LICENSE
109
+ - README.md
110
+ - Rakefile
111
+ - ae-validates_timeliness.gemspec
112
+ - autotest/discover.rb
113
+ - gemfiles/rails_4_0.gemfile
114
+ - gemfiles/rails_4_0.gemfile.lock
115
+ - gemfiles/rails_4_1.gemfile
116
+ - gemfiles/rails_4_1.gemfile.lock
117
+ - gemfiles/rails_4_2.gemfile
118
+ - gemfiles/rails_4_2.gemfile.lock
119
+ - init.rb
120
+ - lib/ae-validates_timeliness.rb
121
+ - lib/ae-validates_timeliness/version.rb
122
+ - lib/generators/validates_timeliness/install_generator.rb
123
+ - lib/generators/validates_timeliness/templates/en.yml
124
+ - lib/generators/validates_timeliness/templates/validates_timeliness.rb
125
+ - lib/validates_timeliness.rb
126
+ - lib/validates_timeliness/attribute_methods.rb
127
+ - lib/validates_timeliness/conversion.rb
128
+ - lib/validates_timeliness/extensions.rb
129
+ - lib/validates_timeliness/extensions/date_time_select.rb
130
+ - lib/validates_timeliness/extensions/multiparameter_handler.rb
131
+ - lib/validates_timeliness/helper_methods.rb
132
+ - lib/validates_timeliness/orm/active_record.rb
133
+ - lib/validates_timeliness/orm/mongoid.rb
134
+ - lib/validates_timeliness/railtie.rb
135
+ - lib/validates_timeliness/validator.rb
136
+ homepage: http://github.com/appfolio/validates_timeliness
137
+ licenses: []
138
+ metadata: {}
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ requirements: []
154
+ rubyforge_project:
155
+ rubygems_version: 2.4.7
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: Date and time validation plugin for Rails which allows custom formats
159
+ test_files: []