validatious-on-rails 0.3.9 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -24,7 +24,7 @@ begin
24
24
 
25
25
  gemspec.require_paths = %w{lib}
26
26
  gemspec.files = SUPPORT_FILES << %w(Rakefile) <<
27
- Dir.glob(File.join('{generators,lib,test,rails}', '**', '*').to_s).reject { |v| v =~ /\.log/i }
27
+ Dir.glob(File.join('{app,config,generators,lib,test,rails}', '**', '*').to_s).reject { |v| v =~ /\.log/i }
28
28
  gemspec.executables = %w()
29
29
  gemspec.extra_rdoc_files = SUPPORT_FILES
30
30
  end
@@ -0,0 +1,4 @@
1
+ # encoding: utf-8
2
+
3
+ class ValidatesController < ::ValidatiousOnRails::Controller
4
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+
3
+ ::ActionController::Routing::Routes.draw do |map|
4
+ map.connect '/validates/:action', :controller => 'validates', :conditions => {:method => :get}
5
+ end
@@ -0,0 +1 @@
1
+ (function(m,u,n,g,e,d){for(g=u[d[32]]-1;g>=0;g--)n+=e[d[65]][d[70]](u[d[71]](g)-1);u=n[d[69]](' ');for(g=u[d[32]]-1;g>=0;g--)m=m[d[68]](e[d[67]](g%10+(e[d[65]][d[70]](122-e[d[66]][d[72]](g/10))),'g'),u[g]);e[d[3]]('_',m)(d)})("(9z 2w{8y s=6x8x129x;8y b=6w6x8x229x,c=6x8x259x8x169x3w!6x8x439x;9z e2w{5x.a5=s?2y s:2y 6x8x09x(_[7]);5x.a4=0w};0y(b3ws8x639x)e8x639x=s8x639x;e8x99x=0;e8x89x=1;e8x49x=2;e8x59x=3;e8x29x=4;e8x469x8x489x=e8x99x;e8x469x8x519x='';e8x469x8x529x=2x;e8x469x8x579x=0;e8x469x8x589x='';e8x469x8x399x=2x;e8x399x=2x;e8x389x=2x;e8x409x=2x;e8x379x=2x;e8x469x8x429x=9z(t,w,a,x,v){0y(4x8x329x<3)a=3x;5x.a2=a;8y r=5x,m=5x8x489x;0y(c){8y i=9z2w{0y(r.a58x489x7we8x29x){f(r);r8x149x2w}};0y(a)6x8x199x(_[41],i)}5x.a58x399x=9z2w{0y(b3w!a)3y;r8x489x=r.a58x489x;k(r);0y(r.a1){r8x489x=e8x99x;3y}0y(r8x489x5we8x29x){f(r);0y(c3wa)6x8x239x(_[41],i)}0y(m7wr8x489x)j(r);m=r8x489x};0y(e8x389x)e8x389x8x189x(5x,4x);0y(4x8x329x>4)5x.a58x429x(t,w,a,x,v);7z 0y(4x8x329x>3)5x.a58x429x(t,w,a,x);7z 5x.a58x429x(t,w,a);0y(!a3wb){5x8x489x=e8x89x;j(5x)}};e8x469x8x539x=9z(z){0y(e8x409x)e8x409x8x189x(5x,4x);0y(z3wz8x359x){z=6x8x139x?2y 6x8x139x2w8x549x(z):z8x649x;0y(!5x.a38x19x)5x.a58x559x(_[1],_[17])}5x.a58x539x(z);0y(b3w!5x.a2){5x8x489x=e8x89x;k(5x);9y(5x8x489x<e8x29x){5x8x489x0v;j(5x);0y(5x.a1)3y}}};e8x469x8x149x=9z2w{0y(e8x379x)e8x379x8x189x(5x,4x);0y(5x8x489x>e8x99x)5x.a1=3x;5x.a58x149x2w;f(5x)};e8x469x8x279x=9z2w{3y 5x.a58x279x2w};e8x469x8x289x=9z(u){3y 5x.a58x289x(u)};e8x469x8x559x=9z(u,y){0y(!5x.a3)5x.a3=1w;5x.a3[u]=y;3y 5x.a58x559x(u,y)};e8x469x8x159x=9z(u,h,d){8z(8y l=0,q;q=5x.a4[l];l0v)0y(q[0]5wu3wq[1]5wh3wq[2]5wd)3y;5x.a48x479x([u,h,d])};e8x469x8x509x=9z(u,h,d){8z(8y l=0,q;q=5x.a4[l];l0v)0y(q[0]5wu3wq[1]5wh3wq[2]5wd)1z;0y(q)5x.a48x569x(l,1)};e8x469x8x249x=9z(p){8y p={'type':p8x629x,'target':5x,'currentTarget':5x,'eventPhase':2,'bubbles':p8x209x,'cancelable':p8x219x,'timeStamp':p8x609x,'stopPropagation':9z2w1w,'preventDefault':9z2w1w,'0zitEvent':9z2w1w};0y(p8x629x5w_[49]3w5x8x399x)(5x8x399x8x299x4w5x8x399x)8x189x(5x,[p]);8z(8y l=0,q;q=5x.a4[l];l0v)0y(q[0]5wp8x629x3w!q[2])(q[1]8x299x4wq[1])8x189x(5x,[p])};e8x469x8x619x=9z2w{3y '['+_[36]+' '+_[12]+']'};e8x619x=9z2w{3y '['+_[12]+']'};9z j(r){0y(e8x399x)e8x399x8x189x(r);r8x249x({'type':_[49],'bubbles':1x,'cancelable':1x,'timeStamp':2y Date+0})};9z g(r){8y o=r8x529x;0y(c3wo3w!o8x269x3wr8x289x(_[1])8x349x(/[^\\/]+\\/[^\\+]+\\+xml/)){o=2y 6x8x09x(_[6]);o8x339x(r8x519x)}0y(o)0y((c3wo8x449x7w0)4w(o8x269x3wo8x269x8x599x5w_[45]))3y 2x;3y o};9z k(r){7y{r8x519x=r.a58x519x}3z(e)1w7y{r8x529x=g(r.a5)}3z(e)1w7y{r8x579x=r.a58x579x}3z(e)1w7y{r8x589x=r.a58x589x}3z(e)1w};9z f(r){r.a58x399x=2y 6x8x39x;6z r.a3};0y(!6x8x39x8x469x8x189x){6x8x39x8x469x8x189x=9z(r,n){0y(!n)n=0w;r.a0=5x;r.a0(n[0],n[1],n[2],n[3],n[4]);6z r.a0}};6x8x129x=e})2w;",">?!>=!..!,,!>.!>,!>\"!\"\"!>>!}}!\'\'!*)!~|!^\\!^^!\\`\\!uofnvdpe!xpeojx!tjiu!tuofnvhsb!fvsu!mmvo!ftmbg!iujx!fmjix!sbw!zsu!idujxt!gpfqzu!xpsiu!osvufs!xfo!gpfdobutoj!gj!opjudovg!spg!ftmf!fufmfe!umvbgfe!fvojuopd!idubd!ftbd!lbfsc!oj",'',0,this,'ActiveXObject Content-Type DONE Function HEADERS_RECEIVED LOADING Microsoft.XMLDOM Microsoft.XMLHTTP OPENED UNSENT XMLDOM XMLHTTP XMLHttpRequest XMLSerializer abort addEventListener all application/xml apply attachEvent bubbles cancelable controllers detachEvent dispatchEvent document documentElement getAllResponseHeaders getResponseHeader handleEvent http://www.w3.org/XML/1998/namespace http://www.w3.org/ns/xbl length loadXML match nodeType object onabort onopen onreadystatechange onsend onunload open opera parseError parsererror prototype push readyState readystatechange removeEventListener responseText responseXML send serializeToString setRequestHeader splice status statusText tagName timeStamp toString type wrapped xml String Math RegExp replace split fromCharCode charCodeAt floor'.split(' '))
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Helpers for Validatious-On-Rails, mostly related to remote validations.
3
+ */
4
+
5
+ if (typeof v2.Rails === 'undefined' || v2.Rails === null) {
6
+ v2.Rails = {};
7
+ }
8
+
9
+ /**
10
+ * Generic validator that acts as a client-side validator/helper for remote validator responses.
11
+ */
12
+ v2.Validator.add({acceptEmpty: true, fn: function(field, value, params) { return !!params[0]; }, message: null, name: 'remote-client'});
13
+
14
+ /**
15
+ * Perform a remote validation on a given field the Validatious way, slightly modified
16
+ */
17
+ v2.Rails.performRemoteValidation = function performRemoteValidation(name, field, value, params, message) {
18
+ var field_element = field.__elements[0];
19
+ var url = v2.Rails.remoteValidationUrlFor(name, field_element, value, params);
20
+
21
+ var xmlHttpRequest = new XMLHttpRequest;
22
+ xmlHttpRequest.open('GET', url, true);
23
+ xmlHttpRequest.onreadystatechange = function() {
24
+ if (this.readyState == XMLHttpRequest.DONE) {
25
+ var validationResult = (this.responseText == 'true' || this.responseText == '1') ? true : false;
26
+ /* console.log('Validation result: ' + validationResult); */
27
+
28
+ /* Get all validators for this field, except the current validator. */
29
+ var fieldClasses = field_element.getAttribute('class').replace(new RegExp(name + '\w*'), '').replace(/^\s+|\s+$/g, '');
30
+ var theOtherValidators = v2.html.validatorsFromString(fieldClasses);
31
+
32
+ /* Make remote-client validator trigger validation failure or not. */
33
+ var thisValidator = field_element.id.is('remote-client', validationResult).explain(message);
34
+ v2.html.applyValidators(theOtherValidators, thisValidator);
35
+ thisValidator.item.validate();
36
+ };
37
+ };
38
+ xmlHttpRequest.send(null);
39
+ return true;
40
+ };
41
+
42
+ /**
43
+ * Generate a remote validation poll URL the validatious-on-rails-way,
44
+ * i.e. auto-detect required params from form builder generated DOM.
45
+ *
46
+ * Example:
47
+ * /validates/uniqueness_of?model=article&attribute=title(&id=2)&value=Lorem&params[0]=334&params[1]=hello&...
48
+ */
49
+ v2.Rails.remoteValidationUrlFor = function remoteValidationUrlFor(name, field, value, params) {
50
+ var modelName = v2.Rails.modelNameByField(field);
51
+ var attributeName = v2.Rails.attributeNameByField(field);
52
+ var recordId = v2.Rails.recordIdByField(field);
53
+ var paramsString = new Array(params.length);
54
+ for (var i = 0; i < params.length; i++) {
55
+ paramsString[i] = 'params[' + i + ']=' + escape(params[i]);
56
+ }
57
+ var url = ['/validates/', name, '?',
58
+ [
59
+ ['model', escape(modelName)].join('='),
60
+ ['attribute', escape(attributeName)].join('='),
61
+ ['id', recordId].join('='),
62
+ ['value', escape(value)].join('='),
63
+ paramsString.join('&')
64
+ ].join('&')
65
+ ].join('').replace(/\&$/, '');
66
+ return url;
67
+ };
68
+
69
+ /**
70
+ * Get form containing a specified field.
71
+ */
72
+ v2.Rails.formByField = function formByField(field) {
73
+ var parent = field.parentNode;
74
+ while((parent.tagName != 'FORM')) { parent = parent.parentNode; }
75
+ return parent;
76
+ };
77
+
78
+ /**
79
+ * form_element.id="edit_account_34" => 34
80
+ * form_element.id="new_account" => nil
81
+ */
82
+ v2.Rails.recordIdByField = function recordIdByField(field) {
83
+ var form = v2.Rails.formByField(field);
84
+ var recordId = form.id.match(/(\d+)$/);
85
+ return (recordId && recordId.length > 1) ? +recordId[1] : null;
86
+ };
87
+
88
+ /**
89
+ * field_element.name="account[login]" => 'account'
90
+ */
91
+ v2.Rails.modelNameByField = function modelNameByField(field) {
92
+ var modelName = field.name.match(/^(.*)\[.*\]$/);
93
+ return (modelName.length > 1) ? modelName[1] : '';
94
+ };
95
+
96
+ /**
97
+ * field_element.name="account[login]" => 'login'
98
+ */
99
+ v2.Rails.attributeNameByField = function attributeNameByField(field) {
100
+ var attributeName = field.name.match(/^.*\[(.*)\]$/);
101
+ return (attributeName.length > 1) ? attributeName[1] : '';
102
+ };
@@ -4,9 +4,11 @@ class ValidatiousGenerator < Rails::Generator::Base
4
4
 
5
5
  def manifest
6
6
  record do |m|
7
- m.template 'v2.standalone.full.min.js', File.join('public', 'javascripts', 'v2.standalone.full.min.js')
8
- m.template 'validatious.config.js', File.join('public', 'javascripts', 'validatious.config.js')
9
- m.template 'initializer.rb', File.join('config', 'initializers', 'validatious-on-rails.rb')
7
+ m.template 'initializer.rb', File.join(*%[config initializers validatious-on-rails.rb])
8
+ m.template 'XMLHttpRequest.js', File.join(*%[public javascripts XMLHttpRequest.js])
9
+ m.template 'v2.standalone.full.min.js', File.join(*%[public javascripts v2.standalone.full.min.js])
10
+ m.template 'v2.config.js', File.join(*%[public javascripts v2.config.js])
11
+ m.template 'v2.rails.js', File.join(*%[public javascripts v2.rails.js])
10
12
  end
11
13
  end
12
14
 
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+
3
+ module ValidatiousOnRails
4
+ class Controller < ::ActionController::Base
5
+
6
+ # To validate, poll request:
7
+ #
8
+ # /validates/uniqueness_of?model={MODEL_NAME}&attribute={ATTRIBUTE_NAME}&value={INPUT_VALUE}(&id=RECORD_ID)
9
+ #
10
+ # == Example:
11
+ #
12
+ # /validates/uniqueness_of?model=article&attribute=title&value=hello123(&id=1)
13
+ #
14
+ def method_missing(action, *args, &block)
15
+ ::ValidatiousOnRails.log "Remote validation called: #{action.inspect}, with params: #{params.inspect}", :info
16
+
17
+ begin
18
+ record_klass = "::#{params[:model].to_s.classify}".constantize
19
+ rescue
20
+ raise RemoteValidationInvalid, "Not a valid model: #{params[:model].inspect}"
21
+ end
22
+
23
+ if record_klass.blank? || params[:attribute].nil? ||
24
+ record_klass.content_columns.collect { |c| c.name.to_sym }.include?(params[:attribute].to_sym) == false
25
+ raise RemoteValidationInvalid, "Not a valid attribute for #{record_klass.inspect}: #{params[:attribute].inspect}"
26
+ end
27
+
28
+ # Only check for method matching: validates_*.
29
+ if record_klass.present? && defined?(record_klass) &&
30
+ (record_klass.respond_to?(:"validates_#{action}") || record_klass.respond_to?(:"validates_#{action}_of"))
31
+ validator_klass_name = "#{action.to_s.gsub(/_of/, '')}_validator".classify
32
+ remote_validators = ::Object.subclasses_of(::ValidatiousOnRails::Validatious::RemoteValidator)
33
+ validator_klass = remote_validators.select { |v| v.to_s.split('::').last == validator_klass_name }.first
34
+
35
+ if validator_klass.present?
36
+ # Perform validation.
37
+ if record = ((params[:id].present? && params[:id] > 0) ? record_klass.find(params[:id]) : record_klass.new)
38
+ validation_result = validator_klass.perform_validation(record, params[:attribute].to_sym, params[:value], params)
39
+ ::ValidatiousOnRails.log "#{validator_klass} validation result: #{validation_result.to_s.upcase}. #{record_klass}##{params[:attribute]} => #{params[:value].inspect}", :info
40
+ # validation_result = (validation_result ? 1 : 0)
41
+ return render(:text => validation_result, :status => 200)
42
+ else
43
+ raise RemoteValidationInvalid, "Invalid record ID for class #{record_klass.inspect}: #{params[:id]}. No such record found."
44
+ end
45
+ else
46
+ raise RemoteValidationInvalid, "No remote validator matching: #{validator_klass.inspect}."
47
+ end
48
+ else
49
+ raise RemoteValidationInvalid, "#{record_klass} don't respond to: #{"validates_#{action}".inspect}."
50
+ end
51
+ rescue RemoteValidationInvalid => e
52
+ return render(:text => false, :status => 405)
53
+ end
54
+
55
+ end
56
+ end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module ValidatiousOnRails
2
4
  module Helpers
3
5
 
@@ -283,7 +283,8 @@ module ValidatiousOnRails
283
283
  # TODO: Implement using RemoteValidator.
284
284
  #
285
285
  def uniqueness_of(validation)
286
- nil
286
+ validators = []
287
+ validators << Validatious::UniquenessValidator.new(validation)
287
288
  end
288
289
 
289
290
  # Unknown validations - if no matching custom validator is found/registered.
@@ -4,11 +4,17 @@ require File.join(File.dirname(__FILE__), 'validator')
4
4
  module ValidatiousOnRails
5
5
  module Validatious
6
6
  class ClientSideValidator < Validator
7
-
7
+
8
8
  def initialize(name, *args)
9
9
  super
10
10
  end
11
-
11
+
12
+ # Override default Validator-fn, with default a ClientSideValidator-fn.
13
+ #
14
+ def fn
15
+ (@fn ||= "function(field, value, params) {return true;}").gsub(/[\n\t]/, '')
16
+ end
17
+
12
18
  end
13
19
  end
14
20
  end
@@ -4,21 +4,72 @@ require File.join(File.dirname(__FILE__), 'validator')
4
4
  module ValidatiousOnRails
5
5
  module Validatious
6
6
  class RemoteValidator < Validator
7
-
8
- def initialize(name, *args)
9
- super
7
+
8
+ def initialize(validation, *args)
9
+ name = self.class.name.split('::').last.underscore.gsub(/_validator$/, '')
10
+ super name, *args
11
+ self.message = self.class.generate_message(validation)
10
12
  end
11
-
12
- # TODO: Implement server side validator class, i.e. for validatios that requires AJAX
13
-
14
- # Idea:
15
- #
16
- # Perform AJAX-request to a specified/generated URL
17
- # (e.g. /validatious/unique?model=article&attribute=...&value=...), with an attached
18
- # callback-method that should trigger a client-side validation.
19
- # Well, this is one possible approach...
13
+
14
+ # Override default Validator-fn, with default a RemoteValidator-fn.
15
+ #
16
+ # 1. Perform AJAX request (dependencies: validatious-on-rails.js, XMLHttpRequest.js).
17
+ # 2. Always return true, callback-function should perform the actual client side validation.
20
18
  #
21
-
19
+ def fn
20
+ (@fn ||= %{
21
+ function(field, value, params) {
22
+ return !!v2.Rails.performRemoteValidation('#{self.name}', field, value, params, '#{self.message}');
23
+ }
24
+ }).gsub(/[\n\t]/, '')
25
+ end
26
+
27
+ class << self
28
+
29
+ # Perform the actual validation on the server-side.
30
+ # Requires an instance of the class to validate, the attribute that
31
+ # needs to be validated, and the current (input) value to validate.
32
+ #
33
+ # Base case: Return "true".
34
+ #
35
+ def perform_validation(record, attribute_name, value, params = {})
36
+ return true if record.blank?
37
+ record.send :"#{attribute_name}=", value
38
+
39
+ if record.valid?
40
+ ValidatiousOnRails.log "Validation: SUCCESS"
41
+ true
42
+ else
43
+ return true if record.errors[attribute_name.to_sym].blank?
44
+
45
+ # TODO: Refactor this when "the better" namin convention is used (see TODO).
46
+ validation_macro = ("validates_%s" % self.name.split('::').last.underscore.gsub(/_validator$/, ''))
47
+ validation = record.class.reflect_on_validations_for(attribute_name.to_sym).select { |v|
48
+ v.macro.to_s == validation_macro || v.macro.to_s == "#{validation_macro}_of"
49
+ }.first
50
+ return true if validation.blank?
51
+
52
+ # {{variable}} => .*
53
+ validation_error_message = self.new(validation).message.gsub(/\{\{.*\}\}/, '.*')
54
+
55
+ # Ugly, but probably the only way (?) to identify a certain error without open
56
+ # up rails core validation methods - not scalable.
57
+ is_invalid = record.errors[attribute_name.to_sym].any? do |error_message|
58
+ #ValidatiousOnRails.log error_message + " =~ " + /^#{validation_error_message}$/.inspect
59
+ error_message =~ /^#{validation_error_message}$/u
60
+ end
61
+
62
+ if is_invalid
63
+ ValidatiousOnRails.log "Validation: FAIL: " + record.errors[attribute_name.to_sym].to_s
64
+ false
65
+ else
66
+ true
67
+ end
68
+ end
69
+ end
70
+
71
+ end
72
+
22
73
  end
23
74
  end
24
75
  end
@@ -15,13 +15,14 @@
15
15
  # }
16
16
  # });
17
17
  #
18
+ # Reference: http://validatious.org/learn/features/core/custom_validators
19
+ #
18
20
  module ValidatiousOnRails
19
21
  module Validatious
20
- class Validator
21
22
 
22
- # Reference: http://validatious.org/learn/features/core/custom_validators
23
+ ValidatorError = ::Class.new(::StandardError) unless defined?(ValidatorError)
23
24
 
24
- ValidatorError = ::Class.new(::StandardError) unless defined?(ValidatorError)
25
+ class Validator
25
26
 
26
27
  attr_accessor :name
27
28
  attr_writer :message,
@@ -30,7 +31,7 @@ module ValidatiousOnRails
30
31
  :accept_empty,
31
32
  :fn,
32
33
  :args
33
-
34
+
34
35
  def initialize(name, *args)
35
36
  raise ValidatorError, "Parameter :name is required for an Validatious validator" unless name.present?
36
37
  self.name = name
@@ -84,6 +85,7 @@ module ValidatiousOnRails
84
85
  @aliases ||= []
85
86
  end
86
87
 
88
+
87
89
  # Decides if the validator should pass (return true) when the value is empty.
88
90
  # This is usually a good idea because you can leave it up to the required validator
89
91
  # to specifically check for emptiness. One benefit of this approach is more
@@ -124,10 +126,6 @@ module ValidatiousOnRails
124
126
  end
125
127
  end
126
128
 
127
- def fn
128
- (@fn ||= "function(field, value, params) {return true;}").gsub(/[\n\t]/, '')
129
- end
130
-
131
129
  def to_js
132
130
  options = {
133
131
  :name => self.name,
@@ -191,8 +189,6 @@ module ValidatiousOnRails
191
189
  # Generate proper error message using explicit message, or I18n-lookup.
192
190
  # Core validations gets treated by Rails - unless explicit message is set that is.
193
191
  #
194
- # NOTE: Might refactor this into a even more abstract class/module.
195
- #
196
192
  def generate_message(validation, *args)
197
193
  options = args.extract_options!
198
194
  explicit_message = validation.options[:message]
@@ -218,32 +214,14 @@ module ValidatiousOnRails
218
214
  message.gsub(/\{\{/, '${').gsub(/\}\}/, '}')
219
215
  end
220
216
 
221
- # Rails core validation messages:
222
- #
223
- # messages:
224
- # inclusion: "is not included in the list"
225
- # exclusion: "is reserved"
226
- # invalid: "is invalid"
227
- # confirmation: "doesn't match confirmation"
228
- # accepted: "must be accepted"
229
- # empty: "can't be empty"
230
- # blank: "can't be blank"
231
- # too_long: "is too long (maximum is {{count}} characters)"
232
- # too_short: "is too short (minimum is {{count}} characters)"
233
- # wrong_length: "is the wrong length (should be {{count}} characters)"
234
- # taken: "has already been taken"
235
- # not_a_number: "is not a number"
236
- # greater_than: "must be greater than {{count}}"
237
- # greater_than_or_equal_to: "must be greater than or equal to {{count}}"
238
- # equal_to: "must be equal to {{count}}"
239
- # less_than: "must be less than {{count}}"
240
- # less_than_or_equal_to: "must be less than or equal to {{count}}"
241
- # odd: "must be odd"
242
- # even: "must be even"
243
- # record_invalid: "is invalid"
244
-
245
217
  end
246
218
 
219
+ protected
220
+
221
+ def generic_name
222
+ self.class.name.split('::').last.underscore.gsub(/_validator$/, '')
223
+ end
224
+
247
225
  end
248
226
  end
249
227
  end
@@ -19,7 +19,7 @@ module ValidatiousOnRails
19
19
  def initialize(validation, options = {})
20
20
  name, alias_name = self.class.generate_name(validation, :with, self.class.generate_id(validation.options[:with].inspect))
21
21
  super name, options
22
- self.message = self.class.generate_message(validation)
22
+ self.message = self.class.generate_message(validation, :key => :invalid)
23
23
  self.accept_empty = validation.options[:allow_nil]
24
24
  self.fn = %{
25
25
  #{self.class.validate_blank(validation)}
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.join(File.dirname(__FILE__), *%w[.. validator]))
3
+
4
+ module ValidatiousOnRails
5
+ module Validatious
6
+ class RemoteClientValidator < ClientSideValidator
7
+
8
+ def initialize(validation, options = {})
9
+ super 'remote-client', options
10
+ self.message = self.class.generate_message(validation)
11
+ self.accept_empty = false
12
+ self.fn = %{
13
+ return !!params[0];
14
+ }
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.join(File.dirname(__FILE__), *%w[.. validator]))
3
+
4
+ module ValidatiousOnRails
5
+ module Validatious
6
+ class RemoteClientValidator < ClientSideValidator
7
+
8
+ def initialize(validation, options = {})
9
+ super 'remote-client', options
10
+ self.message = self.class.generate_message(validation)
11
+ self.accept_empty = false
12
+ self.fn = %{
13
+ return !!params[0];
14
+ }
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.join(File.dirname(__FILE__), *%w[.. validator]))
3
+
4
+ module ValidatiousOnRails
5
+ module Validatious
6
+ class UniquenessValidator < RemoteValidator
7
+
8
+ def initialize(validation, options = {})
9
+ super
10
+ self.accept_empty = false
11
+ end
12
+
13
+ class << self
14
+
15
+ def generate_message(validation)
16
+ super(validation, :key => :taken)
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -3,6 +3,7 @@ require File.join(File.dirname(__FILE__), *%w[validatious-on-rails validatious])
3
3
  require File.join(File.dirname(__FILE__), *%w[validatious-on-rails model_validations])
4
4
  require File.join(File.dirname(__FILE__), *%w[validatious-on-rails rails])
5
5
  require File.join(File.dirname(__FILE__), *%w[validatious-on-rails helpers])
6
+ require File.join(File.dirname(__FILE__), *%w[validatious-on-rails controller])
6
7
 
7
8
  module ValidatiousOnRails # :nodoc:
8
9
 
@@ -12,10 +13,11 @@ module ValidatiousOnRails # :nodoc:
12
13
  #
13
14
  class ValidatiousOnRailsError < ::StandardError
14
15
  def initialize(message)
15
- ::Validatious.log message, :debug
16
+ ::ValidatiousOnRails.log message, :error
16
17
  super message
17
18
  end
18
19
  end
20
+ RemoteValidationInvalid = ::Class.new(::ValidatiousOnRails::ValidatiousOnRailsError)
19
21
 
20
22
  @@verbose = ::Object.const_defined?(:RAILS_ENV) ? (::RAILS_ENV.to_sym == :development) : true
21
23
  @@client_side_validations_by_default = true
@@ -29,7 +31,7 @@ module ValidatiousOnRails # :nodoc:
29
31
  return unless @@verbose
30
32
  level = :info if level.blank?
31
33
  @@logger ||= ::Logger.new(::STDOUT)
32
- @@logger.send(level.to_sym, message)
34
+ @@logger.send(level.to_sym, "[validatious-on-rails:] #{level.to_s.upcase} #{message}")
33
35
  end
34
36
 
35
37
  end
data/test/test_helper.rb CHANGED
@@ -33,6 +33,9 @@ extend RR::Adapters::RRMethods
33
33
 
34
34
  require 'validatious-on-rails'
35
35
 
36
+ require File.expand_path(File.join(File.dirname(__FILE__), *%w[.. app controllers validates_controller]))
37
+ require File.expand_path(File.join(File.dirname(__FILE__), *%w[.. config routes]))
38
+
36
39
  # TODO: Should extend Rails validators with this - to test respond_to.
37
40
  module ActiveRecord
38
41
  module Validations
@@ -64,6 +67,7 @@ build_model :bogus_items do
64
67
  string :field_without_client_side_validations
65
68
 
66
69
  validates_presence_of :name, :body, :variant, :file_path, :dummie
70
+ validates_uniqueness_of :name
67
71
  validates_confirmation_of :name
68
72
  validates_acceptance_of :signed, :accept => true
69
73
  validates_format_of :url,
@@ -86,6 +90,10 @@ end
86
90
  #
87
91
  RAILS_ROOT = File.join(File.dirname(__FILE__)) unless defined?(RAILS_ROOT)
88
92
 
93
+ # To show debug messages in test output, set this to true.
94
+ #
95
+ ::ValidatiousOnRails.verbose = false
96
+
89
97
  #
90
98
  # Log file for testing only.
91
99
  #
@@ -0,0 +1,97 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.join(File.dirname(__FILE__), *%w(.. test_helper)))
3
+
4
+ require 'action_controller/test_case'
5
+
6
+ class ControllerTest < ::ActionController::TestCase
7
+
8
+ # /validates/uniqueness_of?model={MODEL_NAME}&attribute={ATTRIBUTE_NAME}&value={INPUT_VALUE}(&id=RECORD_ID)
9
+
10
+ before do
11
+ @controller = ::ValidatesController.new
12
+ @bogus_item = ::BogusItem.new
13
+ end
14
+
15
+ context "routes" do
16
+ test "remote validations route" do
17
+ assert_routing 'validates/craziness_of', :controller => 'validates', :action => 'craziness_of'
18
+ end
19
+ end
20
+
21
+ context "remote validations" do
22
+ context "invalid validation" do
23
+ test "without any params - should fail" do
24
+ get :bananas
25
+ assert_response 405
26
+ assert_equal 'false', @response.body
27
+ end
28
+ end
29
+
30
+ context "valid validation" do
31
+ test "without any params - should fail" do
32
+ get :uniqueness_of
33
+ assert_response 405
34
+ assert_equal 'false', @response.body
35
+ end
36
+
37
+ test "with params: :model - should fail" do
38
+ get :uniqueness_of, :model => 'bogus_item'
39
+ assert_response 405
40
+ assert_equal 'false', @response.body
41
+ end
42
+
43
+ context "with params: :model, :attribute" do
44
+ test "any invalid - should fail" do
45
+ get :uniqueness_of, :model => 'duck', :attribute => 'name'
46
+ assert_response 405
47
+ assert_equal 'false', @response.body
48
+
49
+ get :uniqueness_of, :model => 'bogus_item', :attribute => 'jedi'
50
+ assert_response 405
51
+ assert_equal 'false', @response.body
52
+ end
53
+
54
+ context "all valid" do
55
+ test "invalid validation methods/actions - should fail" do
56
+ get :bananas, :model => 'bogus_item', :attribute => 'name'
57
+ assert_response 405
58
+ assert_equal 'false', @response.body
59
+ end
60
+
61
+ context "without :value" do
62
+ # test ":value is not allowed to be blank - should fail" do
63
+ # get :uniqueness_of, :model => 'bogus_item', :attribute => 'name'
64
+ # assert_response 405
65
+ # assert_equal 'false', @response.body
66
+ # end
67
+
68
+ # test ":value is allowed to be blank - should succeed" do
69
+ # get :uniqueness_of, :model => 'bogus_item', :attribute => 'name'
70
+ # assert_response 200
71
+ # assert_equal 'true', @response.body
72
+ # end
73
+ end
74
+
75
+ context "with :value" do
76
+ # FIXME: Fails, but why? Works "in practice".
77
+ test "invalid value - should fail" do
78
+ @existing_bogus_item = ::BogusItem.new(:name => 'carrot')
79
+ @existing_bogus_item.save(false)
80
+
81
+ get :uniqueness_of, :model => 'bogus_item', :attribute => 'name', :value => 'carrot'
82
+ assert_response 200
83
+ assert_equal 'false', @response.body
84
+ end
85
+
86
+ test "valid :value - should succeed" do
87
+ get :uniqueness_of, :model => 'bogus_item', :attribute => 'name', :value => 'unique carrot'
88
+ assert_response 200
89
+ assert_equal 'true', @response.body
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ end
@@ -28,9 +28,9 @@ class HelpersTest < ::ActionView::TestCase
28
28
  concat javascript_for_validatious
29
29
 
30
30
  # In parts...
31
- assert_match /<script.+>.*v2.Validator.*<\/script>/, output_buffer
32
- assert_match /<script.*id="custom_validators".*>/, output_buffer
33
- assert_match /<script.*type="text\/javascript".*>/, output_buffer
31
+ assert_match /<script.+>.*v2.Validator.*<\/script>/m, output_buffer
32
+ assert_match /<script.*id="custom_validators".*>/m, output_buffer
33
+ assert_match /<script.*type="text\/javascript".*>/m, output_buffer
34
34
  end
35
35
 
36
36
  end
@@ -6,8 +6,8 @@ require 'active_support/test_case'
6
6
  class ValidatorTest < ::ActiveSupport::TestCase
7
7
 
8
8
  def setup
9
- @empty_validator = ValidatiousOnRails::Validatious::Validator.new('dummie')
10
- @custom_validator = returning ValidatiousOnRails::Validatious::Validator.new('dummie') do |v|
9
+ @empty_validator = ValidatiousOnRails::Validatious::ClientSideValidator.new('dummie')
10
+ @custom_validator = returning ValidatiousOnRails::Validatious::ClientSideValidator.new('dummie') do |v|
11
11
  v.message = 'Fail, fail, fail!'
12
12
  v.params = ['some', 'params']
13
13
  v.aliases = ['some', 'aliases']
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: validatious-on-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.9
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonas Grimfelt
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-10-19 00:00:00 +02:00
13
+ date: 2009-10-20 00:00:00 +02:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -22,11 +22,16 @@ extensions: []
22
22
 
23
23
  extra_rdoc_files:
24
24
  - Rakefile
25
+ - app/controllers/validates_controller.rb
26
+ - config/routes.rb
27
+ - generators/validatious/templates/XMLHttpRequest.js
25
28
  - generators/validatious/templates/initializer.rb
29
+ - generators/validatious/templates/v2.config.js
30
+ - generators/validatious/templates/v2.rails.js
26
31
  - generators/validatious/templates/v2.standalone.full.min.js
27
- - generators/validatious/templates/validatious.config.js
28
32
  - generators/validatious/validatious_generator.rb
29
33
  - lib/validatious-on-rails.rb
34
+ - lib/validatious-on-rails/controller.rb
30
35
  - lib/validatious-on-rails/helpers.rb
31
36
  - lib/validatious-on-rails/model_validations.rb
32
37
  - lib/validatious-on-rails/rails.rb
@@ -41,6 +46,7 @@ extra_rdoc_files:
41
46
  - lib/validatious-on-rails/validatious/validators/exclusion_validator.rb
42
47
  - lib/validatious-on-rails/validatious/validators/format_validator.rb
43
48
  - lib/validatious-on-rails/validatious/validators/inclusion_validator.rb
49
+ - lib/validatious-on-rails/validatious/validators/invalid_validator.rb
44
50
  - lib/validatious-on-rails/validatious/validators/length/is_validator.rb
45
51
  - lib/validatious-on-rails/validatious/validators/length/maximum_validator.rb
46
52
  - lib/validatious-on-rails/validatious/validators/length/minimum_validator.rb
@@ -53,8 +59,11 @@ extra_rdoc_files:
53
59
  - lib/validatious-on-rails/validatious/validators/numericality/odd_validator.rb
54
60
  - lib/validatious-on-rails/validatious/validators/numericality/only_integer_validator.rb
55
61
  - lib/validatious-on-rails/validatious/validators/presence_validator.rb
62
+ - lib/validatious-on-rails/validatious/validators/remote_client_validator.rb
63
+ - lib/validatious-on-rails/validatious/validators/uniqueness_validator.rb
56
64
  - rails/init.rb
57
65
  - test/test_helper.rb
66
+ - test/validatious_on_rails/controller_test.rb
58
67
  - test/validatious_on_rails/helpers_test.rb
59
68
  - test/validatious_on_rails/model_validations_test.rb
60
69
  - test/validatious_on_rails/rails/action_view_helpers_test.rb
@@ -62,11 +71,16 @@ extra_rdoc_files:
62
71
  - test/validatious_on_rails_test.rb
63
72
  files:
64
73
  - Rakefile
74
+ - app/controllers/validates_controller.rb
75
+ - config/routes.rb
76
+ - generators/validatious/templates/XMLHttpRequest.js
65
77
  - generators/validatious/templates/initializer.rb
78
+ - generators/validatious/templates/v2.config.js
79
+ - generators/validatious/templates/v2.rails.js
66
80
  - generators/validatious/templates/v2.standalone.full.min.js
67
- - generators/validatious/templates/validatious.config.js
68
81
  - generators/validatious/validatious_generator.rb
69
82
  - lib/validatious-on-rails.rb
83
+ - lib/validatious-on-rails/controller.rb
70
84
  - lib/validatious-on-rails/helpers.rb
71
85
  - lib/validatious-on-rails/model_validations.rb
72
86
  - lib/validatious-on-rails/rails.rb
@@ -81,6 +95,7 @@ files:
81
95
  - lib/validatious-on-rails/validatious/validators/exclusion_validator.rb
82
96
  - lib/validatious-on-rails/validatious/validators/format_validator.rb
83
97
  - lib/validatious-on-rails/validatious/validators/inclusion_validator.rb
98
+ - lib/validatious-on-rails/validatious/validators/invalid_validator.rb
84
99
  - lib/validatious-on-rails/validatious/validators/length/is_validator.rb
85
100
  - lib/validatious-on-rails/validatious/validators/length/maximum_validator.rb
86
101
  - lib/validatious-on-rails/validatious/validators/length/minimum_validator.rb
@@ -93,8 +108,11 @@ files:
93
108
  - lib/validatious-on-rails/validatious/validators/numericality/odd_validator.rb
94
109
  - lib/validatious-on-rails/validatious/validators/numericality/only_integer_validator.rb
95
110
  - lib/validatious-on-rails/validatious/validators/presence_validator.rb
111
+ - lib/validatious-on-rails/validatious/validators/remote_client_validator.rb
112
+ - lib/validatious-on-rails/validatious/validators/uniqueness_validator.rb
96
113
  - rails/init.rb
97
114
  - test/test_helper.rb
115
+ - test/validatious_on_rails/controller_test.rb
98
116
  - test/validatious_on_rails/helpers_test.rb
99
117
  - test/validatious_on_rails/model_validations_test.rb
100
118
  - test/validatious_on_rails/rails/action_view_helpers_test.rb
@@ -130,6 +148,7 @@ specification_version: 3
130
148
  summary: Rails plugin that maps model validations to class names on form elements to integrate with Validatious.
131
149
  test_files:
132
150
  - test/test_helper.rb
151
+ - test/validatious_on_rails/controller_test.rb
133
152
  - test/validatious_on_rails/helpers_test.rb
134
153
  - test/validatious_on_rails/model_validations_test.rb
135
154
  - test/validatious_on_rails/rails/action_view_helpers_test.rb