client_side_validations 3.0.5 → 3.0.14

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7bbfbec3b5249e2f44af35b70f85e6ffe9290248
4
+ data.tar.gz: 511bde483bc7b4958690df487f5668ec08361871
5
+ SHA512:
6
+ metadata.gz: c0cd68439759ff06235233463653296bc7366fa868aba93655e468d3cd20cb8010d73991e45c97287201b2d471bafc9ba2370c6e75597c79644dd2500f1e5c2a
7
+ data.tar.gz: 33cfd19f17ea44875b07506d3f6599f884f434815f9e2b79636270047a45fa769e42a986ba158d16c60b951d164ae550f497ec963b70847f09c8de8a6fffd111
@@ -12,33 +12,23 @@ Gem::Specification.new do |s|
12
12
  s.summary = %q{Client Side Validations}
13
13
  s.description = %q{Client Side Validations}
14
14
 
15
- s.files = `git ls-files -- {lib/*,javascript/*,*.gemspec}`.split("\n")
15
+ s.files = `git ls-files -- {lib/*,vendor/*,*.gemspec}`.split("\n")
16
16
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
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_dependency 'activesupport'
21
-
22
20
  s.add_development_dependency 'rails', '~> 3.0.0'
23
21
  s.add_development_dependency 'sqlite3'
24
22
  s.add_development_dependency 'bson_ext'
25
23
  s.add_development_dependency 'mongoid', '~> 2.0.0'
26
24
  s.add_development_dependency 'mongo_mapper','~>0.9.0'
27
25
  s.add_development_dependency 'mocha'
28
- s.add_development_dependency 'simple_form'
29
- s.add_development_dependency 'formtastic'
26
+ s.add_development_dependency 'simple_form', '~> 1.5.0'
27
+ s.add_development_dependency 'formtastic', '~> 1.2.0'
30
28
 
31
29
  # For QUnit testing
32
30
  s.add_development_dependency 'sinatra', '~> 1.0'
33
31
  s.add_development_dependency 'shotgun'
34
32
  s.add_development_dependency 'thin'
35
33
  s.add_development_dependency 'json'
36
-
37
- ruby_minor_version = RUBY_VERSION.split('.')[1].to_i
38
- if ruby_minor_version == 8
39
- s.add_development_dependency 'minitest'
40
- s.add_development_dependency 'ruby-debug'
41
- elsif ruby_minor_version == 9
42
- s.add_development_dependency 'ruby-debug19'
43
- end
44
34
  end
@@ -2,7 +2,7 @@ module ClientSideValidations::ActionView::Helpers
2
2
  module FormBuilder
3
3
 
4
4
  def self.included(base)
5
- (base.field_helpers - %w(apply_form_for_options! label check_box radio_button fields_for hidden_field)).each do |selector|
5
+ (base.field_helpers.map(&:to_s) - %w(apply_form_for_options! label check_box radio_button fields_for hidden_field)).each do |selector|
6
6
  base.class_eval <<-RUBY_EVAL
7
7
  def #{selector}_with_client_side_validations(method, options = {})
8
8
  apply_client_side_validators(method, options)
@@ -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(@object.client_side_validation_hash[method], options[:validate])
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(validators, filters)
88
- if validators
89
- filtered_validators = validators.inject({}) do |filtered_validators, validator|
90
- filtered_validators[validator.first] = validator.last
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
- filtered_validators.delete(validator.first)
94
- elsif force_validator_despite_conditional?(validator, filters) && !can_run_validator?(validator)
95
- filtered_validators.delete(validator.first)
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.key?(:if) || validator.last.key?(:unless)
99
- filtered_validators.delete(validator.first)
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
- filtered_validators[validator.first].delete(:if) if filtered_validators[validator.first]
103
- filtered_validators[validator.first].delete(:unless) if filtered_validators[validator.first]
104
- filtered_validators
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
- filtered_validators.empty? ? nil : filtered_validators
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 = can_run_if_validator?(validator.last[:if])
126
- unless_result = can_run_unless_validator?(validator.last[:unless])
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 can_run_if_validator?(conditional)
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 can_run_unless_validator?(conditional)
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
+
@@ -10,7 +10,7 @@ module ClientSideValidations::ActionView::Helpers
10
10
 
11
11
  # Always turn off HTML5 Validations
12
12
  options[:html] ||= {}
13
- options[:html][:novalidate] = true
13
+ options[:html][:novalidate] = 'novalidate'
14
14
 
15
15
  case record_or_name_or_array
16
16
  when String, Symbol
@@ -2,6 +2,7 @@ module ClientSideValidations::ActiveRecord
2
2
  class Middleware
3
3
 
4
4
  def self.is_unique?(klass, attribute, value, params)
5
+ value = type_cast_value(klass, attribute, value)
5
6
  column = klass.columns_hash[attribute.to_s]
6
7
  value = column.limit ? value.to_s.mb_chars[0, column.limit] : value.to_s if column.text?
7
8
 
@@ -23,11 +24,18 @@ module ClientSideValidations::ActiveRecord
23
24
  relation = relation.and(t.primary_key.not_eq(params[:id])) if params[:id]
24
25
  end
25
26
 
26
- (params[:scope] || {}).each do |key, value|
27
- relation = relation.and(t[key].eq(value))
27
+ (params[:scope] || {}).each do |attribute, value|
28
+ value = type_cast_value(klass, attribute, value)
29
+ relation = relation.and(t[attribute].eq(value))
28
30
  end
29
31
 
30
32
  !klass.where(relation).exists?
31
33
  end
34
+
35
+ private
36
+
37
+ def self.type_cast_value(klass, attribute, value)
38
+ klass.columns_hash[attribute].type_cast(value)
39
+ end
32
40
  end
33
41
  end
@@ -0,0 +1,6 @@
1
+ module ClientSideValidations
2
+ class Engine < ::Rails::Engine
3
+ config.app_middleware.use ClientSideValidations::Middleware::Validators
4
+ end
5
+ end
6
+
@@ -0,0 +1,8 @@
1
+ # This is only used by dependant libraries that need to find the files
2
+
3
+ module ClientSideValidations
4
+ module Files
5
+ Initializer = File.expand_path(File.dirname(__FILE__) + '/../generators/templates/client_side_validations/initializer.rb')
6
+ Javascript = File.expand_path(File.dirname(__FILE__) + '/../../vendor/assets/javascripts/rails.validations.js')
7
+ end
8
+ end
@@ -76,10 +76,5 @@ module ClientSideValidations
76
76
  end
77
77
 
78
78
  end
79
-
80
- class Engine < ::Rails::Engine
81
- config.app_middleware.use ClientSideValidations::Middleware::Validators
82
- end
83
-
84
79
  end
85
80
 
@@ -1,3 +1,3 @@
1
1
  module ClientSideValidations
2
- VERSION = "3.0.5"
2
+ VERSION = '3.0.14'
3
3
  end
@@ -6,5 +6,8 @@ require 'client_side_validations/active_record' if defined?(::ActiveRecord)
6
6
  require 'client_side_validations/mongoid' if defined?(::Mongoid)
7
7
  require 'client_side_validations/mongo_mapper' if defined?(::MongoMapper)
8
8
  require 'client_side_validations/action_view'
9
- require 'client_side_validations/middleware' if defined?(::Rails)
9
+ if defined?(::Rails)
10
+ require 'client_side_validations/middleware'
11
+ require 'client_side_validations/engine'
12
+ end
10
13
 
@@ -6,15 +6,15 @@ module ClientSideValidations
6
6
  desc 'Creates a ClientSideValidations initializer and copies client-side-validations.js to public/javascripts.'
7
7
 
8
8
  def copy_initializer
9
- copy_file 'client_side_validations.rb', 'config/initializers/client_side_validations.rb'
9
+ copy_file 'client_side_validations/initializer.rb', 'config/initializers/client_side_validations.rb'
10
10
  end
11
11
 
12
12
  def copy_locale
13
- copy_file '../../../javascript/rails.validations.js', 'public/javascripts/rails.validations.js'
13
+ copy_file '../../../vendor/assets/javascripts/rails.validations.js', 'public/javascripts/rails.validations.js'
14
14
  end
15
15
 
16
16
  def show_readme
17
- readme 'README' if behavior == :invoke
17
+ readme 'client_side_validations/README' if behavior == :invoke
18
18
  end
19
19
  end
20
20
  end
@@ -346,7 +346,7 @@ class ClientSideValidations::ActionViewHelpersTest < ActionView::TestCase
346
346
  assert_equal expected, output_buffer
347
347
  end
348
348
 
349
- def test_conditional_validator_filters
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 test_conditional_validators_should_be_filtered
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 test_conditional_validator_filters_being_forced
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 test_conditional_validator_filters_being_forced_and_not_meeting_condition
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 test_conditional_validator_filters_being_forced_individually
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 => :cannot_validate?
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 => :can_validate?
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 => { :presence => true })
506
- concat f.text_field(:title, :validate => { :presence => true })
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 test_conditional_validator_filters_being_forced_and_not_meeting_condition_individually
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 => :cannot_validate?
561
+ :unless => :cost_changed?
526
562
  }
527
563
  },
528
564
  :title => {
529
565
  :presence => {
530
566
  :message => "can't be blank",
531
- :if => :can_validate?
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, :validate => { :presence => true })
542
- concat f.text_field(:title, :validate => { :presence => true })
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 test_conditional_validator_filters_being_forced_with_procs
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 => Proc.new { |post| post.cannot_validate? }
595
+ :unless => :cost_changed?
559
596
  }
560
597
  },
561
598
  :title => {
562
599
  :presence => {
563
600
  :message => "can't be blank",
564
- :if => Proc.new { |post| post.can_validate? }
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)
@@ -171,5 +171,20 @@ class ClientSideValidationsActiveRecordMiddlewareTest < Test::Unit::TestCase
171
171
  assert_equal 'false', last_response.body
172
172
  assert last_response.ok?
173
173
  end
174
- end
175
174
 
175
+ def test_uniqueness_when_value_must_be_typecast
176
+ User.create(:active => false)
177
+ get '/validators/uniqueness.json', { 'user[active]' => 'false', 'case_sensitive' => true }
178
+
179
+ assert_equal 'false', last_response.body
180
+ assert last_response.ok?
181
+ end
182
+
183
+ def test_uniqueness_when_scope_is_given_and_value_must_be_typecast
184
+ User.create(:email => 'user@test.com', :active => true)
185
+ get '/validators/uniqueness.json', { 'user[email]' => 'user@test.com', 'scope' => { 'active' => 'true' }, 'case_sensitive' => true }
186
+
187
+ assert_equal 'false', last_response.body
188
+ assert last_response.ok?
189
+ end
190
+ end
@@ -1,4 +1,4 @@
1
- users_table = %{CREATE TABLE users (id INTEGER PRIMARY KEY, age INTEGER, name TEXT, email TEXT, title VARCHAR(5));}
1
+ users_table = %{CREATE TABLE users (id INTEGER PRIMARY KEY, age INTEGER, name TEXT, email TEXT, title VARCHAR(5), active BOOLEAN);}
2
2
  ActiveRecord::Base.connection.execute(users_table)
3
3
 
4
4
  class User < ActiveRecord::Base
data/test/base_helper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'rubygems'
2
- require 'ruby-debug'
2
+ require 'bundler'
3
+ Bundler.setup
3
4
  require 'test/unit'
4
5
  require 'mocha'
5
6
 
@@ -2,7 +2,7 @@ require 'sinatra'
2
2
  require 'json'
3
3
  require 'ruby-debug'
4
4
 
5
- use Rack::Static, :urls => ['/javascript'], :root => File.expand_path('../..', settings.root)
5
+ use Rack::Static, :urls => ['/vendor/assets/javascripts'], :root => File.expand_path('../..', settings.root)
6
6
 
7
7
  helpers do
8
8
  def jquery_link version
@@ -12,7 +12,7 @@
12
12
  </style>
13
13
 
14
14
  <%= script_tag jquery_src %>
15
- <%= script_tag "/javascript/rails.validations.js" %>
15
+ <%= script_tag "/vendor/assets/javascripts/rails.validations.js" %>
16
16
  </head>
17
17
 
18
18
  <body id="body">
@@ -11,5 +11,6 @@ module TestApp
11
11
  end
12
12
 
13
13
  require 'client_side_validations/middleware'
14
+ require 'client_side_validations/engine'
14
15
 
15
16
  TestApp::Application.initialize!