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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 74a0ec2fee1f73f4bbb10e8384609c16914c16e9
4
- data.tar.gz: fdc6f78dd60b02930a4bfc876e090785c21f5206
3
+ metadata.gz: 62857994d1326cfb20a2c2d3c1c5fd746fa72065
4
+ data.tar.gz: 5d187e21b9b0b8935f3d5bfee8099095a128a389
5
5
  SHA512:
6
- metadata.gz: 2c777cc7a0190546e612e7602e5dc578d5e30172d3b0393912ad8d2e5c2d48b36d9e3a5fe9cc5979e5ad3e8dada301d0f0eab51bca923fc8d02f63e3fcef0017
7
- data.tar.gz: 795119c15633fb66e4b6091eb3e4a29698b49791855a64488de8c687f62fb2138924f4f849c2be99ae2cd78e8055f40bc2af3663aa935a9a431ee105ad1962c7
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
  [![Build Status](https://secure.travis-ci.org/DavyJonesLocker/client_side_validations.svg?branch=master)](https://travis-ci.org/DavyJonesLocker/client_side_validations)
5
5
  [![Dependency Status](https://gemnasium.com/DavyJonesLocker/client_side_validations.svg)](https://gemnasium.com/DavyJonesLocker/client_side_validations)
6
6
  [![Code Climate](https://codeclimate.com/github/DavyJonesLocker/client_side_validations/badges/gpa.svg)](https://codeclimate.com/github/DavyJonesLocker/client_side_validations)
7
- [![Coverage Status](https://coveralls.io/repos/DavyJonesLocker/client_side_validations/badge.svg?branch=master)](https://coveralls.io/r/DavyJonesLocker/client_side_validations?branch=master)
7
+ [![Coverage Status](https://coveralls.io/repos/github/DavyJonesLocker/client_side_validations/badge.svg?branch=master)](https://coveralls.io/github/DavyJonesLocker/client_side_validations?branch=master)
8
8
 
9
- `ClientSideValidations` made easy for your Rails 4 applications!
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://www.alistapart.com/articles/inline-validation-in-web-forms/)
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 want to copy the asset files from the gem into your project:
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/DockYard/client_side_validations-simple_form)
74
- * [Formtastic](https://github.com/DockYard/client_side_validations-formtastic)
75
- * [Mongoid](https://github.com/DockYard/client_side_validations-mongoid)
76
- * [MongoMapper](https://github.com/DockYard/client_side_validations-mongo_mapper)
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 Procs, or any object that responds to `#call`
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](http://twitter.com/bcardarella)
525
+ [Brian Cardarella](https://twitter.com/bcardarella)
508
526
 
509
- [Geremia Taglialatela](http://twitter.com/gtagliala)
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](http://dockyard.com), LLC &copy; 2012-2015
543
+ [DockYard](https://dockyard.com/), LLC &copy; 2012-2017
537
544
 
538
- [@dockyard](http://twitter.com/dockyard)
545
+ [@dockyard](https://twitter.com/dockyard)
539
546
 
540
- [Licensed under the MIT license](http://www.opensource.org/licenses/mit-license.php)
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.included(base)
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}_with_client_side_validations(method, options = {})
8
+ def #{selector}(method, options = {})
9
9
  build_validation_options(method, options)
10
10
  options.delete(:validate)
11
- #{selector}_without_client_side_validations(method, options)
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 initialize_with_client_side_validations(object_name, object, *args)
49
- initialize_without_client_side_validations(object_name, object, *args)
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 fields_for_with_client_side_validations(record_or_name_or_array, *args, &block)
54
- options = args.extract_options!
55
- options[:validate] ||= @options[:validate] if @options[:validate] && !options.key?(:validate)
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 check_box_with_client_side_validations(method, options = {}, checked_value = '1', unchecked_value = '0')
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
- check_box_without_client_side_validations(method, options, checked_value, unchecked_value)
52
+ super(method, options, checked_value, unchecked_value)
63
53
  end
64
54
 
65
- def radio_button_with_client_side_validations(method, tag_value, options = {})
55
+ def radio_button(method, tag_value, options = {})
66
56
  build_validation_options(method, options)
67
57
  options.delete(:validate)
68
- radio_button_without_client_side_validations(method, tag_value, options)
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 collection_select_with_client_side_validations(method, collection, value_method, text_method, options = {}, html_options = {})
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
- collection_select_without_client_side_validations(method, collection, value_method, text_method, options, html_options)
64
+ super(method, choices, options, html_options, &block)
81
65
  end
82
66
 
83
- def collection_check_boxes_with_client_side_validations(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
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
- collection_check_boxes_without_client_side_validations(method, collection, value_method, text_method, options, html_options, &block)
70
+ super(method, collection, value_method, text_method, options, html_options)
87
71
  end
88
72
 
89
- def collection_radio_buttons_with_client_side_validations(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
90
- build_validation_options(method, html_options.merge(name: options[:name]))
91
- html_options.delete(:validate)
92
- collection_radio_buttons_without_client_side_validations(method, collection, value_method, text_method, options, html_options, &block)
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 grouped_collection_select_with_client_side_validations(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
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
- grouped_collection_select_without_client_side_validations(method, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options)
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 time_zone_select_with_client_side_validations(method, priority_zones = nil, options = {}, html_options = {})
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
- time_zone_select_without_client_side_validations(method, priority_zones, options, html_options)
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 = @default_options[:index].present? ? "[#{@default_options[: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 = "#{name}#{options[:multiple] ? '[]' : nil}"
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
- fail ArgumentError, 'Missing block' unless block_given?
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
- fail ClientSideValidations::ActionView::Helpers::FormHelper::Error, 'Using form_for(:name, @resource) is not supported with ClientSideValidations. Please use form_for(@resource, as: :name) instead.'
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(name) { script.html_safe }
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
- if object_opts[0].respond_to?(:client_side_validation_hash)
95
- validation_hash = object_opts[0].client_side_validation_hash(option_hash)
96
- else
97
- validation_hash = {}
98
- end
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
- if options[:id]
111
- var_name = options[:id]
112
- else
113
- var_name =
114
- if object.respond_to?(:persisted?) && object.persisted?
115
- options[:as] ? "edit_#{options[:as]}" : [options[:namespace], dom_id(object, :edit)].compact.join('_'.freeze)
116
- else
117
- options[:as] ? "new_#{options[:as]}" : [options[:namespace], dom_id(object)].compact.join('_'.freeze)
118
- end
119
- end
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
- content_tag(:script) do
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(:include, ClientSideValidations::ActionView::Helpers::FormBuilder)
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
- if force
8
- options[:with] = options[:with].call(model)
9
- build_client_side_hash(model, attribute, options)
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
- if force
15
- options[:without] = options[:without].call(model)
16
- build_client_side_hash(model, attribute, options)
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
- OPTION_MAP = {}
4
+ @@option_map = {}
5
5
 
6
6
  def self.included(base)
7
- OPTION_MAP.merge!(base::CHECKS.keys.inject({}) { |a, e| a.merge!(e => e) })
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
- OPTION_MAP.each do |option, message_type|
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
- if force
27
- count = count.call(model)
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 = ((self.respond_to?(:new_record?) && validator.options[:on] == (self.new_record? ? :create : :update)) || validator.options[:on].nil?)
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 &&= run_conditional(validator.options[:if])
74
+ result &&= run_conditionals(validator.options[:if], :if)
72
75
  end
73
76
  if validator.options[:unless]
74
- result &&= !run_conditional(validator.options[:unless])
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
- ::ClientSideValidations::Config.disabled_validators.include?(validator.kind)
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
- if force
132
- options[:in] = options[:in].call(model)
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(absence acceptance exclusion inclusion length format numericality presence).each do |validator|
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