client_side_validations 3.1.0 → 3.1.4
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.
- data/client_side_validations.gemspec +4 -4
- data/lib/client_side_validations/action_view/form_builder.rb +26 -21
- data/lib/client_side_validations/version.rb +1 -1
- data/lib/generators/client_side_validations/copy_asset_generator.rb +15 -2
- data/lib/generators/client_side_validations/install_generator.rb +16 -5
- data/test/action_view/cases/test_helpers.rb +65 -30
- data/test/base_helper.rb +0 -1
- data/test/formtastic/cases/test_form_helper.rb +2 -2
- data/test/generators/cases/test_generators.rb +47 -8
- data/test/javascript/public/test/validators/numericality.js +18 -2
- data/test/javascript/public/test/validators/uniqueness.js +11 -0
- data/vendor/assets/javascripts/rails.validations.js +47 -41
- metadata +8 -8
|
@@ -17,14 +17,14 @@ Gem::Specification.new do |s|
|
|
|
17
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
18
18
|
s.require_paths = ["lib"]
|
|
19
19
|
|
|
20
|
-
s.add_development_dependency 'rails', '3.1.0
|
|
20
|
+
s.add_development_dependency 'rails', '~> 3.1.0'
|
|
21
21
|
s.add_development_dependency 'sqlite3'
|
|
22
22
|
s.add_development_dependency 'bson_ext'
|
|
23
23
|
s.add_development_dependency 'mongoid', '~> 2.0.0'
|
|
24
|
-
s.add_development_dependency 'mongo_mapper','~>0.9.0'
|
|
24
|
+
s.add_development_dependency 'mongo_mapper','~> 0.9.0'
|
|
25
25
|
s.add_development_dependency 'mocha'
|
|
26
|
-
s.add_development_dependency 'simple_form'
|
|
27
|
-
s.add_development_dependency 'formtastic', '~> 2.0.0
|
|
26
|
+
s.add_development_dependency 'simple_form', '~> 1.5.0'
|
|
27
|
+
s.add_development_dependency 'formtastic', '~> 2.0.0'
|
|
28
28
|
|
|
29
29
|
# For QUnit testing
|
|
30
30
|
s.add_development_dependency 'sinatra', '~> 1.0'
|
|
@@ -78,33 +78,33 @@ module ClientSideValidations::ActionView::Helpers
|
|
|
78
78
|
private
|
|
79
79
|
|
|
80
80
|
def apply_client_side_validators(method, options = {})
|
|
81
|
-
if @options[:validate] && options[:validate] != false && validators = filter_validators(
|
|
81
|
+
if @options[:validate] && options[:validate] != false && validators = filter_validators(method, options[:validate])
|
|
82
82
|
options.merge!("data-validate" => true)
|
|
83
83
|
@options[:validators].merge!("#{@object_name}[#{method}]#{options[:multiple] ? "[]" : nil}" => validators)
|
|
84
84
|
end
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
-
def filter_validators(
|
|
88
|
-
if validators
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
def filter_validators(method, filters)
|
|
88
|
+
if validators = @object.client_side_validation_hash[method]
|
|
89
|
+
unfiltered_validators = validators.inject({}) do |unfiltered_validators, validator|
|
|
90
|
+
unfiltered_validators[validator.first] = validator.last
|
|
91
91
|
if has_filter_for_validator?(validator, filters)
|
|
92
92
|
if filter_validator?(validator, filters)
|
|
93
|
-
|
|
94
|
-
elsif force_validator_despite_conditional?(validator, filters) && !can_run_validator?(validator)
|
|
95
|
-
|
|
93
|
+
unfiltered_validators.delete(validator.first)
|
|
94
|
+
elsif force_validator_despite_conditional?(validator, filters) && !can_run_validator?(validator, method)
|
|
95
|
+
unfiltered_validators.delete(validator.first)
|
|
96
96
|
end
|
|
97
97
|
else
|
|
98
|
-
if validator.last
|
|
99
|
-
|
|
98
|
+
if (conditional = (validator.last[:if] || validator.last[:unless])) && conditional.is_a?(Symbol) && !conditional_method_is_change_method?(conditional, method)
|
|
99
|
+
unfiltered_validators.delete(validator.first)
|
|
100
100
|
end
|
|
101
101
|
end
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
unfiltered_validators[validator.first].delete(:if) if unfiltered_validators[validator.first]
|
|
103
|
+
unfiltered_validators[validator.first].delete(:unless) if unfiltered_validators[validator.first]
|
|
104
|
+
unfiltered_validators
|
|
105
105
|
end
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
unfiltered_validators.empty? ? nil : unfiltered_validators
|
|
108
108
|
end
|
|
109
109
|
end
|
|
110
110
|
|
|
@@ -120,33 +120,38 @@ module ClientSideValidations::ActionView::Helpers
|
|
|
120
120
|
filters == true || filters[validator.first] == true
|
|
121
121
|
end
|
|
122
122
|
|
|
123
|
-
def can_run_validator?(validator)
|
|
123
|
+
def can_run_validator?(validator, method)
|
|
124
124
|
result = true
|
|
125
|
-
if_result =
|
|
126
|
-
unless_result =
|
|
125
|
+
if_result = run_if_validator(validator.last[:if], method)
|
|
126
|
+
unless_result = run_unless_validator(validator.last[:unless], method)
|
|
127
127
|
result = result && if_result unless if_result.nil?
|
|
128
128
|
result = result && unless_result unless unless_result.nil?
|
|
129
129
|
result
|
|
130
130
|
end
|
|
131
131
|
|
|
132
|
-
def
|
|
132
|
+
def run_if_validator(conditional, method)
|
|
133
133
|
if conditional
|
|
134
134
|
if conditional.is_a?(Symbol)
|
|
135
|
-
!!@object.send(conditional)
|
|
135
|
+
conditional_method_is_change_method?(conditional, method) ? true : !!@object.send(conditional)
|
|
136
136
|
else
|
|
137
137
|
!!conditional.call(@object)
|
|
138
138
|
end
|
|
139
139
|
end
|
|
140
140
|
end
|
|
141
141
|
|
|
142
|
-
def
|
|
142
|
+
def run_unless_validator(conditional, method)
|
|
143
143
|
if conditional
|
|
144
144
|
if conditional.is_a?(Symbol)
|
|
145
|
-
!@object.send(conditional)
|
|
145
|
+
conditional_method_is_change_method?(conditional, method) ? true : !@object.send(conditional)
|
|
146
146
|
else
|
|
147
147
|
!conditional.call(@object)
|
|
148
148
|
end
|
|
149
149
|
end
|
|
150
150
|
end
|
|
151
|
+
|
|
152
|
+
def conditional_method_is_change_method?(conditional, method)
|
|
153
|
+
conditional.to_sym == "#{method}_changed?".to_sym
|
|
154
|
+
end
|
|
151
155
|
end
|
|
152
156
|
end
|
|
157
|
+
|
|
@@ -2,14 +2,27 @@ module ClientSideValidations
|
|
|
2
2
|
module Generators
|
|
3
3
|
class CopyAssetGenerator < Rails::Generators::Base
|
|
4
4
|
source_root File.expand_path('../../../../vendor/assets/javascripts', __FILE__)
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
def self.asset_pipeline_enabled?
|
|
9
|
+
(Rails.configuration.respond_to?(:assets) ? (Rails.configuration.assets || {}) : {})[:enabled]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def asset_pipeline_enabled?
|
|
13
|
+
self.class.asset_pipeline_enabled?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
public
|
|
17
|
+
|
|
18
|
+
if asset_pipeline_enabled?
|
|
6
19
|
desc 'Creates a ClientSideValidations initializer and copies rails.validations.js to app/assets/javascripts.'
|
|
7
20
|
else
|
|
8
21
|
desc 'Creates a ClientSideValidations initializer and copies rails.validations.js to public/javascripts.'
|
|
9
22
|
end
|
|
10
23
|
|
|
11
24
|
def copy_javascript_asset
|
|
12
|
-
if
|
|
25
|
+
if asset_pipeline_enabled?
|
|
13
26
|
destination = 'app/assets/javascripts'
|
|
14
27
|
else
|
|
15
28
|
destination = 'public/javascripts'
|
|
@@ -3,7 +3,19 @@ module ClientSideValidations
|
|
|
3
3
|
class InstallGenerator < Rails::Generators::Base
|
|
4
4
|
source_root File.expand_path('../../templates/client_side_validations', __FILE__)
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
def self.asset_pipeline_enabled?
|
|
9
|
+
(Rails.configuration.respond_to?(:assets) ? (Rails.configuration.assets || {}) : {})[:enabled]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def asset_pipeline_enabled?
|
|
13
|
+
self.class.asset_pipeline_enabled?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
public
|
|
17
|
+
|
|
18
|
+
if asset_pipeline_enabled?
|
|
7
19
|
desc 'Creates a ClientSideValidations initializer.'
|
|
8
20
|
else
|
|
9
21
|
desc 'Creates a ClientSideValidations initializer and copies rails.validations.js to public/javascripts.'
|
|
@@ -14,10 +26,8 @@ module ClientSideValidations
|
|
|
14
26
|
end
|
|
15
27
|
|
|
16
28
|
def copy_javascript_asset
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
copy_file '../../../../vendor/assets/javascripts/rails.validations.js', 'public/javascripts/rails.validations.js'
|
|
20
|
-
end
|
|
29
|
+
unless asset_pipeline_enabled?
|
|
30
|
+
copy_file '../../../../vendor/assets/javascripts/rails.validations.js', 'public/javascripts/rails.validations.js'
|
|
21
31
|
end
|
|
22
32
|
end
|
|
23
33
|
|
|
@@ -28,6 +38,7 @@ module ClientSideValidations
|
|
|
28
38
|
readme 'README.rails.3.0' if behavior == :invoke
|
|
29
39
|
end
|
|
30
40
|
end
|
|
41
|
+
|
|
31
42
|
end
|
|
32
43
|
end
|
|
33
44
|
end
|
|
@@ -346,7 +346,7 @@ class ClientSideValidations::ActionViewHelpersTest < ActionView::TestCase
|
|
|
346
346
|
assert_equal expected, output_buffer
|
|
347
347
|
end
|
|
348
348
|
|
|
349
|
-
def
|
|
349
|
+
def test_conditional_validators_should_be_filtered
|
|
350
350
|
hash = {
|
|
351
351
|
:cost => {
|
|
352
352
|
:presence => {
|
|
@@ -379,7 +379,7 @@ class ClientSideValidations::ActionViewHelpersTest < ActionView::TestCase
|
|
|
379
379
|
assert_equal expected, output_buffer
|
|
380
380
|
end
|
|
381
381
|
|
|
382
|
-
def
|
|
382
|
+
def test_conditional_validator_filters_being_forced
|
|
383
383
|
hash = {
|
|
384
384
|
:cost => {
|
|
385
385
|
:presence => {
|
|
@@ -400,8 +400,44 @@ class ClientSideValidations::ActionViewHelpersTest < ActionView::TestCase
|
|
|
400
400
|
@post.stubs(:can_validate?).returns(true)
|
|
401
401
|
@post.stubs(:client_side_validation_hash).returns(hash)
|
|
402
402
|
form_for(@post, :validate => true) do |f|
|
|
403
|
-
concat f.text_field(:cost)
|
|
404
|
-
concat f.text_field(:title)
|
|
403
|
+
concat f.text_field(:cost, :validate => true)
|
|
404
|
+
concat f.text_field(:title, :validate => true)
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
validators = {
|
|
408
|
+
'post[cost]' => {:presence => {:message => "can't be blank"}},
|
|
409
|
+
'post[title]' => {:presence => {:message => "can't be blank"}}
|
|
410
|
+
}
|
|
411
|
+
expected = whole_form("/posts/123", "edit_post_123", "edit_post", :method => "put", :validators => validators) do
|
|
412
|
+
%{<input data-validate="true" id="post_cost" name="post[cost]" size="30" type="text" />} +
|
|
413
|
+
%{<input data-validate="true" id="post_title" name="post[title]" size="30" type="text" />}
|
|
414
|
+
end
|
|
415
|
+
assert_equal expected, output_buffer
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
def test_conditional_validator_filters_being_forced_and_not_meeting_condition
|
|
419
|
+
hash = {
|
|
420
|
+
:cost => {
|
|
421
|
+
:presence => {
|
|
422
|
+
:message => "can't be blank",
|
|
423
|
+
:unless => :cannot_validate?
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
:title => {
|
|
427
|
+
:presence => {
|
|
428
|
+
:message => "can't be blank",
|
|
429
|
+
:if => :can_validate?
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
@post.title = nil
|
|
435
|
+
@post.stubs(:cannot_validate?).returns(true)
|
|
436
|
+
@post.stubs(:can_validate?).returns(false)
|
|
437
|
+
@post.stubs(:client_side_validation_hash).returns(hash)
|
|
438
|
+
form_for(@post, :validate => true) do |f|
|
|
439
|
+
concat f.text_field(:cost, :validate => true)
|
|
440
|
+
concat f.text_field(:title, :validate => true)
|
|
405
441
|
end
|
|
406
442
|
|
|
407
443
|
validators = {}
|
|
@@ -412,7 +448,7 @@ class ClientSideValidations::ActionViewHelpersTest < ActionView::TestCase
|
|
|
412
448
|
assert_equal expected, output_buffer
|
|
413
449
|
end
|
|
414
450
|
|
|
415
|
-
def
|
|
451
|
+
def test_conditional_validator_filters_being_forced_individually
|
|
416
452
|
hash = {
|
|
417
453
|
:cost => {
|
|
418
454
|
:presence => {
|
|
@@ -433,8 +469,8 @@ class ClientSideValidations::ActionViewHelpersTest < ActionView::TestCase
|
|
|
433
469
|
@post.stubs(:can_validate?).returns(true)
|
|
434
470
|
@post.stubs(:client_side_validation_hash).returns(hash)
|
|
435
471
|
form_for(@post, :validate => true) do |f|
|
|
436
|
-
concat f.text_field(:cost, :validate => true)
|
|
437
|
-
concat f.text_field(:title, :validate => true)
|
|
472
|
+
concat f.text_field(:cost, :validate => { :presence => true })
|
|
473
|
+
concat f.text_field(:title, :validate => { :presence => true })
|
|
438
474
|
end
|
|
439
475
|
|
|
440
476
|
validators = {
|
|
@@ -448,7 +484,7 @@ class ClientSideValidations::ActionViewHelpersTest < ActionView::TestCase
|
|
|
448
484
|
assert_equal expected, output_buffer
|
|
449
485
|
end
|
|
450
486
|
|
|
451
|
-
def
|
|
487
|
+
def test_conditional_validator_filters_being_forced_and_not_meeting_condition_individually
|
|
452
488
|
hash = {
|
|
453
489
|
:cost => {
|
|
454
490
|
:presence => {
|
|
@@ -469,8 +505,8 @@ class ClientSideValidations::ActionViewHelpersTest < ActionView::TestCase
|
|
|
469
505
|
@post.stubs(:can_validate?).returns(false)
|
|
470
506
|
@post.stubs(:client_side_validation_hash).returns(hash)
|
|
471
507
|
form_for(@post, :validate => true) do |f|
|
|
472
|
-
concat f.text_field(:cost, :validate => true)
|
|
473
|
-
concat f.text_field(:title, :validate => true)
|
|
508
|
+
concat f.text_field(:cost, :validate => { :presence => true })
|
|
509
|
+
concat f.text_field(:title, :validate => { :presence => true })
|
|
474
510
|
end
|
|
475
511
|
|
|
476
512
|
validators = {}
|
|
@@ -481,18 +517,18 @@ class ClientSideValidations::ActionViewHelpersTest < ActionView::TestCase
|
|
|
481
517
|
assert_equal expected, output_buffer
|
|
482
518
|
end
|
|
483
519
|
|
|
484
|
-
def
|
|
520
|
+
def test_conditional_validator_filters_being_forced_with_procs
|
|
485
521
|
hash = {
|
|
486
522
|
:cost => {
|
|
487
523
|
:presence => {
|
|
488
524
|
:message => "can't be blank",
|
|
489
|
-
:unless =>
|
|
525
|
+
:unless => Proc.new { |post| post.cannot_validate? }
|
|
490
526
|
}
|
|
491
527
|
},
|
|
492
528
|
:title => {
|
|
493
529
|
:presence => {
|
|
494
530
|
:message => "can't be blank",
|
|
495
|
-
:if =>
|
|
531
|
+
:if => Proc.new { |post| post.can_validate? }
|
|
496
532
|
}
|
|
497
533
|
}
|
|
498
534
|
}
|
|
@@ -502,8 +538,8 @@ class ClientSideValidations::ActionViewHelpersTest < ActionView::TestCase
|
|
|
502
538
|
@post.stubs(:can_validate?).returns(true)
|
|
503
539
|
@post.stubs(:client_side_validation_hash).returns(hash)
|
|
504
540
|
form_for(@post, :validate => true) do |f|
|
|
505
|
-
concat f.text_field(:cost, :validate =>
|
|
506
|
-
concat f.text_field(:title, :validate =>
|
|
541
|
+
concat f.text_field(:cost, :validate => true)
|
|
542
|
+
concat f.text_field(:title, :validate => true)
|
|
507
543
|
end
|
|
508
544
|
|
|
509
545
|
validators = {
|
|
@@ -517,58 +553,57 @@ class ClientSideValidations::ActionViewHelpersTest < ActionView::TestCase
|
|
|
517
553
|
assert_equal expected, output_buffer
|
|
518
554
|
end
|
|
519
555
|
|
|
520
|
-
def
|
|
556
|
+
def test_conditional_validator_ignored_when_using_changed_helpers
|
|
521
557
|
hash = {
|
|
522
558
|
:cost => {
|
|
523
559
|
:presence => {
|
|
524
560
|
:message => "can't be blank",
|
|
525
|
-
:unless => :
|
|
561
|
+
:unless => :cost_changed?
|
|
526
562
|
}
|
|
527
563
|
},
|
|
528
564
|
:title => {
|
|
529
565
|
:presence => {
|
|
530
566
|
:message => "can't be blank",
|
|
531
|
-
:if => :
|
|
567
|
+
:if => :title_changed?
|
|
532
568
|
}
|
|
533
569
|
}
|
|
534
570
|
}
|
|
535
571
|
|
|
536
572
|
@post.title = nil
|
|
537
|
-
@post.stubs(:cannot_validate?).returns(true)
|
|
538
|
-
@post.stubs(:can_validate?).returns(false)
|
|
539
573
|
@post.stubs(:client_side_validation_hash).returns(hash)
|
|
540
574
|
form_for(@post, :validate => true) do |f|
|
|
541
|
-
concat f.text_field(:cost
|
|
542
|
-
concat f.text_field(:title
|
|
575
|
+
concat f.text_field(:cost)
|
|
576
|
+
concat f.text_field(:title)
|
|
543
577
|
end
|
|
544
578
|
|
|
545
|
-
validators = {
|
|
579
|
+
validators = {
|
|
580
|
+
'post[cost]' => {:presence => {:message => "can't be blank"}},
|
|
581
|
+
'post[title]' => {:presence => {:message => "can't be blank"}}
|
|
582
|
+
}
|
|
546
583
|
expected = whole_form("/posts/123", "edit_post_123", "edit_post", :method => "put", :validators => validators) do
|
|
547
|
-
%{<input id="post_cost" name="post[cost]" size="30" type="text" />} +
|
|
548
|
-
%{<input id="post_title" name="post[title]" size="30" type="text" />}
|
|
584
|
+
%{<input data-validate="true" id="post_cost" name="post[cost]" size="30" type="text" />} +
|
|
585
|
+
%{<input data-validate="true" id="post_title" name="post[title]" size="30" type="text" />}
|
|
549
586
|
end
|
|
550
587
|
assert_equal expected, output_buffer
|
|
551
588
|
end
|
|
552
589
|
|
|
553
|
-
def
|
|
590
|
+
def test_conditional_validator_ignored_when_using_changed_helpers_and_forcing_validators
|
|
554
591
|
hash = {
|
|
555
592
|
:cost => {
|
|
556
593
|
:presence => {
|
|
557
594
|
:message => "can't be blank",
|
|
558
|
-
:unless =>
|
|
595
|
+
:unless => :cost_changed?
|
|
559
596
|
}
|
|
560
597
|
},
|
|
561
598
|
:title => {
|
|
562
599
|
:presence => {
|
|
563
600
|
:message => "can't be blank",
|
|
564
|
-
:if =>
|
|
601
|
+
:if => :title_changed?
|
|
565
602
|
}
|
|
566
603
|
}
|
|
567
604
|
}
|
|
568
605
|
|
|
569
606
|
@post.title = nil
|
|
570
|
-
@post.stubs(:cannot_validate?).returns(false)
|
|
571
|
-
@post.stubs(:can_validate?).returns(true)
|
|
572
607
|
@post.stubs(:client_side_validation_hash).returns(hash)
|
|
573
608
|
form_for(@post, :validate => true) do |f|
|
|
574
609
|
concat f.text_field(:cost, :validate => true)
|
data/test/base_helper.rb
CHANGED
|
@@ -14,8 +14,8 @@ class ClientSideValidations::Formtastic::FormHelperTest < ActionView::TestCase
|
|
|
14
14
|
concat f.input(:cost)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
expected = %{<form accept-charset="UTF-8" action="/posts/123" class="formtastic post" data-validate="true" id="edit_post_123" method="post" novalidate="novalidate"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="_method" type="hidden" value="put" /></div><li class="string input required stringish" id="post_cost_input"><label class=\" label\" for="post_cost">Cost<abbr title="required">*</abbr></label><input data-validate="true" id="post_cost" name="post[cost]"
|
|
17
|
+
expected = %{<form accept-charset="UTF-8" action="/posts/123" class="formtastic post" data-validate="true" id="edit_post_123" method="post" novalidate="novalidate"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="_method" type="hidden" value="put" /></div><li class="string input required stringish" id="post_cost_input"><label class=\" label\" for="post_cost">Cost<abbr title="required">*</abbr></label><input data-validate="true" id="post_cost" name="post[cost]" type="text" />\n\n</li></form><script>window['edit_post_123'] = {"type":"Formtastic::FormBuilder","inline_error_class":"inline-errors","validators":{"post[cost]":{"presence":{"message":"can't be blank"}}}};</script>}
|
|
18
18
|
assert_equal expected, output_buffer, "\n\n *** If you're running Ruby 1.8 and this test fails is is most likely due to 1.8's lack of insertion order persistence with Hashes ***\n"
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
end
|
|
21
|
+
end
|
|
@@ -7,10 +7,32 @@ class InstallGeneratorTest < Rails::Generators::TestCase
|
|
|
7
7
|
destination File.expand_path('../../tmp', __FILE__)
|
|
8
8
|
setup :prepare_destination
|
|
9
9
|
|
|
10
|
-
test 'Assert all files are properly created' do
|
|
10
|
+
test 'Assert all files are properly created when no asset pipeline present' do
|
|
11
|
+
stub_configuration
|
|
11
12
|
run_generator
|
|
12
13
|
assert_file 'config/initializers/client_side_validations.rb'
|
|
13
|
-
assert_file 'public/javascripts/rails.validations.js'
|
|
14
|
+
assert_file 'public/javascripts/rails.validations.js'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
test 'Assert all files are properly created when asset pipeline present and disabled' do
|
|
18
|
+
stub_configuration
|
|
19
|
+
Rails.configuration.stubs(:assets).returns({})
|
|
20
|
+
Rails.configuration.assets[:enabled] = false
|
|
21
|
+
run_generator
|
|
22
|
+
assert_file 'config/initializers/client_side_validations.rb'
|
|
23
|
+
assert_file 'public/javascripts/rails.validations.js'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
test 'Assert all files are properly created when asset pipeline present and enabled' do
|
|
27
|
+
stub_configuration
|
|
28
|
+
Rails.configuration.stubs(:assets).returns({})
|
|
29
|
+
Rails.configuration.assets[:enabled] = true
|
|
30
|
+
run_generator
|
|
31
|
+
assert_file 'config/initializers/client_side_validations.rb'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def stub_configuration
|
|
35
|
+
Rails.stubs(:configuration).returns(mock('Configuration'))
|
|
14
36
|
end
|
|
15
37
|
end
|
|
16
38
|
|
|
@@ -19,13 +41,30 @@ class CopyAssetGeneratorTest < Rails::Generators::TestCase
|
|
|
19
41
|
destination File.expand_path('../../tmp', __FILE__)
|
|
20
42
|
setup :prepare_destination
|
|
21
43
|
|
|
22
|
-
test 'Assert file is properly created' do
|
|
44
|
+
test 'Assert file is properly created when no asset pipeline present' do
|
|
45
|
+
stub_configuration
|
|
23
46
|
run_generator
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
47
|
+
assert_file 'public/javascripts/rails.validations.js'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
test 'Assert file is properly created when asset pipeline present and disabled' do
|
|
51
|
+
stub_configuration
|
|
52
|
+
Rails.configuration.stubs(:assets).returns({})
|
|
53
|
+
Rails.configuration.assets[:enabled] = false
|
|
54
|
+
run_generator
|
|
55
|
+
assert_file 'public/javascripts/rails.validations.js'
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
test 'Assert file is properly created when asset pipeline present and enabled' do
|
|
59
|
+
stub_configuration
|
|
60
|
+
Rails.configuration.stubs(:assets).returns({})
|
|
61
|
+
Rails.configuration.assets[:enabled] = true
|
|
62
|
+
run_generator
|
|
63
|
+
assert_file 'app/assets/javascripts/rails.validations.js'
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def stub_configuration
|
|
67
|
+
Rails.stubs(:configuration).returns(mock('Configuration'))
|
|
29
68
|
end
|
|
30
69
|
end
|
|
31
70
|
|
|
@@ -2,14 +2,14 @@ module('Numericality options');
|
|
|
2
2
|
|
|
3
3
|
test('when value is a number', function() {
|
|
4
4
|
var element = $('<input type="text" />');
|
|
5
|
-
var options = {
|
|
5
|
+
var options = { messagess: { numericality: "failed validation" } };
|
|
6
6
|
element.val('123');
|
|
7
7
|
equal(clientSideValidations.validators.local.numericality(element, options), undefined);
|
|
8
8
|
});
|
|
9
9
|
|
|
10
10
|
test('when value is a decimal number', function() {
|
|
11
11
|
var element = $('<input type="text" />');
|
|
12
|
-
var options = {
|
|
12
|
+
var options = { messages: { numericality: "failed validation" } };
|
|
13
13
|
element.val('123.456');
|
|
14
14
|
equal(clientSideValidations.validators.local.numericality(element, options), undefined);
|
|
15
15
|
});
|
|
@@ -28,6 +28,15 @@ test('when only allowing integers and value is integer', function() {
|
|
|
28
28
|
equal(clientSideValidations.validators.local.numericality(element, options), undefined);
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
+
test('when only allowing integers and value has a negative or positive sign', function() {
|
|
32
|
+
var element = $('<input type="text" />');
|
|
33
|
+
var options = { messages: { only_integer: "failed validation"}, only_integer: true };
|
|
34
|
+
element.val('-23');
|
|
35
|
+
equal(clientSideValidations.validators.local.numericality(element, options), undefined);
|
|
36
|
+
element.val('+23');
|
|
37
|
+
equal(clientSideValidations.validators.local.numericality(element, options), undefined);
|
|
38
|
+
});
|
|
39
|
+
|
|
31
40
|
test('when only allowing integers and value is not integer', function() {
|
|
32
41
|
var element = $('<input type="text" />');
|
|
33
42
|
var options = { messages: { only_integer: "failed validation" }, only_integer: true };
|
|
@@ -140,3 +149,10 @@ test('when only allowing even values and the value is odd', function() {
|
|
|
140
149
|
equal(clientSideValidations.validators.local.numericality(element, options), "failed validation");
|
|
141
150
|
});
|
|
142
151
|
|
|
152
|
+
test('blank values should be evaluated as zero', function() {
|
|
153
|
+
var element = $('<input type="text" />');
|
|
154
|
+
var options = { messages: { numericality: "failed validation" } };
|
|
155
|
+
element.val('');
|
|
156
|
+
equal(clientSideValidations.validators.local.numericality(element, options), undefined);
|
|
157
|
+
});
|
|
158
|
+
|
|
@@ -94,3 +94,14 @@ test('when matching uniqueness on a resource with a defined class name', functio
|
|
|
94
94
|
equal(clientSideValidations.validators.remote.uniqueness(element, options), 'failed validation');
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
+
test('when allowing blank', function() {
|
|
98
|
+
var element = $('<input type="text" name="user2[email]" />');
|
|
99
|
+
var options = { 'message': "failed validation", 'with': /\d+/, 'allow_blank': true };
|
|
100
|
+
equal(clientSideValidations.validators.remote.uniqueness(element, options), undefined);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('when not allowing blank', function() {
|
|
104
|
+
var element = $('<input type="text" name="user2[email]" />');
|
|
105
|
+
var options = { 'message': "failed validation", 'with': /\d+/ };
|
|
106
|
+
equal(clientSideValidations.validators.remote.uniqueness(element, options), "failed validation");
|
|
107
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Rails 3 Client Side Validations - v3.1.
|
|
2
|
+
* Rails 3 Client Side Validations - v3.1.4
|
|
3
3
|
* https://github.com/bcardarlela/client_side_validations
|
|
4
4
|
*
|
|
5
5
|
* Copyright (c) 2011 Brian Cardarella
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
|
|
16
16
|
// Set up the events for the form
|
|
17
17
|
form
|
|
18
|
-
.submit(function()
|
|
19
|
-
.bind('ajax:beforeSend', function()
|
|
18
|
+
.submit( function() { return form.isValid(settings.validators); })
|
|
19
|
+
.bind('ajax:beforeSend', function(eventData) { if(eventData.target == this) return form.isValid(settings.validators); })
|
|
20
20
|
// Callbacks
|
|
21
21
|
.bind('form:validate:after', function(eventData) { clientSideValidations.callbacks.form.after( form, eventData); })
|
|
22
22
|
.bind('form:validate:before', function(eventData) { clientSideValidations.callbacks.form.before(form, eventData); })
|
|
@@ -161,11 +161,11 @@ var clientSideValidations = {
|
|
|
161
161
|
}
|
|
162
162
|
},
|
|
163
163
|
numericality: function(element, options) {
|
|
164
|
-
if (!/^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d*)?$/.test(element.val())) {
|
|
164
|
+
if (!/^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d*)?$/.test(element.val()) && element.val() != '') {
|
|
165
165
|
return options.messages.numericality;
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
if (options.only_integer &&
|
|
168
|
+
if (options.only_integer && !/^[+-]?\d+$/.test(element.val())) {
|
|
169
169
|
return options.messages.only_integer;
|
|
170
170
|
}
|
|
171
171
|
|
|
@@ -263,48 +263,54 @@ var clientSideValidations = {
|
|
|
263
263
|
},
|
|
264
264
|
remote: {
|
|
265
265
|
uniqueness: function(element, options) {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
if (
|
|
269
|
-
|
|
270
|
-
}
|
|
266
|
+
if ((message = clientSideValidations.validators.local.presence(element, options)) && options.allow_blank === true) {
|
|
267
|
+
return;
|
|
268
|
+
} else if (message) {
|
|
269
|
+
return message;
|
|
270
|
+
} else {
|
|
271
|
+
var data = {};
|
|
272
|
+
data['case_sensitive'] = !!options.case_sensitive;
|
|
273
|
+
if (options.id) {
|
|
274
|
+
data['id'] = options.id;
|
|
275
|
+
}
|
|
271
276
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
277
|
+
if (options.scope) {
|
|
278
|
+
data.scope = {}
|
|
279
|
+
for (key in options.scope) {
|
|
280
|
+
var scoped_element = jQuery('[name="' + element.attr('name').replace(/\[\w+]$/, '[' + key + ']' + '"]'));
|
|
281
|
+
if (scoped_element[0] && scoped_element.val() != options.scope[key]) {
|
|
282
|
+
data.scope[key] = scoped_element.val();
|
|
283
|
+
scoped_element.unbind('change.' + element.id).bind('change.' + element.id, function() { element.trigger('change'); element.trigger('focusout'); });
|
|
284
|
+
} else {
|
|
285
|
+
data.scope[key] = options.scope[key];
|
|
286
|
+
}
|
|
281
287
|
}
|
|
282
288
|
}
|
|
283
|
-
}
|
|
284
289
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
290
|
+
// Kind of a hack but this will isolate the resource name and attribute.
|
|
291
|
+
// e.g. user[records_attributes][0][title] => records[title]
|
|
292
|
+
// e.g. user[record_attributes][title] => record[title]
|
|
293
|
+
// Server side handles classifying the resource properly
|
|
294
|
+
if (/_attributes]/.test(element.attr('name'))) {
|
|
295
|
+
var name = element.attr('name').match(/\[\w+_attributes]/g).pop().match(/\[(\w+)_attributes]/).pop();
|
|
296
|
+
name += /(\[\w+])$/.exec(element.attr('name'))[1];
|
|
297
|
+
} else {
|
|
298
|
+
var name = element.attr('name');
|
|
299
|
+
}
|
|
295
300
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
+
// Override the name if a nested module class is passed
|
|
302
|
+
if (options['class']) {
|
|
303
|
+
name = options['class'] + '[' + name.split('[')[1]
|
|
304
|
+
}
|
|
305
|
+
data[name] = element.val();
|
|
301
306
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
307
|
+
if (jQuery.ajax({
|
|
308
|
+
url: '/validators/uniqueness',
|
|
309
|
+
data: data,
|
|
310
|
+
async: false
|
|
311
|
+
}).status == 200) {
|
|
312
|
+
return options.message;
|
|
313
|
+
}
|
|
308
314
|
}
|
|
309
315
|
}
|
|
310
316
|
}
|
metadata
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: client_side_validations
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease:
|
|
5
|
-
version: 3.1.
|
|
5
|
+
version: 3.1.4
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
8
8
|
- Brian Cardarella
|
|
@@ -10,7 +10,7 @@ autorequire:
|
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
12
|
|
|
13
|
-
date: 2011-
|
|
13
|
+
date: 2011-12-22 00:00:00 -05:00
|
|
14
14
|
default_executable:
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
@@ -19,9 +19,9 @@ dependencies:
|
|
|
19
19
|
requirement: &id001 !ruby/object:Gem::Requirement
|
|
20
20
|
none: false
|
|
21
21
|
requirements:
|
|
22
|
-
- -
|
|
22
|
+
- - ~>
|
|
23
23
|
- !ruby/object:Gem::Version
|
|
24
|
-
version: 3.1.0
|
|
24
|
+
version: 3.1.0
|
|
25
25
|
type: :development
|
|
26
26
|
version_requirements: *id001
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
@@ -85,9 +85,9 @@ dependencies:
|
|
|
85
85
|
requirement: &id007 !ruby/object:Gem::Requirement
|
|
86
86
|
none: false
|
|
87
87
|
requirements:
|
|
88
|
-
- -
|
|
88
|
+
- - ~>
|
|
89
89
|
- !ruby/object:Gem::Version
|
|
90
|
-
version:
|
|
90
|
+
version: 1.5.0
|
|
91
91
|
type: :development
|
|
92
92
|
version_requirements: *id007
|
|
93
93
|
- !ruby/object:Gem::Dependency
|
|
@@ -98,7 +98,7 @@ dependencies:
|
|
|
98
98
|
requirements:
|
|
99
99
|
- - ~>
|
|
100
100
|
- !ruby/object:Gem::Version
|
|
101
|
-
version: 2.0.0
|
|
101
|
+
version: 2.0.0
|
|
102
102
|
type: :development
|
|
103
103
|
version_requirements: *id008
|
|
104
104
|
- !ruby/object:Gem::Dependency
|
|
@@ -304,7 +304,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
304
304
|
requirements: []
|
|
305
305
|
|
|
306
306
|
rubyforge_project:
|
|
307
|
-
rubygems_version: 1.
|
|
307
|
+
rubygems_version: 1.3.9.3
|
|
308
308
|
signing_key:
|
|
309
309
|
specification_version: 3
|
|
310
310
|
summary: Client Side Validations
|