pcai_client_side_validations 3.2.1 → 3.2.2

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.
Files changed (31) hide show
  1. data/client_side_validations.gemspec +28 -0
  2. data/lib/client_side_validations.rb +18 -0
  3. data/lib/client_side_validations/action_view.rb +14 -0
  4. data/lib/client_side_validations/action_view/form_builder.rb +176 -0
  5. data/lib/client_side_validations/action_view/form_helper.rb +105 -0
  6. data/lib/client_side_validations/action_view/form_tag_helper.rb +12 -0
  7. data/lib/client_side_validations/active_model.rb +68 -0
  8. data/lib/client_side_validations/active_model/acceptance.rb +10 -0
  9. data/lib/client_side_validations/active_model/exclusion.rb +15 -0
  10. data/lib/client_side_validations/active_model/format.rb +10 -0
  11. data/lib/client_side_validations/active_model/inclusion.rb +15 -0
  12. data/lib/client_side_validations/active_model/length.rb +26 -0
  13. data/lib/client_side_validations/active_model/numericality.rb +33 -0
  14. data/lib/client_side_validations/active_model/presence.rb +10 -0
  15. data/lib/client_side_validations/active_record.rb +12 -0
  16. data/lib/client_side_validations/active_record/middleware.rb +50 -0
  17. data/lib/client_side_validations/active_record/uniqueness.rb +28 -0
  18. data/lib/client_side_validations/core_ext.rb +3 -0
  19. data/lib/client_side_validations/core_ext/range.rb +10 -0
  20. data/lib/client_side_validations/core_ext/regexp.rb +14 -0
  21. data/lib/client_side_validations/engine.rb +6 -0
  22. data/lib/client_side_validations/files.rb +8 -0
  23. data/lib/client_side_validations/generators.rb +12 -0
  24. data/lib/client_side_validations/generators/rails_validations.rb +15 -0
  25. data/lib/client_side_validations/middleware.rb +105 -0
  26. data/lib/client_side_validations/version.rb +3 -0
  27. data/lib/generators/client_side_validations/copy_assets_generator.rb +56 -0
  28. data/lib/generators/client_side_validations/install_generator.rb +22 -0
  29. data/lib/generators/templates/client_side_validations/initializer.rb +11 -0
  30. data/vendor/assets/javascripts/rails.validations.js +424 -0
  31. metadata +48 -18
@@ -0,0 +1,11 @@
1
+ # ClientSideValidations Initializer
2
+
3
+ # Uncomment the following block if you want each input field to have the validation messages attached.
4
+ # ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
5
+ # unless html_tag =~ /^<label/
6
+ # %{<div class="field_with_errors">#{html_tag}<label for="#{instance.send(:tag_id)}" class="message">#{instance.error_message.first}</label></div>}.html_safe
7
+ # else
8
+ # %{<div class="field_with_errors">#{html_tag}</div>}.html_safe
9
+ # end
10
+ # end
11
+
@@ -0,0 +1,424 @@
1
+ (function() {
2
+ var $, validateElement, validateForm, validatorsFor,
3
+ __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
4
+
5
+ $ = jQuery;
6
+
7
+ $.fn.validate = function() {
8
+ return this.filter('form[data-validate]').each(function() {
9
+ var addError, binding, event, form, removeError, settings, _ref, _ref2;
10
+ form = $(this);
11
+ settings = window.ClientSideValidations.forms[form.attr('id')];
12
+ addError = function(element, message) {
13
+ return ClientSideValidations.formBuilders[settings.type].add(element, settings, message);
14
+ };
15
+ removeError = function(element) {
16
+ return ClientSideValidations.formBuilders[settings.type].remove(element, settings);
17
+ };
18
+ form.submit(function() {
19
+ return form.isValid(settings.validators);
20
+ });
21
+ _ref = {
22
+ 'ajax:beforeSend': function(eventData) {
23
+ if (eventData.target === this) return form.isValid(settings.validators);
24
+ },
25
+ 'form:validate:after': function(eventData) {
26
+ return ClientSideValidations.callbacks.form.after(form, eventData);
27
+ },
28
+ 'form:validate:before': function(eventData) {
29
+ return ClientSideValidations.callbacks.form.before(form, eventData);
30
+ },
31
+ 'form:validate:fail': function(eventData) {
32
+ return ClientSideValidations.callbacks.form.fail(form, eventData);
33
+ },
34
+ 'form:validate:pass': function(eventData) {
35
+ return ClientSideValidations.callbacks.form.pass(form, eventData);
36
+ }
37
+ };
38
+ for (event in _ref) {
39
+ binding = _ref[event];
40
+ form.bind(event, binding);
41
+ }
42
+ _ref2 = {
43
+ 'focusout': function() {
44
+ return $(this).isValid(settings.validators);
45
+ },
46
+ 'change': function() {
47
+ return $(this).data('changed', true);
48
+ },
49
+ 'element:validate:after': function(eventData) {
50
+ return ClientSideValidations.callbacks.element.after($(this), eventData);
51
+ },
52
+ 'element:validate:before': function(eventData) {
53
+ return ClientSideValidations.callbacks.element.before($(this), eventData);
54
+ },
55
+ 'element:validate:fail': function(eventData, message) {
56
+ var element;
57
+ element = $(this);
58
+ return ClientSideValidations.callbacks.element.fail(element, message, function() {
59
+ return addError(element, message);
60
+ }, eventData);
61
+ },
62
+ 'element:validate:pass': function(eventData) {
63
+ var element;
64
+ element = $(this);
65
+ return ClientSideValidations.callbacks.element.pass(element, function() {
66
+ return removeError(element);
67
+ }, eventData);
68
+ }
69
+ };
70
+ for (event in _ref2) {
71
+ binding = _ref2[event];
72
+ form.find('[data-validate="true"]:input:enabled:not(:radio)').live(event, binding);
73
+ }
74
+ form.find('[data-validate="true"]:checkbox').live('click', function() {
75
+ return $(this).isValid(settings.validators);
76
+ });
77
+ return form.find('[id*=_confirmation]').each(function() {
78
+ var binding, confirmationElement, element, event, _ref3, _results;
79
+ confirmationElement = $(this);
80
+ element = form.find("#" + (this.id.match(/(.+)_confirmation/)[1]) + "[data-validate='true']:input");
81
+ if (element[0]) {
82
+ _ref3 = {
83
+ 'focusout': function() {
84
+ return element.data('changed', true).isValid(settings.validators);
85
+ },
86
+ 'keyup': function() {
87
+ return element.data('changed', true).isValid(settings.validators);
88
+ }
89
+ };
90
+ _results = [];
91
+ for (event in _ref3) {
92
+ binding = _ref3[event];
93
+ _results.push($("#" + (confirmationElement.attr('id'))).live(event, binding));
94
+ }
95
+ return _results;
96
+ }
97
+ });
98
+ });
99
+ };
100
+
101
+ $.fn.isValid = function(validators) {
102
+ var obj;
103
+ obj = $(this[0]);
104
+ if (obj.is('form')) {
105
+ return validateForm(obj, validators);
106
+ } else {
107
+ return validateElement(obj, validatorsFor(this[0].name, validators));
108
+ }
109
+ };
110
+
111
+ validatorsFor = function(name, validators) {
112
+ name = name.replace(/_attributes\]\[\d+\]/g, "_attributes][]");
113
+ return validators[name];
114
+ };
115
+
116
+ validateForm = function(form, validators) {
117
+ var valid;
118
+ form.trigger('form:validate:before');
119
+ valid = true;
120
+ form.find('[data-validate="true"]:input:enabled').each(function() {
121
+ if ($(this).isValid(validators)) return valid = false;
122
+ });
123
+ if (valid) {
124
+ form.trigger('form:validate:pass');
125
+ } else {
126
+ form.trigger('form:validate:fail');
127
+ }
128
+ form.trigger('form:validate:after');
129
+ return valid;
130
+ };
131
+
132
+ validateElement = function(element, validators) {
133
+ var context, fn, kind, message, valid, _ref;
134
+ element.trigger('element:validate:before');
135
+ if (element.data('changed') !== false) {
136
+ valid = true;
137
+ element.data('changed', false);
138
+ context = ClientSideValidations.validators.local;
139
+ for (kind in context) {
140
+ fn = context[kind];
141
+ if (validators[kind] && (message = fn.call(context, element, validators[kind]))) {
142
+ element.trigger('element:validate:fail', message).data('valid', false);
143
+ valid = false;
144
+ break;
145
+ }
146
+ }
147
+ if (valid) {
148
+ context = ClientSideValidations.validators.remote;
149
+ for (kind in context) {
150
+ fn = context[kind];
151
+ if (validators[kind] && (message = fn.call(context, element, validators[kind]))) {
152
+ element.trigger('element:validate:fail', message).data('valid', false);
153
+ valid = false;
154
+ break;
155
+ }
156
+ }
157
+ }
158
+ if (valid) {
159
+ element.data('valid', null);
160
+ element.trigger('element:validate:pass');
161
+ }
162
+ }
163
+ element.trigger('element:validate:after');
164
+ return (_ref = element.data('valid') === false) != null ? _ref : {
165
+ "false": true
166
+ };
167
+ };
168
+
169
+ $(function() {
170
+ return $('form[data-validate]').validate();
171
+ });
172
+
173
+ window.ClientSideValidations = {
174
+ forms: {},
175
+ validators: {
176
+ all: function() {
177
+ return jQuery.extend({}, ClientSideValidations.validators.local, ClientSideValidations.validators.remote);
178
+ },
179
+ local: {
180
+ presence: function(element, options) {
181
+ if (/^\s*$/.test(element.val() || '')) return options.message;
182
+ },
183
+ acceptance: function(element, options) {
184
+ var _ref;
185
+ switch (element.attr('type')) {
186
+ case 'checkbox':
187
+ if (!element.attr('checked')) return options.message;
188
+ break;
189
+ case 'text':
190
+ if (element.val() !== (((_ref = options.accept) != null ? _ref.toString() : void 0) || '1')) {
191
+ return options.message;
192
+ }
193
+ }
194
+ },
195
+ format: function(element, options) {
196
+ var message;
197
+ message = this.presence(element, options);
198
+ if (message) {
199
+ if (options.allow_blank === true) return;
200
+ return message;
201
+ }
202
+ if (options["with"] && !options["with"].test(element.val())) {
203
+ return options.message;
204
+ }
205
+ if (options.without && options.without.test(element.val())) {
206
+ return options.message;
207
+ }
208
+ },
209
+ numericality: function(element, options) {
210
+ var CHECKS, check, fn, operator;
211
+ if (!/^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d*)?$/.test(element.val())) {
212
+ return options.messages.numericality;
213
+ }
214
+ if (options.only_integer && !/^[+-]?\d+$/.test(element.val())) {
215
+ return options.messages.only_integer;
216
+ }
217
+ CHECKS = {
218
+ greater_than: '>',
219
+ greater_than_or_equal_to: '>=',
220
+ equal_to: '==',
221
+ less_than: '<',
222
+ less_than_or_equal_to: '<='
223
+ };
224
+ for (check in CHECKS) {
225
+ operator = CHECKS[check];
226
+ if (!(options[check] != null)) continue;
227
+ fn = new Function("return " + (element.val()) + " " + operator + " " + options[check]);
228
+ if (!fn()) return options.messages[check];
229
+ }
230
+ if (options.odd && !(parseInt(element.val(), 10) % 2)) {
231
+ return options.messages.odd;
232
+ }
233
+ if (options.even && (parseInt(element.val(), 10) % 2)) {
234
+ return options.messages.even;
235
+ }
236
+ },
237
+ length: function(element, options) {
238
+ var CHECKS, blankOptions, check, fn, message, operator, tokenized_length, tokenizer;
239
+ tokenizer = options.js_tokenizer || "split('')";
240
+ tokenized_length = new Function('element', "return (element.val()." + tokenizer + " || '').length")(element);
241
+ CHECKS = {
242
+ is: '==',
243
+ minimum: '>=',
244
+ maximum: '<='
245
+ };
246
+ blankOptions = {};
247
+ blankOptions.message = options.is ? options.messages.is : options.minimum ? options.messages.minimum : void 0;
248
+ message = this.presence(element, blankOptions);
249
+ if (message) {
250
+ if (options.allow_blank === true) return;
251
+ return message;
252
+ }
253
+ for (check in CHECKS) {
254
+ operator = CHECKS[check];
255
+ if (!options[check]) continue;
256
+ fn = new Function("return " + tokenized_length + " " + operator + " " + options[check]);
257
+ if (!fn()) return options.messages[check];
258
+ }
259
+ },
260
+ exclusion: function(element, options) {
261
+ var lower, message, o, upper, _ref;
262
+ message = this.presence(element, options);
263
+ if (message) {
264
+ if (options.allow_blank === true) return;
265
+ return message;
266
+ }
267
+ if (options["in"]) {
268
+ if (_ref = element.val(), __indexOf.call((function() {
269
+ var _i, _len, _ref2, _results;
270
+ _ref2 = options["in"];
271
+ _results = [];
272
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
273
+ o = _ref2[_i];
274
+ _results.push(o.toString());
275
+ }
276
+ return _results;
277
+ })(), _ref) >= 0) {
278
+ return options.message;
279
+ }
280
+ }
281
+ if (options.range) {
282
+ lower = options.range[0];
283
+ upper = options.range[1];
284
+ if (element.val() >= lower && element.val() <= upper) {
285
+ return options.message;
286
+ }
287
+ }
288
+ },
289
+ inclusion: function(element, options) {
290
+ var lower, message, o, upper, _ref;
291
+ message = this.presence(element, options);
292
+ if (message) {
293
+ if (options.allow_blank === true) return;
294
+ return message;
295
+ }
296
+ if (options["in"]) {
297
+ if (_ref = element.val(), __indexOf.call((function() {
298
+ var _i, _len, _ref2, _results;
299
+ _ref2 = options["in"];
300
+ _results = [];
301
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
302
+ o = _ref2[_i];
303
+ _results.push(o.toString());
304
+ }
305
+ return _results;
306
+ })(), _ref) >= 0) {
307
+ return;
308
+ }
309
+ return options.message;
310
+ }
311
+ if (options.range) {
312
+ lower = options.range[0];
313
+ upper = options.range[1];
314
+ if (element.val() >= lower && element.val() <= upper) return;
315
+ return options.message;
316
+ }
317
+ },
318
+ confirmation: function(element, options) {
319
+ if (element.val() !== jQuery("#" + (element.attr('id')) + "_confirmation").val()) {
320
+ return options.message;
321
+ }
322
+ }
323
+ },
324
+ remote: {
325
+ uniqueness: function(element, options) {
326
+ var data, key, message, name, scope_value, scoped_element, scoped_name, _ref;
327
+ message = ClientSideValidations.validators.local.presence(element, options);
328
+ if (message) {
329
+ if (options.allow_blank === true) return;
330
+ return message;
331
+ }
332
+ data = {};
333
+ data.case_sensitive = !!options.case_sensitive;
334
+ if (options.id) data.id = options.id;
335
+ if (options.scope) {
336
+ data.scope = {};
337
+ _ref = options.scope;
338
+ for (key in _ref) {
339
+ scope_value = _ref[key];
340
+ scoped_name = element.attr('name').replace(/\[\w+\]$/, "[" + key + "]");
341
+ scoped_element = jQuery("[name='" + scoped_name + "']");
342
+ if (scoped_element[0] && scoped_element.val() !== scope_value) {
343
+ data.scope[key] = scoped_element.val();
344
+ scoped_element.unbind("change." + element.id).bind("change." + element.id, function() {
345
+ element.trigger('change');
346
+ return element.trigger('focusout');
347
+ });
348
+ } else {
349
+ data.scope[key] = scope_value;
350
+ }
351
+ }
352
+ }
353
+ if (/_attributes\]/.test(element.attr('name'))) {
354
+ name = element.attr('name').match(/\[\w+_attributes\]/g).pop().match(/\[(\w+)_attributes\]/).pop();
355
+ name += /(\[\w+\])$/.exec(element.attr('name'))[1];
356
+ } else {
357
+ name = element.attr('name');
358
+ }
359
+ if (options['class']) name = options['class'] + '[' + name.split('[')[1];
360
+ data[name] = element.val();
361
+ if (jQuery.ajax({
362
+ url: '/validators/uniqueness',
363
+ data: data,
364
+ async: false
365
+ }).status === 200) {
366
+ return options.message;
367
+ }
368
+ }
369
+ }
370
+ },
371
+ formBuilders: {
372
+ 'ActionView::Helpers::FormBuilder': {
373
+ add: function(element, settings, message) {
374
+ var inputErrorField, label, labelErrorField;
375
+ if (element.data('valid') !== false && !(jQuery("label.message[for='" + (element.attr('id')) + "']")[0] != null)) {
376
+ inputErrorField = jQuery(settings.input_tag);
377
+ labelErrorField = jQuery(settings.label_tag);
378
+ label = jQuery("label[for='" + (element.attr('id')) + "']:not(.message)");
379
+ if (element.attr('autofocus')) element.attr('autofocus', false);
380
+ element.before(inputErrorField);
381
+ inputErrorField.find('span#input_tag').replaceWith(element);
382
+ inputErrorField.find('label.message').attr('for', element.attr('id'));
383
+ labelErrorField.find('label.message').attr('for', element.attr('id'));
384
+ label.replaceWith(labelErrorField);
385
+ labelErrorField.find('label#label_tag').replaceWith(label);
386
+ }
387
+ return jQuery("label.message[for='" + (element.attr('id')) + "']").text(message);
388
+ },
389
+ remove: function(element, settings) {
390
+ var errorFieldClass, inputErrorField, label, labelErrorField;
391
+ errorFieldClass = jQuery(settings.input_tag).attr('class');
392
+ inputErrorField = element.closest("." + errorFieldClass);
393
+ label = jQuery("label[for='" + (element.attr('id')) + "']:not(.message)");
394
+ labelErrorField = label.closest("." + errorFieldClass);
395
+ if (inputErrorField[0]) {
396
+ inputErrorField.find("#" + (element.attr('id'))).detach();
397
+ inputErrorField.replaceWith(element);
398
+ label.detach();
399
+ return labelErrorField.replaceWith(label);
400
+ }
401
+ }
402
+ }
403
+ },
404
+ callbacks: {
405
+ element: {
406
+ after: function(element, eventData) {},
407
+ before: function(element, eventData) {},
408
+ fail: function(element, message, addError, eventData) {
409
+ return addError();
410
+ },
411
+ pass: function(element, removeError, eventData) {
412
+ return removeError();
413
+ }
414
+ },
415
+ form: {
416
+ after: function(form, eventData) {},
417
+ before: function(form, eventData) {},
418
+ fail: function(form, eventData) {},
419
+ pass: function(form, eventData) {}
420
+ }
421
+ }
422
+ };
423
+
424
+ }).call(this);
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pcai_client_side_validations
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.1
4
+ version: 3.2.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-05-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &21633972 !ruby/object:Gem::Requirement
16
+ requirement: &25491264 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.2.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *21633972
24
+ version_requirements: *25491264
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: sqlite3
27
- requirement: &21633624 !ruby/object:Gem::Requirement
27
+ requirement: &25490952 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *21633624
35
+ version_requirements: *25490952
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: mocha
38
- requirement: &21633252 !ruby/object:Gem::Requirement
38
+ requirement: &25490628 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *21633252
46
+ version_requirements: *25490628
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: sinatra
49
- requirement: &21632844 !ruby/object:Gem::Requirement
49
+ requirement: &25490256 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '1.0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *21632844
57
+ version_requirements: *25490256
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: shotgun
60
- requirement: &21632448 !ruby/object:Gem::Requirement
60
+ requirement: &25489956 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *21632448
68
+ version_requirements: *25489956
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: thin
71
- requirement: &21632172 !ruby/object:Gem::Requirement
71
+ requirement: &25489632 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *21632172
79
+ version_requirements: *25489632
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: json
82
- requirement: &21631836 !ruby/object:Gem::Requirement
82
+ requirement: &25477020 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *21631836
90
+ version_requirements: *25477020
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: coffee-script
93
- requirement: &21631464 !ruby/object:Gem::Requirement
93
+ requirement: &25476720 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,14 +98,44 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *21631464
101
+ version_requirements: *25476720
102
102
  description: Client Side Validations
103
103
  email:
104
104
  - bcardarella@gmail.com
105
105
  executables: []
106
106
  extensions: []
107
107
  extra_rdoc_files: []
108
- files: []
108
+ files:
109
+ - lib/client_side_validations/action_view/form_builder.rb
110
+ - lib/client_side_validations/action_view/form_helper.rb
111
+ - lib/client_side_validations/action_view/form_tag_helper.rb
112
+ - lib/client_side_validations/action_view.rb
113
+ - lib/client_side_validations/active_model/acceptance.rb
114
+ - lib/client_side_validations/active_model/exclusion.rb
115
+ - lib/client_side_validations/active_model/format.rb
116
+ - lib/client_side_validations/active_model/inclusion.rb
117
+ - lib/client_side_validations/active_model/length.rb
118
+ - lib/client_side_validations/active_model/numericality.rb
119
+ - lib/client_side_validations/active_model/presence.rb
120
+ - lib/client_side_validations/active_model.rb
121
+ - lib/client_side_validations/active_record/middleware.rb
122
+ - lib/client_side_validations/active_record/uniqueness.rb
123
+ - lib/client_side_validations/active_record.rb
124
+ - lib/client_side_validations/core_ext/range.rb
125
+ - lib/client_side_validations/core_ext/regexp.rb
126
+ - lib/client_side_validations/core_ext.rb
127
+ - lib/client_side_validations/engine.rb
128
+ - lib/client_side_validations/files.rb
129
+ - lib/client_side_validations/generators/rails_validations.rb
130
+ - lib/client_side_validations/generators.rb
131
+ - lib/client_side_validations/middleware.rb
132
+ - lib/client_side_validations/version.rb
133
+ - lib/client_side_validations.rb
134
+ - lib/generators/client_side_validations/copy_assets_generator.rb
135
+ - lib/generators/client_side_validations/install_generator.rb
136
+ - lib/generators/templates/client_side_validations/initializer.rb
137
+ - vendor/assets/javascripts/rails.validations.js
138
+ - client_side_validations.gemspec
109
139
  homepage: https://github.com/bcardarella/client_side_validations
110
140
  licenses: []
111
141
  post_install_message: