client_side_validations 4.2.0 → 6.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +71 -0
- data/README.md +32 -25
- data/lib/client_side_validations/action_view/form_builder.rb +37 -49
- data/lib/client_side_validations/action_view/form_helper.rb +32 -26
- data/lib/client_side_validations/action_view.rb +1 -1
- data/lib/client_side_validations/active_model/conditionals.rb +41 -0
- data/lib/client_side_validations/active_model/format.rb +6 -12
- data/lib/client_side_validations/active_model/numericality.rb +5 -8
- data/lib/client_side_validations/active_model.rb +15 -23
- data/lib/client_side_validations/active_record/middleware.rb +22 -13
- data/lib/client_side_validations/active_record.rb +5 -6
- data/lib/client_side_validations/generators.rb +6 -2
- data/lib/client_side_validations/middleware.rb +5 -5
- data/lib/client_side_validations/version.rb +2 -1
- data/lib/generators/client_side_validations/copy_assets_generator.rb +15 -15
- data/lib/generators/client_side_validations/install_generator.rb +0 -2
- data/vendor/assets/javascripts/rails.validations.js +37 -29
- metadata +60 -69
- data/HISTORY.md +0 -46
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 62857994d1326cfb20a2c2d3c1c5fd746fa72065
|
|
4
|
+
data.tar.gz: 5d187e21b9b0b8935f3d5bfee8099095a128a389
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 284d47098c63a20c73aad2d252028e54ecd7b519d6130d16170206440e4f70b6e28f70be895a71c4f71dc555acf65765f1137acbded5910aa5aea779bdf3862a
|
|
7
|
+
data.tar.gz: 4c0b3c38d2254184cd34841d87683a3c21e0e5c1805be57134b913078f96e964e920cf78b85efb41a214f9bb81721b24e3e78996ca82e2877e751d15717cb6b2
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 6.0.0 (2017-01-20)
|
|
4
|
+
|
|
5
|
+
* Rails 5.0 compatibility
|
|
6
|
+
|
|
7
|
+
## 4.2.12 (2017-01-19)
|
|
8
|
+
|
|
9
|
+
* Add Changelog ([#688](https://github.com/DavyJonesLocker/client_side_validations/issues/688))
|
|
10
|
+
* Test against jQuery from 1.7.2 to 3.1.1
|
|
11
|
+
* Drop Ruby 2.0.0 support
|
|
12
|
+
* Other minor changes
|
|
13
|
+
|
|
14
|
+
## 4.2.11 (2016-12-08)
|
|
15
|
+
|
|
16
|
+
* Fix conditional validators ([#686](https://github.com/DavyJonesLocker/client_side_validations/issues/686))
|
|
17
|
+
|
|
18
|
+
## 4.2.10 (2016-11-16)
|
|
19
|
+
|
|
20
|
+
* Fix dollar sign in regular expression ([#684](https://github.com/DavyJonesLocker/client_side_validations/issues/684))
|
|
21
|
+
|
|
22
|
+
## 4.2.9 (2016-11-11)
|
|
23
|
+
|
|
24
|
+
* Fix jQuery 3 compatibility
|
|
25
|
+
|
|
26
|
+
## 4.2.8 (2016-11-11)
|
|
27
|
+
|
|
28
|
+
* Fix numericality validator ([#679](https://github.com/DavyJonesLocker/client_side_validations/pull/679))
|
|
29
|
+
|
|
30
|
+
## 4.2.7 (2016-10-08)
|
|
31
|
+
|
|
32
|
+
* Fix: Prevent undesired `stopPropagation` on `focusout` event ([#675](https://github.com/DavyJonesLocker/client_side_validations/pull/675))
|
|
33
|
+
|
|
34
|
+
## 4.2.6 (2016-09-10)
|
|
35
|
+
|
|
36
|
+
* Add some clarity to the `copy_assets` command ([#671](https://github.com/DavyJonesLocker/client_side_validations/pull/671))
|
|
37
|
+
* Other minor changes
|
|
38
|
+
|
|
39
|
+
## 4.2.5 (2016-07-06)
|
|
40
|
+
|
|
41
|
+
* Fix: Make helpers consistent with their Rails counterparts ([#665](https://github.com/DavyJonesLocker/client_side_validations/issues/665))
|
|
42
|
+
* Other minor changes
|
|
43
|
+
|
|
44
|
+
## 4.2.4 (2016-06-14)
|
|
45
|
+
|
|
46
|
+
* Add Turbolinks 5 compatibility
|
|
47
|
+
* Drop Ruby 1.9 support
|
|
48
|
+
* Test against Ruby 2.1.10, 2.2.5 and 2.3.1
|
|
49
|
+
* Test against jQuery 1.12.4
|
|
50
|
+
|
|
51
|
+
## 4.2.3 (2016-03-14)
|
|
52
|
+
|
|
53
|
+
* Test against jQuery 1.12.1
|
|
54
|
+
* Other minor changes
|
|
55
|
+
|
|
56
|
+
## 4.2.2 (2016-02-28)
|
|
57
|
+
|
|
58
|
+
* Fix uniqueness validator data disclosure ([#648](https://github.com/DavyJonesLocker/client_side_validations/issues/648))
|
|
59
|
+
* Fix config.root_path to work in middleware ([#598](https://github.com/DavyJonesLocker/client_side_validations/pull/598))
|
|
60
|
+
* Other minor changes
|
|
61
|
+
|
|
62
|
+
## 4.2.1 (2016-01-15)
|
|
63
|
+
|
|
64
|
+
* Test against jQuery 1.12.0
|
|
65
|
+
* Other minor changes
|
|
66
|
+
|
|
67
|
+
## 4.2.0 (2016-01-07)
|
|
68
|
+
|
|
69
|
+
* First Rails 4.x compatible version
|
|
70
|
+
|
|
71
|
+
For older versions, please refer to [GitHub releases](https://github.com/DavyJonesLocker/client_side_validations/releases)
|
data/README.md
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
[](https://travis-ci.org/DavyJonesLocker/client_side_validations)
|
|
5
5
|
[](https://gemnasium.com/DavyJonesLocker/client_side_validations)
|
|
6
6
|
[](https://codeclimate.com/github/DavyJonesLocker/client_side_validations)
|
|
7
|
-
[](https://coveralls.io/
|
|
7
|
+
[](https://coveralls.io/github/DavyJonesLocker/client_side_validations?branch=master)
|
|
8
8
|
|
|
9
|
-
`ClientSideValidations` made easy for your Rails
|
|
9
|
+
`ClientSideValidations` made easy for your Rails 5 applications!
|
|
10
10
|
|
|
11
11
|
## Project Goals ##
|
|
12
12
|
|
|
13
|
-
1. Follow the best practices for client side validations developed by [Luke Wroblewski](http://
|
|
13
|
+
1. Follow the best practices for client side validations developed by [Luke Wroblewski](http://alistapart.com/article/inline-validation-in-web-forms)
|
|
14
14
|
2. Automatically extract and apply validation rules defined on the
|
|
15
15
|
server to the client.
|
|
16
16
|
3. In the cases where a server-side validation rule would not work on
|
|
@@ -46,11 +46,12 @@ This will install the initializer:
|
|
|
46
46
|
config/initializers/client_side_validations.rb
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
If you
|
|
49
|
+
If you need to copy the asset files from the gem into your project:
|
|
50
50
|
|
|
51
51
|
```
|
|
52
52
|
rails g client_side_validations:copy_assets
|
|
53
53
|
```
|
|
54
|
+
Note: If you run `copy_assets`, you will need to run it again each time you update this project.
|
|
54
55
|
|
|
55
56
|
## Initializer ##
|
|
56
57
|
|
|
@@ -70,10 +71,10 @@ There is additional support for other `ActiveModel` based ORMs and other
|
|
|
70
71
|
Rails `FormBuilders`. Please see the [Plugin wiki page](https://github.com/DavyJonesLocker/client_side_validations/wiki/Plugins)
|
|
71
72
|
(feel free to add your own)
|
|
72
73
|
|
|
73
|
-
* [SimpleForm](https://github.com/
|
|
74
|
-
* [Formtastic](https://github.com/
|
|
75
|
-
* [Mongoid](https://github.com/
|
|
76
|
-
* [MongoMapper](https://github.com/
|
|
74
|
+
* [SimpleForm](https://github.com/DavyJonesLocker/client_side_validations-simple_form)
|
|
75
|
+
* [Formtastic](https://github.com/DavyJonesLocker/client_side_validations-formtastic)
|
|
76
|
+
* [Mongoid](https://github.com/DavyJonesLocker/client_side_validations-mongoid)
|
|
77
|
+
* [MongoMapper](https://github.com/DavyJonesLocker/client_side_validations-mongo_mapper)
|
|
77
78
|
|
|
78
79
|
## Usage ##
|
|
79
80
|
|
|
@@ -142,7 +143,24 @@ individual validators:
|
|
|
142
143
|
|
|
143
144
|
In the above case only the `presence` validator will be passed to the client.
|
|
144
145
|
|
|
145
|
-
This is also the case with
|
|
146
|
+
This is also the case with [other supported conditional validations](http://guides.rubyonrails.org/v4.2.0/active_record_validations.html#conditional-validation) (such as Procs, Arrays or Strings).
|
|
147
|
+
|
|
148
|
+
**NOTE:** when `:if` conditional includes a symbol or a string with
|
|
149
|
+
`changed?` in it, validator will forced automatically.
|
|
150
|
+
|
|
151
|
+
```ruby
|
|
152
|
+
class Person < ActiveRecord::Base
|
|
153
|
+
validates :name, presence: true, if: :name_changed?
|
|
154
|
+
end
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The presence of name in the example above will be validated
|
|
158
|
+
without explicit forcing.
|
|
159
|
+
|
|
160
|
+
This is done because it is always assumed the value will change on the
|
|
161
|
+
form.
|
|
162
|
+
|
|
163
|
+
Conditionals defined with `:unless` key do not have this optimization.
|
|
146
164
|
|
|
147
165
|
### Turning off validators ###
|
|
148
166
|
|
|
@@ -504,9 +522,9 @@ Note that the `FormBuilder` will automatically skip building validators that are
|
|
|
504
522
|
|
|
505
523
|
## Authors ##
|
|
506
524
|
|
|
507
|
-
[Brian Cardarella](
|
|
525
|
+
[Brian Cardarella](https://twitter.com/bcardarella)
|
|
508
526
|
|
|
509
|
-
[Geremia Taglialatela](
|
|
527
|
+
[Geremia Taglialatela](https://twitter.com/gtagliala)
|
|
510
528
|
|
|
511
529
|
[We are very thankful for the many contributors](https://github.com/DavyJonesLocker/client_side_validations/graphs/contributors)
|
|
512
530
|
|
|
@@ -514,17 +532,6 @@ Note that the `FormBuilder` will automatically skip building validators that are
|
|
|
514
532
|
|
|
515
533
|
This gem follows [Semantic Versioning](http://semver.org)
|
|
516
534
|
|
|
517
|
-
Major and minor version numbers will follow `Rails`'s major and
|
|
518
|
-
minor version numbers. For example,
|
|
519
|
-
`client_side_validations-4.2.0` will be compatible up to
|
|
520
|
-
`~> rails-4.2.0`
|
|
521
|
-
|
|
522
|
-
We will maintain compatibility with one minor version back. So the 4.2.0 version of `client_side_validations`
|
|
523
|
-
will be compatible with `~> rails-4.1.0`. We will not drop support
|
|
524
|
-
to older versions if not necessary.
|
|
525
|
-
|
|
526
|
-
Only two versions minor versions will be actively maintained.
|
|
527
|
-
|
|
528
535
|
## Want to help? ##
|
|
529
536
|
|
|
530
537
|
Please do! We are always looking to improve this gem. Please see our
|
|
@@ -533,8 +540,8 @@ on how to properly submit issues and pull requests.
|
|
|
533
540
|
|
|
534
541
|
## Legal ##
|
|
535
542
|
|
|
536
|
-
[DockYard](
|
|
543
|
+
[DockYard](https://dockyard.com/), LLC © 2012-2017
|
|
537
544
|
|
|
538
|
-
[@dockyard](
|
|
545
|
+
[@dockyard](https://twitter.com/dockyard)
|
|
539
546
|
|
|
540
|
-
[Licensed under the MIT license](
|
|
547
|
+
[Licensed under the MIT license](https://opensource.org/licenses/mit-license.php)
|
|
@@ -2,30 +2,21 @@ module ClientSideValidations
|
|
|
2
2
|
module ActionView
|
|
3
3
|
module Helpers
|
|
4
4
|
module FormBuilder
|
|
5
|
-
def self.
|
|
5
|
+
def self.prepended(base)
|
|
6
6
|
(base.field_helpers.map(&:to_s) - %w(apply_form_for_options! label check_box radio_button fields_for hidden_field)).each do |selector|
|
|
7
7
|
base.class_eval <<-RUBY_EVAL
|
|
8
|
-
def #{selector}
|
|
8
|
+
def #{selector}(method, options = {})
|
|
9
9
|
build_validation_options(method, options)
|
|
10
10
|
options.delete(:validate)
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
# Cannot call super here, override the whole method
|
|
13
|
+
@template.send( # @template.send(
|
|
14
|
+
#{selector.inspect}, # "text_field",
|
|
15
|
+
@object_name, # @object_name,
|
|
16
|
+
method, # method,
|
|
17
|
+
objectify_options(options)) # objectify_options(options))
|
|
12
18
|
end
|
|
13
19
|
RUBY_EVAL
|
|
14
|
-
|
|
15
|
-
base.class_eval { alias_method_chain selector, :client_side_validations }
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
base.class_eval do
|
|
19
|
-
alias_method_chain :initialize, :client_side_validations
|
|
20
|
-
alias_method_chain :fields_for, :client_side_validations
|
|
21
|
-
alias_method_chain :check_box, :client_side_validations
|
|
22
|
-
alias_method_chain :radio_button, :client_side_validations
|
|
23
|
-
alias_method_chain :select, :client_side_validations
|
|
24
|
-
alias_method_chain :collection_select, :client_side_validations
|
|
25
|
-
alias_method_chain :collection_check_boxes, :client_side_validations
|
|
26
|
-
alias_method_chain :collection_radio_buttons, :client_side_validations
|
|
27
|
-
alias_method_chain :grouped_collection_select, :client_side_validations
|
|
28
|
-
alias_method_chain :time_zone_select, :client_side_validations
|
|
29
20
|
end
|
|
30
21
|
end
|
|
31
22
|
|
|
@@ -45,63 +36,58 @@ module ClientSideValidations
|
|
|
45
36
|
nil
|
|
46
37
|
end
|
|
47
38
|
|
|
48
|
-
def
|
|
49
|
-
|
|
39
|
+
def initialize(object_name, object, template, options)
|
|
40
|
+
super(object_name, object, template, options)
|
|
50
41
|
@options[:validators] = { object => {} }
|
|
51
42
|
end
|
|
52
43
|
|
|
53
|
-
def
|
|
54
|
-
options
|
|
55
|
-
|
|
56
|
-
fields_for_without_client_side_validations(record_or_name_or_array, *(args << options), &block)
|
|
44
|
+
def fields_for(record_name, record_object = nil, fields_options = {}, &block)
|
|
45
|
+
fields_options[:validate] ||= @options[:validate] if @options[:validate] && !fields_options.key?(:validate)
|
|
46
|
+
super(record_name, record_object, fields_options, &block)
|
|
57
47
|
end
|
|
58
48
|
|
|
59
|
-
def
|
|
49
|
+
def check_box(method, options = {}, checked_value = '1', unchecked_value = '0')
|
|
60
50
|
build_validation_options(method, options)
|
|
61
51
|
options.delete(:validate)
|
|
62
|
-
|
|
52
|
+
super(method, options, checked_value, unchecked_value)
|
|
63
53
|
end
|
|
64
54
|
|
|
65
|
-
def
|
|
55
|
+
def radio_button(method, tag_value, options = {})
|
|
66
56
|
build_validation_options(method, options)
|
|
67
57
|
options.delete(:validate)
|
|
68
|
-
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def select_with_client_side_validations(method, choices, options = {}, html_options = {}, &block)
|
|
72
|
-
build_validation_options(method, html_options.merge(name: options[:name]))
|
|
73
|
-
html_options.delete(:validate)
|
|
74
|
-
select_without_client_side_validations(method, choices, options, html_options, &block)
|
|
58
|
+
super(method, tag_value, options)
|
|
75
59
|
end
|
|
76
60
|
|
|
77
|
-
def
|
|
61
|
+
def select(method, choices = nil, options = {}, html_options = {}, &block)
|
|
78
62
|
build_validation_options(method, html_options.merge(name: options[:name]))
|
|
79
63
|
html_options.delete(:validate)
|
|
80
|
-
|
|
64
|
+
super(method, choices, options, html_options, &block)
|
|
81
65
|
end
|
|
82
66
|
|
|
83
|
-
def
|
|
67
|
+
def collection_select(method, collection, value_method, text_method, options = {}, html_options = {})
|
|
84
68
|
build_validation_options(method, html_options.merge(name: options[:name]))
|
|
85
69
|
html_options.delete(:validate)
|
|
86
|
-
|
|
70
|
+
super(method, collection, value_method, text_method, options, html_options)
|
|
87
71
|
end
|
|
88
72
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
73
|
+
%i(collection_check_boxes collection_radio_buttons).each do |method_name|
|
|
74
|
+
define_method method_name do |method, collection, value_method, text_method, options = {}, html_options = {}, &block|
|
|
75
|
+
build_validation_options(method, html_options.merge(name: options[:name]))
|
|
76
|
+
html_options.delete(:validate)
|
|
77
|
+
super(method, collection, value_method, text_method, options, html_options, &block)
|
|
78
|
+
end
|
|
93
79
|
end
|
|
94
80
|
|
|
95
|
-
def
|
|
81
|
+
def grouped_collection_select(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
|
|
96
82
|
build_validation_options(method, html_options.merge(name: options[:name]))
|
|
97
83
|
html_options.delete(:validate)
|
|
98
|
-
|
|
84
|
+
super(method, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options)
|
|
99
85
|
end
|
|
100
86
|
|
|
101
|
-
def
|
|
87
|
+
def time_zone_select(method, priority_zones = nil, options = {}, html_options = {})
|
|
102
88
|
build_validation_options(method, html_options.merge(name: options[:name]))
|
|
103
89
|
html_options.delete(:validate)
|
|
104
|
-
|
|
90
|
+
super(method, priority_zones, options, html_options)
|
|
105
91
|
end
|
|
106
92
|
|
|
107
93
|
private
|
|
@@ -109,11 +95,13 @@ module ClientSideValidations
|
|
|
109
95
|
def build_validation_options(method, options = {})
|
|
110
96
|
return unless @options[:validate]
|
|
111
97
|
|
|
112
|
-
index
|
|
113
|
-
name = options[:name] || "#{@object_name}#{index}[#{method}]"
|
|
98
|
+
index = @default_options[:index].present? ? "[#{@default_options[:index]}]" : ''
|
|
114
99
|
child_index = @options[:child_index] ? "(\\d+|#{Regexp.escape(@options[:child_index].to_s)})" : '\\d+'
|
|
100
|
+
|
|
101
|
+
name = options[:name] || "#{@object_name}#{index}[#{method}]"
|
|
115
102
|
name = name.to_s.gsub(/_attributes\]\[#{child_index}\]/, '_attributes][]')
|
|
116
|
-
name
|
|
103
|
+
name << '[]' if options[:multiple]
|
|
104
|
+
|
|
117
105
|
@options[:validators][@object][method] = { name: name, options: options[:validate] }
|
|
118
106
|
end
|
|
119
107
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module ClientSideValidations
|
|
2
3
|
module ActionView
|
|
3
4
|
module Helpers
|
|
@@ -6,7 +7,7 @@ module ClientSideValidations
|
|
|
6
7
|
end
|
|
7
8
|
|
|
8
9
|
def form_for(record, options = {}, &block)
|
|
9
|
-
|
|
10
|
+
raise ArgumentError, 'Missing block' unless block_given?
|
|
10
11
|
if options[:validate]
|
|
11
12
|
|
|
12
13
|
# Always turn off HTML5 Validations
|
|
@@ -15,7 +16,7 @@ module ClientSideValidations
|
|
|
15
16
|
|
|
16
17
|
case record
|
|
17
18
|
when String, Symbol
|
|
18
|
-
|
|
19
|
+
raise ClientSideValidations::ActionView::Helpers::FormHelper::Error, 'Using form_for(:name, @resource) is not supported with ClientSideValidations. Please use form_for(@resource, as: :name) instead.'
|
|
19
20
|
else
|
|
20
21
|
object = record.is_a?(Array) ? record.last : record
|
|
21
22
|
object_name = options[:as] || model_name_from_record_or_class(object).param_key
|
|
@@ -37,17 +38,23 @@ module ClientSideValidations
|
|
|
37
38
|
# Would be nice to not do this
|
|
38
39
|
script = insert_validators_into_script(script)
|
|
39
40
|
|
|
41
|
+
# rubocop:disable OutputSafety
|
|
42
|
+
# TODO: check if html_safe is really needed here
|
|
40
43
|
if assign_script_to_content_for(options[:validate], script)
|
|
41
44
|
form.html_safe
|
|
42
45
|
else
|
|
43
46
|
"#{form}#{script}".html_safe
|
|
44
47
|
end
|
|
48
|
+
# rubocop:enable OutputSafety
|
|
45
49
|
end
|
|
46
50
|
|
|
47
51
|
def assign_script_to_content_for(name, script)
|
|
52
|
+
# rubocop:disable OutputSafety
|
|
53
|
+
# TODO: check if html_safe is really needed here
|
|
48
54
|
return unless name && name != true
|
|
49
|
-
content_for
|
|
55
|
+
content_for name, script.html_safe
|
|
50
56
|
true
|
|
57
|
+
# rubocop:enable OutputSafety
|
|
51
58
|
end
|
|
52
59
|
|
|
53
60
|
def apply_form_for_options!(record, object, options)
|
|
@@ -91,11 +98,12 @@ module ClientSideValidations
|
|
|
91
98
|
result[attr[0]] = attr[1][:options]
|
|
92
99
|
end
|
|
93
100
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
validation_hash =
|
|
102
|
+
if object_opts[0].respond_to?(:client_side_validation_hash)
|
|
103
|
+
object_opts[0].client_side_validation_hash(option_hash)
|
|
104
|
+
else
|
|
105
|
+
{}
|
|
106
|
+
end
|
|
99
107
|
|
|
100
108
|
option_hash.each_key do |attr|
|
|
101
109
|
if validation_hash[attr]
|
|
@@ -107,27 +115,25 @@ module ClientSideValidations
|
|
|
107
115
|
|
|
108
116
|
def client_side_form_settings(object, options, builder)
|
|
109
117
|
return unless options[:validate]
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
var_name =
|
|
119
|
+
if options[:id]
|
|
120
|
+
options[:id]
|
|
121
|
+
elsif object.respond_to?(:persisted?) && object.persisted?
|
|
122
|
+
options[:as] ? "edit_#{options[:as]}" : [options[:namespace], dom_id(object, :edit)].compact.join('_'.freeze)
|
|
123
|
+
else
|
|
124
|
+
options[:as] ? "new_#{options[:as]}" : [options[:namespace], dom_id(object)].compact.join('_'.freeze)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
number_format =
|
|
128
|
+
if ClientSideValidations::Config.number_format_with_locale && defined?(I18n)
|
|
129
|
+
I18n.t('number.format').slice(:separator, :delimiter)
|
|
130
|
+
else
|
|
131
|
+
{ separator: '.', delimiter: ',' }
|
|
132
|
+
end
|
|
120
133
|
|
|
121
|
-
if ClientSideValidations::Config.number_format_with_locale && defined?(I18n)
|
|
122
|
-
number_format = I18n.t('number.format').slice(:separator, :delimiter)
|
|
123
|
-
else
|
|
124
|
-
number_format = { separator: '.', delimiter: ',' }
|
|
125
|
-
end
|
|
126
134
|
patterns = { numericality: "/^(-|\\+)?(?:\\d+|\\d{1,3}(?:\\#{number_format[:delimiter]}\\d{3})+)(?:\\#{number_format[:separator]}\\d*)?$/" }
|
|
127
135
|
|
|
128
|
-
|
|
129
|
-
"//<![CDATA[\nif(window.ClientSideValidations===undefined)window.ClientSideValidations={};window.ClientSideValidations.disabled_validators=#{ClientSideValidations::Config.disabled_validators.to_json};window.ClientSideValidations.number_format=#{number_format.to_json};if(window.ClientSideValidations.patterns===undefined)window.ClientSideValidations.patterns = {};window.ClientSideValidations.patterns.numericality=#{patterns[:numericality]};#{"if(window.ClientSideValidations.remote_validators_prefix===undefined)window.ClientSideValidations.remote_validators_prefix='#{(ClientSideValidations::Config.root_path).sub(%r{/+\Z}, '')}';" if ClientSideValidations::Config.root_path.present?}if(window.ClientSideValidations.forms===undefined)window.ClientSideValidations.forms={};window.ClientSideValidations.forms['#{var_name}'] = #{builder.client_side_form_settings(options, self).merge(validators: 'validator_hash').to_json};\n//]]>".html_safe
|
|
130
|
-
end
|
|
136
|
+
javascript_tag "if(window.ClientSideValidations===undefined)window.ClientSideValidations={};window.ClientSideValidations.disabled_validators=#{ClientSideValidations::Config.disabled_validators.to_json};window.ClientSideValidations.number_format=#{number_format.to_json};if(window.ClientSideValidations.patterns===undefined)window.ClientSideValidations.patterns = {};window.ClientSideValidations.patterns.numericality=#{patterns[:numericality]};#{"if(window.ClientSideValidations.remote_validators_prefix===undefined)window.ClientSideValidations.remote_validators_prefix='#{ClientSideValidations::Config.root_path.sub(%r{/+\Z}, '')}';" if ClientSideValidations::Config.root_path.present?}if(window.ClientSideValidations.forms===undefined)window.ClientSideValidations.forms={};window.ClientSideValidations.forms['#{var_name}'] = #{builder.client_side_form_settings(options, self).merge(validators: 'validator_hash').to_json};"
|
|
131
137
|
end
|
|
132
138
|
end
|
|
133
139
|
end
|
|
@@ -12,4 +12,4 @@ require 'client_side_validations/action_view/form_builder'
|
|
|
12
12
|
|
|
13
13
|
ActionView::Base.send(:include, ClientSideValidations::ActionView::Helpers::FormHelper)
|
|
14
14
|
ActionView::Base.send(:include, ClientSideValidations::ActionView::Helpers::FormTagHelper)
|
|
15
|
-
ActionView::Helpers::FormBuilder.send(:
|
|
15
|
+
ActionView::Helpers::FormBuilder.send(:prepend, ClientSideValidations::ActionView::Helpers::FormBuilder)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module ClientSideValidations
|
|
2
|
+
module ActiveModel
|
|
3
|
+
module Conditionals
|
|
4
|
+
private
|
|
5
|
+
|
|
6
|
+
def run_conditionals(conditionals, conditional_type)
|
|
7
|
+
Array.wrap(conditionals).all? do |conditional|
|
|
8
|
+
value = run_one_conditional(conditional)
|
|
9
|
+
if conditional_type == :unless
|
|
10
|
+
!value
|
|
11
|
+
else
|
|
12
|
+
value
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def run_one_conditional(conditional)
|
|
18
|
+
case conditional
|
|
19
|
+
when ::Proc
|
|
20
|
+
case conditional.arity
|
|
21
|
+
when 0
|
|
22
|
+
instance_exec(&conditional)
|
|
23
|
+
when 1
|
|
24
|
+
instance_exec(self, &conditional)
|
|
25
|
+
else
|
|
26
|
+
raise ArgumentError, 'Missing argument'
|
|
27
|
+
end
|
|
28
|
+
when String
|
|
29
|
+
# rubocop:disable Security/Eval'
|
|
30
|
+
l = eval "lambda { |value| #{conditional} }"
|
|
31
|
+
# rubocop:enable Security/Eval'
|
|
32
|
+
instance_exec(nil, &l)
|
|
33
|
+
when Symbol
|
|
34
|
+
send conditional
|
|
35
|
+
else
|
|
36
|
+
raise ArgumentError, "Unknown conditional #{conditional}. If supported by ActiveModel/ActiveRecord open a bug for client_side_validations gem."
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -4,19 +4,13 @@ module ClientSideValidations
|
|
|
4
4
|
def client_side_hash(model, attribute, force = nil)
|
|
5
5
|
options = self.options.dup
|
|
6
6
|
if options[:with].respond_to?(:call)
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
else
|
|
11
|
-
return
|
|
12
|
-
end
|
|
7
|
+
return unless force
|
|
8
|
+
options[:with] = options[:with].call(model)
|
|
9
|
+
build_client_side_hash(model, attribute, options)
|
|
13
10
|
elsif options[:without].respond_to?(:call)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
else
|
|
18
|
-
return
|
|
19
|
-
end
|
|
11
|
+
return unless force
|
|
12
|
+
options[:without] = options[:without].call(model)
|
|
13
|
+
build_client_side_hash(model, attribute, options)
|
|
20
14
|
else
|
|
21
15
|
super
|
|
22
16
|
end
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
module ClientSideValidations
|
|
2
2
|
module ActiveModel
|
|
3
3
|
module Numericality
|
|
4
|
-
|
|
4
|
+
@@option_map = {}
|
|
5
5
|
|
|
6
6
|
def self.included(base)
|
|
7
|
-
|
|
7
|
+
@@option_map.merge!(base::CHECKS.keys.inject({}) { |acc, elem| acc.merge!(elem => elem) })
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def client_side_hash(model, attribute, force = nil)
|
|
@@ -18,16 +18,13 @@ module ClientSideValidations
|
|
|
18
18
|
|
|
19
19
|
hash[:allow_blank] = true if options[:allow_nil] || options[:allow_blank]
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
@@option_map.each do |option, message_type|
|
|
22
22
|
count = options[option]
|
|
23
23
|
next unless count
|
|
24
24
|
|
|
25
25
|
if count.respond_to?(:call)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
else
|
|
29
|
-
next
|
|
30
|
-
end
|
|
26
|
+
next unless force
|
|
27
|
+
count = count.call(model)
|
|
31
28
|
end
|
|
32
29
|
|
|
33
30
|
hash[:messages][option] = model.errors.generate_message(attribute, message_type, options.merge(count: count))
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'client_side_validations/core_ext'
|
|
2
|
+
require 'client_side_validations/active_model/conditionals'
|
|
2
3
|
|
|
3
4
|
module ClientSideValidations
|
|
4
5
|
module ActiveModel
|
|
@@ -23,6 +24,8 @@ module ClientSideValidations
|
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
module Validations
|
|
27
|
+
include ClientSideValidations::ActiveModel::Conditionals
|
|
28
|
+
|
|
26
29
|
def client_side_validation_hash(force = nil)
|
|
27
30
|
_validators.inject({}) do |attr_hash, attr|
|
|
28
31
|
return attr_hash if [nil, :block].include?(attr[0])
|
|
@@ -59,7 +62,7 @@ module ClientSideValidations
|
|
|
59
62
|
return false if validator_turned_off?(attr, validator, force)
|
|
60
63
|
|
|
61
64
|
# Yeah yeah, #new_record? is not part of ActiveModel :p
|
|
62
|
-
result = ((
|
|
65
|
+
result = ((respond_to?(:new_record?) && validator.options[:on] == (new_record? ? :create : :update)) || validator.options[:on].nil?)
|
|
63
66
|
result &&= validator.kind != :block
|
|
64
67
|
|
|
65
68
|
if validator.options[:if] || validator.options[:unless]
|
|
@@ -68,10 +71,10 @@ module ClientSideValidations
|
|
|
68
71
|
else
|
|
69
72
|
result = can_force_validator?(attr, validator, force)
|
|
70
73
|
if validator.options[:if]
|
|
71
|
-
result &&=
|
|
74
|
+
result &&= run_conditionals(validator.options[:if], :if)
|
|
72
75
|
end
|
|
73
76
|
if validator.options[:unless]
|
|
74
|
-
result &&=
|
|
77
|
+
result &&= run_conditionals(validator.options[:unless], :unless)
|
|
75
78
|
end
|
|
76
79
|
end
|
|
77
80
|
end
|
|
@@ -79,15 +82,8 @@ module ClientSideValidations
|
|
|
79
82
|
result
|
|
80
83
|
end
|
|
81
84
|
|
|
82
|
-
def run_conditional(method_name_value_or_proc)
|
|
83
|
-
if method_name_value_or_proc.respond_to?(:call)
|
|
84
|
-
method_name_value_or_proc.call self
|
|
85
|
-
else
|
|
86
|
-
send method_name_value_or_proc
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
85
|
def validator_turned_off?(attr, validator, force)
|
|
86
|
+
return true if ::ClientSideValidations::Config.disabled_validators.include?(validator.kind)
|
|
91
87
|
case force
|
|
92
88
|
when FalseClass
|
|
93
89
|
true
|
|
@@ -101,7 +97,7 @@ module ClientSideValidations
|
|
|
101
97
|
false
|
|
102
98
|
end
|
|
103
99
|
else
|
|
104
|
-
|
|
100
|
+
false
|
|
105
101
|
end
|
|
106
102
|
end
|
|
107
103
|
|
|
@@ -127,17 +123,14 @@ module ClientSideValidations
|
|
|
127
123
|
module EnumerableValidator
|
|
128
124
|
def client_side_hash(model, attribute, force = nil)
|
|
129
125
|
options = self.options.dup
|
|
126
|
+
|
|
130
127
|
if options[:in].respond_to?(:call)
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
hash = build_client_side_hash(model, attribute, options)
|
|
134
|
-
else
|
|
135
|
-
return
|
|
136
|
-
end
|
|
137
|
-
else
|
|
138
|
-
hash = build_client_side_hash(model, attribute, options)
|
|
128
|
+
return unless force
|
|
129
|
+
options[:in] = options[:in].call(model)
|
|
139
130
|
end
|
|
140
131
|
|
|
132
|
+
hash = build_client_side_hash(model, attribute, options)
|
|
133
|
+
|
|
141
134
|
if hash[:in].is_a?(Range)
|
|
142
135
|
hash[:range] = hash[:in]
|
|
143
136
|
hash.delete(:in)
|
|
@@ -152,8 +145,7 @@ end
|
|
|
152
145
|
ActiveModel::Validator.send(:include, ClientSideValidations::ActiveModel::Validator)
|
|
153
146
|
ActiveModel::Validations.send(:include, ClientSideValidations::ActiveModel::Validations)
|
|
154
147
|
|
|
155
|
-
%w(
|
|
156
|
-
require "client_side_validations/active_model/#{validator}"
|
|
157
|
-
validator.capitalize!
|
|
148
|
+
%w(Absence Acceptance Exclusion Format Inclusion Length Numericality Presence).each do |validator|
|
|
149
|
+
require "client_side_validations/active_model/#{validator.downcase}"
|
|
158
150
|
ActiveModel::Validations.const_get("#{validator}Validator").send :include, ClientSideValidations::ActiveModel.const_get(validator)
|
|
159
151
|
end
|