grimen-validatious_on_rails 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,15 @@
1
+ Validatious on Rails
2
+ ####################
3
+
4
+ Official URL:
5
+ github.com/cjohansen/juicer/tree/master
6
+
7
+ Original Author:
8
+ Christian Johansen
9
+ www.cjohansen.no
10
+
11
+ Validatious client side validation framework:
12
+ www.validatious.org
13
+
14
+ Released under the MIT license. No Support. No Warranty.
15
+ Copyright (c) 2008 Christian Johansen
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+
6
+ NAME = "validatious_on_rails"
7
+ SUMMARY = %Q{Rails plugin that maps model validations to class names on form elements to integrate with Validatious.}
8
+ HOMEPAGE = "http://github.com/grimen/#{NAME}"
9
+ AUTHORS = ["Christian Johansen", "Jonas Grimfelt"]
10
+ EMAIL = "christian@cjohansen.no"
11
+ SUPPORT_FILES = %w(README)
12
+
13
+ begin
14
+ gem 'technicalpickles-jeweler', '>= 1.2.1'
15
+ require 'jeweler'
16
+ Jeweler::Tasks.new do |gemspec|
17
+ gemspec.name = NAME
18
+ gemspec.summary = SUMMARY
19
+ gemspec.description = SUMMARY
20
+ gemspec.homepage = HOMEPAGE
21
+ gemspec.authors = AUTHORS
22
+ gemspec.email = EMAIL
23
+
24
+ gemspec.require_paths = %w{lib}
25
+ gemspec.files = SUPPORT_FILES << %w(Rakefile) <<
26
+ Dir.glob(File.join('{generators,lib,test,rails}', '**', '*').to_s).reject { |v| v =~ /\.log/i }
27
+ gemspec.executables = %w()
28
+ gemspec.extra_rdoc_files = SUPPORT_FILES
29
+ end
30
+ rescue LoadError
31
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
32
+ end
33
+
34
+ desc %Q{Default: Run unit tests for "#{NAME}".}
35
+ task :default => :test
36
+
37
+ desc %Q{Run unit tests for "#{NAME}".}
38
+ Rake::TestTask.new(:test) do |test|
39
+ test.libs << %w(lib test)
40
+ test.pattern = File.join('test', '**', '*_test.rb')
41
+ test.verbose = true
42
+ end
43
+
44
+ desc %Q{Generate documentation for "#{NAME}".}
45
+ Rake::RDocTask.new(:rdoc) do |rdoc|
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = NAME
48
+ rdoc.options << '--line-numbers' << '--inline-source' << '--charset=UTF-8'
49
+ rdoc.rdoc_files.include(SUPPORT_FILES)
50
+ rdoc.rdoc_files.include(File.join('lib', '**', '*.rb'))
51
+ end
@@ -0,0 +1,7 @@
1
+ /**
2
+ * TERMS OF USE - Validatious 2.0
3
+ * Open source under the BSD License.
4
+ * Copyright 2008 Christian Johansen.
5
+ * All rights reserved.
6
+ */
7
+ var addDOMLoadEvent=(function(){var F=[],A,E,C,B,D,G=function(){C=true;clearInterval(A);while(B=F.shift()){B()}if(E){E.onreadystatechange=""}};return function(H){if(C){return H()}if(!F[0]){if(document.addEventListener){document.addEventListener("DOMContentLoaded",G,false)}if(/WebKit/i.test(navigator.userAgent)){A=setInterval(function(){if(/loaded|complete/.test(document.readyState)){G()}},10)}D=window.onload;window.onload=function(){G();if(D){D()}}}F.push(H)}})();var Base=function(){};Base.extend=function(B,E){var F=Base.prototype.extend;Base._prototyping=true;var D=new this;F.call(D,B);delete Base._prototyping;var C=D.constructor;var A=D.constructor=function(){if(!Base._prototyping){if(this._constructing||this.constructor==A){this._constructing=true;C.apply(this,arguments);delete this._constructing}else{if(arguments[0]!=null){return(arguments[0].extend||F).call(arguments[0],D)}}}};A.ancestor=this;A.extend=this.extend;A.forEach=this.forEach;A.implement=this.implement;A.prototype=D;A.toString=this.toString;A.valueOf=function(G){return(G=="object")?A:C.valueOf()};F.call(A,E);if(typeof A.init=="function"){A.init()}return A};Base.prototype={extend:function(B,H){if(arguments.length>1){var E=this[B];if(E&&(typeof H=="function")&&(!E.valueOf||E.valueOf()!=H.valueOf())&&/\bbase\b/.test(H)){var A=H.valueOf();H=function(){var K=this.base||Base.prototype.base;this.base=E;var J=A.apply(this,arguments);this.base=K;return J};H.valueOf=function(J){return(J=="object")?H:A};H.toString=Base.toString}this[B]=H}else{if(B){var G=Base.prototype.extend;if(!Base._prototyping&&typeof this!="function"){G=this.extend||G}var D={toSource:null};var F=["constructor","toString","valueOf"];var C=Base._prototyping?0:1;while(I=F[C++]){if(B[I]!=D[I]){G.call(this,I,B[I])}}for(var I in B){if(!D[I]){G.call(this,I,B[I])}}}}return this},base:function(){}};Base=Base.extend({constructor:function(){this.extend(arguments[0])}},{ancestor:Object,version:"1.1",forEach:function(A,D,C){for(var B in A){if(this.prototype[B]===undefined){D.call(C,A[B],B,A)}}},implement:function(){for(var A=0;A<arguments.length;A++){if(typeof arguments[A]=="function"){arguments[A](this.prototype)}else{this.prototype.extend(arguments[A])}}return this},toString:function(){return String(this.valueOf())}});function addEvent(B,D,C){if(B.addEventListener){B.addEventListener(D,C,false)}else{if(!C.$$guid){C.$$guid=addEvent.guid++}if(!B.events){B.events={}}var A=B.events[D];if(!A){A=B.events[D]={};if(B["on"+D]){A[0]=B["on"+D]}}A[C.$$guid]=C;B["on"+D]=handleEvent}}addEvent.guid=1;function removeEvent(A,C,B){if(A.removeEventListener){A.removeEventListener(C,B,false)}else{if(A.events&&A.events[C]){delete A.events[C][B.$$guid]}}}function handleEvent(D){var C=true;D=D||fixEvent(((this.ownerDocument||this.document||this).parentWindow||window).event);var A=this.events[D.type];for(var B in A){this.$$handleEvent=A[B];if(this.$$handleEvent(D)===false){C=false}}return C}function fixEvent(A){A.preventDefault=fixEvent.preventDefault;A.stopPropagation=fixEvent.stopPropagation;return A}fixEvent.preventDefault=function(){this.returnValue=false};fixEvent.stopPropagation=function(){this.cancelBubble=true};if(typeof v2==="undefined"||v2===null){v2={}}v2.empty=function empty(A){return typeof A=="undefined"||A===null||A===""};v2.array=function array(C){var A=[];if(C&&typeof C.item==="function"){for(var B=0;B<C.length;B++){A[B]=C[B]}C=A}return v2.empty(C)?[]:(typeof C.shift=="undefined"?[C]:C)};v2.Object={extend:function(C,A,B){B=typeof B==="undefined"?false:B;for(var D in A){if(B&&typeof C[D]!=="undefined"){continue}if(A.hasOwnProperty(D)&&typeof A[D]!=="undefined"){C[D]=A[D]}}return C}};v2.Object.extend(String.prototype,{strip:function(){return this.replace(/^\s+|\s+$/,"")}});v2.Object.extend(Array.prototype,{indexOf:function(C,A){for(var B=0;B<this.length;B++){if(this[B]===C){return B}}return -1}});v2.$=function(A,C){if(typeof A=="string"){A=document.getElementById(A)}C=typeof C=="undefined"?true:C;if(A===null||typeof A.hide!="undefined"||!C){return A}for(var B in v2.Element){if(v2.Element.hasOwnProperty(B)){(function(){var D=B;var E={};E[D]=function(){var F=[A];for(var G=0;G<arguments.length;G++){F.push(arguments[G])}return v2.Element[D].apply(v2.Element,F)};v2.Object.extend(A,E,true)})()}}return A};v2.$$=function $$(E,N){N=N||document;if(document.querySelectorAll){v2.$$=function(Q,R){return(R||document).querySelectorAll(Q)};return v2.$$(E,N)}var O=E.split(",");var J,H,F,B,K,D,A,I,C,G,L,M;var P=[];for(J=0;(E=O[J]);J++){B=E.strip().split(/[^a-zA-Z]/)[0]||"*";K=E.replace(/^\./,"_.").split(/\./);C=[];G=[];for(H=1;H<K.length;H++){C.push(K[H].split(/[^a-zA-Z\-_]/)[0])}K=E.replace("][","].[").split(/[\[\]]/);for(H=0;H<K.length-1;H+=2){D=K[H+1].split("=");D[1]=D[1]||true;G.push(D)}A=N.getElementsByTagName(B);elementLoop:for(H=0;(I=A[H]);H++){for(F=0;F<C.length;F++){if(!v2.Element.hasClassName(I,C[F])){continue elementLoop}}for(F=0;F<G.length;F++){L=G[F][0];M=G[F][1];if(I.hasAttribute){if(!I.hasAttribute(L)||(M!==true&&I.getAttribute(L)!==M)){continue elementLoop}}else{L=L==="for"?"htmlFor":L;if(typeof I[L]==="undefined"||(M!==true&&I[L]!==M)){continue elementLoop}}}if(P.indexOf(I)<0){P.push(I)}}}return P};v2.Element={observe:function(B,C,A){addEvent(B,C,A)},computedStyle:function(A,C){var B="";if(document.defaultView&&document.defaultView.getComputedStyle){B=document.defaultView.getComputedStyle(A,"").getPropertyValue(C)}else{if(A.currentStyle){C=C.replace(/\-(\w)/g,function(D,E){return E.toUpperCase()});B=A.currentStyle[C]}}return B},visible:function(A){return v2.Element.computedStyle(A,"display")!="none"&&v2.Element.computedStyle(A,"visibility")!="hidden"&&(A.parentNode===null||A.parentNode.nodeType!=1||v2.Element.visible(A.parentNode))},hasClassName:function(B,A){return new RegExp("(^|\\s)"+A+"(\\s|$)").test(B.className)},addClassName:function(B,A){B.className+=v2.Element.hasClassName(B,A)?"":" "+A;B.className=B.className.replace(" "," ").replace(/^\s|\s$/,"");return B},removeClassName:function(B,A){var C=new RegExp("(^|\\s)"+A+"(\\s|$)");B.className=B.className.replace(C," ").replace(" "," ").replace(/^\s|\s$/,"");return B},position:function(A){var B={x:0,y:0};while(A!==null){B.x+=A.offsetLeft;B.y+=A.offsetTop;A=A.offsetParent}return B},scrollTo:function(A){var B=v2.Element.position(A);window.scrollTo(B.x,B.y)},previous:function(A){do{A=A.previousSibling}while(A&&A.nodeType!==1);return A}};v2.Object.extend(Function.prototype,{bind:function(B){var A=this;A.__cc=A.__cc||[];window.__coc=window.__coc||0;if(typeof B.__id=="undefined"){B.__id=window.__coc++}A.__cc[B.__id]=A.__cc[B.__id]||function(){try{return A.apply(B,arguments)}catch(C){}};return A.__cc[B.__id]}});if(typeof addDOMLoadEvent!="undefined"){v2.addDOMLoadEvent=addDOMLoadEvent}v2.CompositeFormItem=Base.extend({type:"generic",constructor:function(){if(v2.empty(this.__validators)){this.__validators=[]}if(v2.empty(this.__errors)){this.__errors=[]}this.__passOnAny=false;this.__message=null;this.parent=null},add:function(A){this.__validators.push(A);A.parent=this},get:function(A){return !v2.empty(A)?this.__validators[A]:this.__validators},validate:function(){this.__errors=[];var A=this.test("validate");if(A){this.__errors=[];this.onSuccess()}else{this.onFailure()}return A},test:function(C){var B,A,D=0;C=C||"test";for(B=0;(A=this.__validators[B]);B++){if(A[C]()){D++}else{this.__errors.push(A)}}return this.passOnAny()&&D>0||!this.passOnAny()&&D===this.__validators.length},getInvalid:function(){return this.__errors.length===0?null:this.__errors},setMessage:function(A){this.__message=A},getMessages:function(){if(!v2.empty(this.__message)){return[this.__message]}var C=[],B,A;for(B=0,A;(A=this.__errors[B]);B++){C=C.concat(A.getMessages())}return C},passOnAny:function(A){if(typeof A!=="undefined"){this.__passOnAny=!!A}return this.__passOnAny},onSuccess:function(){},onFailure:function(){}});v2.InputElement=Base.extend({constructor:function(B,A){this.__name=null;this.__events=v2.empty(A)?["blur"]:v2.array(A);this.__elements=v2.array(B)},monitor:function(D){this.__monitored=true;var C,A,B,E;for(C=0;(B=this.__elements[C]);C++){for(A=0;(E=this.__events[A]);A++){v2.Element.observe(B,E,D)}}},getValue:function(){return this.__elements[0].value},getLabel:function(){var B=this.__elements[0];var A=v2.$$("label[for="+(B.id||B.name)+"]",B.form);return A&&A[0]},getName:function(){if(this.__name){return this.__name}var A=this.getLabel();if(A){return A.title!==""?A.title:A.innerHTML}var B=this.__elements[0];return B.id||B.name},setName:function(A){this.__name=!!A?A:null;return this},getParent:function(){return this.__elements[0].parentNode},getElements:function(){return this.__elements},visible:function(){if(!v2.$(this.getParent()).visible()){return false}for(var A=0,B;(B=this.__elements[A]);A++){if(v2.Element.visible(B)){return true}}return false}},{__fields:{},get:function(B){if(B&&B.constructor===v2.InputElement){return B}var C=v2.$(B),H,G,F,A,D,E;if(!C){A="input$, select$, textarea$";F=v2.$$(A.replace(/\$/g,"[name="+B+"]"));C=F[0]}if(!C){throw new TypeError(B+" does not resolve to an HTML element!")}H=C.name||C.id;if((G=v2.InputElement.__fields[H])){return G}if(C.options){G=new v2.SelectElement(C)}else{if(C.tagName.toLowerCase()==="textarea"){G=new v2.TextareaElement(C)}else{if(C.type&&C.type=="radio"){F=v2.$$("input[type=radio][name="+C.name+"]",C.form);G=new v2.RadioElement(F)}else{if(C.type&&C.type=="checkbox"){D=C.className;E=/\bg_([^\s]*)\b/;F=E.test(D)?v2.$$("input[type=checkbox].g_"+D.match(E)[1],C.form):[C];G=new v2.CheckboxElement(F)}else{G=new v2.InputElement(C)}}}}return(v2.InputElement.__fields[H]=G)}});v2.$f=v2.InputElement.get;v2.RadioElement=v2.InputElement.extend({constructor:function(A){this.base(A,["click","change"])},getValue:function(){for(var B=0,A;(A=this.__elements[B]);B++){if(A.checked){return A.value}}return null},getLabel:function(){var B=this.__elements[0].parentNode;if(B.tagName.toLowerCase()==="li"){return v2.$(B.parentNode).previous()}var A=v2.$(this.__elements[0]).previous();return A||this.base()},getParent:function(){var A=this.__elements[0].parentNode;return A.tagName.toLowerCase()==="li"?A.parentNode.parentNode:A}});v2.SelectElement=v2.InputElement.extend({constructor:function(A){this.base([A],"change")},getValue:function(){var A=this.__elements[0];if(!A.multiple){return A.options[A.selectedIndex].value}var B=[];for(var C=0,D;(D=A.options[C]);C++){if(D.selected){B.push(D.value)}}return B}});v2.TextareaElement=v2.InputElement.extend({});v2.CheckboxElement=v2.RadioElement.extend({getValue:function(){var A=[],B,C;for(B=0,C;(C=this.__elements[B]);B++){if(C.checked){A.push(C.value)}}return A}});v2.Message=Base.extend({constructor:function(B,C,A){this.message=B;this.params=C||[];this.values=A||[]},copy:function(){return new v2.Message(this.message,this.params,this.values)},toString:function(){var C=this.message+"";for(var A=0,B=null;(B=this.params[A]);A++){C=C.replace("${"+B+"}",this.values[A])}return C}});v2.Validator=Base.extend({constructor:function(B,C,D,E,A){this.__name=B;this.__test=C;this.__message=new v2.Message(D||"${field} does not pass "+B+" validator",E);this.__aliases=v2.array(A);this.acceptEmpty=true},test:function(C,E,D){D=typeof D==="undefined"?false:D;var B=C.getValue();var A=(this.acceptEmpty&&B==="")||this.__test(C,B,E);return(A&&!D)||(!A&&D)},getName:function(){return this.__name},getMessage:function(){return this.__message},setMessage:function(A){this.__message.message=A}},{validators:{},add:function(B){if(!B.name||!B.fn){throw new TypeError("Options object should contain name and fn")}B=v2.Object.extend({params:[],aliases:[],acceptEmpty:true},B,false);var F=v2.array(B.params);var D=new v2.Validator(B.name,B.fn,B.message,F,B.aliases);D.acceptEmpty=B.acceptEmpty;var E=v2.array(B.aliases).concat([B.name]);for(var C=0,A;(A=E[C]);C++){v2.Validator.validators[A]=D}return D},reg:function(B,C,F,D,A,E){return v2.Validator.add({name:B,fn:C,message:D,params:F,aliases:A,acceptEmpty:E})},get:function(A){var B;if(A.constructor===v2.Validator){return A}if((B=v2.Validator.validators[A])){return B}return null}});v2.$v=function(A){return v2.Validator.get(A)};v2.$msg=function(){if(arguments.length===2){return v2.Validator.get(arguments[0]).setMessage(arguments[1])}for(var A in arguments[0]){try{v2.Validator.get(A).setMessage(arguments[0][A])}catch(B){}}};v2.Field=v2.CompositeFormItem.extend({validateHidden:false,instant:false,instantWhenValidated:true,type:"field",constructor:function(B,A,C){this.base();this.__monitored=false;this.element=v2.$f(B);this.instant=typeof A!=="undefined"?A:this.instant;this.instantWhenValidated=typeof C!=="undefined"?C:this.instantWhenValidated;this.__monitor(this.instant)},test:function(){if(!this.validateHidden&&!this.element.visible()){return true}return this.base()},validate:function(){this.__monitor(this.instantWhenValidated&&!this.__monitored);return this.base()},addValidator:function(A,E,C){var B=v2.$v(A);if(B===null){throw new Error(A+" is not a valid validator")}if(typeof C!=="undefined"&&C!==null){C=new v2.Message(C,B.getMessage().params)}var D=new v2.FieldValidator(this.element,B,v2.array(E),C);this.add(D);return D},getParent:function(){return this.element.getParent()},__monitor:function(C){if(!C||this.__monitored){return }this.__monitored=true;var A=this.parent&&this.parent.type==="fieldset"?this.parent:this;var B=A.validate.bind(this);this.element.monitor(function(D){B(D)})}});v2.Fieldset=v2.CompositeFormItem.extend({type:"fieldset",constructor:function(A){this.base();this.element=A},getParent:function(){return this.element}});v2.FieldValidator=Base.extend({invert:false,constructor:function(C,A,E,D){this.__field=C;this.__validator=A;this.__params=v2.array(E);this.__message=D||A.__message.copy();var B=this.__message.params;if(B.length<1||B[0]!=="field"){this.__message.params=["field"].concat(B)}this.__message.values=[this.__field.getName()].concat(this.__params)},test:function(){return this.__validator.test(this.__field,this.__params,this.invert)},validate:function(){return this.test()},getInvalid:function(){return !this.test()?this:null},setMessage:function(A){this.__message.message=A},getMessages:function(){return[this.__message.toString()]},add:function(){},remove:function(){},get:function(){},passOnAny:function(){},onSuccess:function(){},onFailure:function(){}});v2.Form=v2.CompositeFormItem.extend({type:"form",constructor:function(A){this.base();this.__form=v2.$(A);this.__form.observe("submit",this.validate.bind(this));this.__buttons=[];this.__activeButton=null},addButton:function(A){this.__buttons.push(A);v2.Element.observe(A,"click",(function(B){this.__activeButton=A}).bind(this))},validate:function(){var D=arguments.length>0?arguments[0]:null;var C=this.__buttons;var A=this.__activeButton;this.__activeButton=null;if(C.length>0&&C.indexOf(A)<0){return true}var B=this.base();if(!B&&D){D.preventDefault();D.returnValue=false}return B}},{forms:{},get:function(C){var B=v2.$(C),A;if(B===null||B.tagName.toLowerCase()!=="form"){throw new ArgumentError("idOrElement should represent a form element")}if(!v2.empty(A=v2.Form.forms[B.id])){return A}return(v2.Form.forms[B.id]=new v2.Form(B))}});(function(){var A=v2.Validator;A.reg("alpha",function(C,B,D){return/^[a-zA-Z\u00A1-\uFFFF]*$/.test(B)});A.reg("alphanum",function(C,B,D){return/^([a-zA-Z\u00A1-\uFFFF0-9])*$/.test(B)});A.reg("confirmation-of",function(C,B,D){return B===v2.$f(D[0]).getValue()},"field-id","${field} should be an exact match",null,false);A.reg("email",function(C,B,D){return/^[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(B)});A.reg("max-length",function(C,B,D){return B.length<D[0]},"max");A.reg("max-val",function(C,B,D){return B<=D[0]},"max");A.reg("min-length",function(C,B,D){return B.length>=D[0]},"min");A.reg("min-val",function(C,B,D){return B>=D[0]},"min");A.reg("numeric",function(C,B,D){return/^[0-9]*(\.[0-9]+)?$/.test(B)});A.reg("required",function(C,B,D){return !v2.empty(B)&&!(typeof B.length!=="undefined"&&B.length===0)},null,null,"not-empty",false);A.reg("url",function(C,B,D){return/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i.test(B)});A.reg("word",function(C,B,D){return/^([a-zA-Z\u00A1-\uFFFF0-9_\-\s\t])*$/.test(B)})})();v2.$msg({alpha:"${field} should only contain letters",alphanum:"${field} should only contain letters and numbers","car-regnum-nor":"${field} should be a valid norwegian auto registration number","confirmation-of":"${field} should be a confirmation of ${field-id}",email:"${field} should be a valid email address","max-length":"${field} should be no more than ${max} characters long","max-val":"${field} should be no bigger than ${min}","min-length":"${field} should be atleast ${min} characters long","min-val":"${field} should be atleast ${min}",numeric:"${field} should only contain numbers","phone-nor":"${field} should be a valid norwegian phone number",required:"${field} is required","ssn-nor":"${field} should be a valid norwegian social security number",url:"${field} should be a valid URL",word:"${field} should only contain letters, numbers and punctuation"});v2.ErrorReporting={displayErrors:-1,positionErrorsAbove:true,failureClass:"error",successClass:"",messagesClass:"messages",onFailure:function(){if(this.parent&&this.parent.type==="fieldset"){return }var I=this.onSuccess();var F="",C,G,A,J;var K=[];var B=this.getMessages();I.addClassName(this.failureClass);I.removeClassName(this.successClass);var D=this.displayErrors;var H=this.__errors.length;D=D<0||D>H?H:D;if(D===0){return }var E=document.createElement("ul");E.id=this.__getId();E.className=this.messagesClass;for(C=0;C<D;C++){G=B[C];if(!G||K.indexOf(G.toString())>=0){continue}K.push(G.toString());J=document.createElement("li");J.innerHTML=G.toString();E.appendChild(J)}if(this.positionErrorsAbove){I.insertBefore(E,I.firstChild)}else{I.appendChild(E)}},onSuccess:function(){if(this.parent&&this.parent.type==="fieldset"){return null}var A=v2.$(this.getParent());var B=v2.$(this.__getId());if(B&&A===B.parentNode){A.removeChild(B)}A.removeClassName(this.failureClass);A.addClassName(this.successClass);return A},__getId:function(){var A=this.element.getElements?this.element.getElements()[0]:null;var C=A||this.getParent();var B=C.className;var D=((C.id||C.name||B.replace(this.failureClass,""))+"_"+this.failureClass).replace(" ","_").replace(/_+/,"_");return D}};v2.Object.extend(v2.Field.prototype,v2.ErrorReporting);v2.Object.extend(v2.Fieldset.prototype,v2.ErrorReporting);v2.Object.extend(v2.Form.prototype,{scrollToFirstWhenFail:true,onFailure:function(){if(!this.scrollToFirstWhenFail){return }var B,A,D,C=this.__form;D=C.all||C.getElementsByTagName("*");for(B=0;(A=D[B]);B++){if(v2.Element.hasClassName(A,v2.ErrorReporting.failureClass)){v2.Element.scrollTo(A);return }}}});v2.Object.extend(v2.Validator,{prefix:""});v2.Object.extend(v2.Form,{autoValidateClass:"validate",actionButtonClass:"action"});v2.html={validateAnyClass:"validate_any",validateAllClass:"validate_all",validatorsFromString:function(I){var E=v2.Validator.prefix;var G=new RegExp("^"+E,"");var F,H,B,D,A,C=[];I=I.split(" ");for(F=0;(H=I[F]);F++){B=false;if(!v2.empty(E)&&!G.test(H)){continue}H=H.replace(G,"");if(/^not_/.test(H)){H=H.replace(/^not_/,"");B=true}D=H.split("_");A=D.shift();if(A&&(A=v2.$v(A))){C.push({validator:A,params:D,invert:B})}}return C},applyValidators:function(A,F,D){if(!v2.empty(D)){F.setMessage(D)}for(var C=0,B,E;(B=A[C]);C++){E=F.addValidator(B.validator,B.params);E.invert=B.invert}return F}};v2.html.Form=Base.extend({constructor:function(A){this.form=v2.Form.get(A);this.__parsed={};this.parseElement(A,this.form);this.form.passOnAny(v2.$(A).hasClassName(v2.html.validateAnyClass))},parseElement:function(C,K,E){var A=v2.$$("div, fieldset, input, select, textarea",C);var H,F,B,I,G,D,L,J;this.__parsed[C.id||C.name]=true;E=E||[];for(H=0;(G=A[H]);H++){if(E.length===0&&(/^\s*$/.test(G.className)||this.__parsed[G.id||G.name])){continue}D=G.tagName.toLowerCase();if(D==="input"&&v2.Element.hasClassName(G,v2.Form.actionButtonClass)){this.form.addButton(G);continue}if(D==="div"||D==="fieldset"){this.parseBlock(G,K);continue}J=E.concat(v2.html.validatorsFromString(G.className));if(J.length>0){L=new v2.Field(G);v2.html.applyValidators(J,L,G.title);this.__parsed[G.id||G.name]=true;K.add(L)}}},parseBlock:function(C,E){var D=new v2.Fieldset(C);var B=true;v2.$(C);if(C.hasClassName(v2.html.validateAnyClass)){}else{if(C.hasClassName(v2.html.validateAllClass)){B=false}else{return }}D.passOnAny(B);var A=v2.html.validatorsFromString(C.className);this.parseElement(C,D,A);if(!/^\s*$/.test(C.title)){D.setMessage(C.title)}if(D.get(0)){E.add(D)}}});v2.addDOMLoadEvent(function(){var A=document.getElementsByTagName("form");for(var B=0,C;(C=A[B]);B++){if(v2.Element.hasClassName(C,v2.Form.autoValidateClass)){new v2.html.Form(C)}}});v2.dsl={__validateTemplate:function(A){return function(){var F=arguments[0];var D=F.element||(F.item?F.item.element:null)||null;if(D===null){while(!!F&&!F.element){F=F.get(0)}}var E=new v2.dsl.Form(D.getElements()[0].form);E.item.passOnAny(A);for(var C=0,B;(B=arguments[C]);C++){E.item.add(B.item||B)}return E}},__andOr:function(A){return function(){var D=new v2.dsl.Collection();D.item.passOnAny(A);for(var C=0,B;(B=arguments[C]);C++){D.item.add(B.item)}return D}}};v2.dsl.expose=function(){var A=v2.dsl;v2.Object.extend(window,{validate:A.validate,validateAll:A.validateAll,validateAny:A.validateAny,and:A.and,or:A.or},false)};v2.dsl.validateAll=v2.dsl.validate=v2.dsl.__validateTemplate(false);v2.dsl.validateAny=v2.dsl.__validateTemplate(true);v2.dsl.and=v2.dsl.__andOr(false);v2.dsl.or=v2.dsl.__andOr(true);v2.Object.extend(String.prototype,{is:function(A,C){var B=new v2.dsl.Field(this.toString());return B.addValidator(A,C)}});(function(){var A=String.prototype;A.isA=A.isAn=A.has=A.hasA=A.hasAn=A.is})();v2.dsl.Field=Base.extend({__currentValidator:null,__and:null,constructor:function(A){this.item=new v2.Field(A)},addValidator:function(A,C,B){if(typeof B!=="undefined"){if(this.__and!==null&&this.__and!==B){throw new Error("Field previously set up with "+(this.__and?"AND":"OR")+", unable to shift")}this.__and=B;this.item.passOnAny(!B)}this.__currentValidator=this.item.addValidator(A,C);return this},and:function(A,B){if(!this.__currentValidator){throw new Error("Cannot add more validators when no validators are added yet")}return this.addValidator(A,B,true)},or:function(A,B){if(!!this.__currentValidator){throw new Error("Cannot add more validators when no validators are added yet")}return this.addValidator(A,B,false)},explain:function(A){if(!this.__currentValidator){throw new Error("No active field validator")}this.__currentValidator.setMessage(A);return this},help:function(A){this.item.setMessage(A);return this},withName:function(A){this.item.element.setName(A);return this}});(function(){var A=v2.dsl.Field.prototype;A.orIs=A.orIsA=A.orIsAn=A.orHas=A.orHasA=A.orHasAn=A.or;A.andIs=A.andIsA=A.andIsAn=A.andHas=A.andHasA=A.andHasAn=A.and})();v2.dsl.Collection=Base.extend({constructor:function(){this.item=new v2.CompositeFormItem()},explain:function(A){this.item.setMessage(A)}});v2.dsl.Form=Base.extend({constructor:function(A){this.item=v2.Form.get(A)},on:function(){var B,A;for(B=0;B<arguments.length;B++){A=v2.$(arguments[B]);this.item.addButton(A.tagName.toLowerCase()!=="input"?A.getElementsByTagName("input")[0]:A)}}});
@@ -0,0 +1,83 @@
1
+ // -------------------------------------------
2
+ // VALIDATIOUS 2.0: Configuration
3
+ // -------------------------------------------
4
+ //
5
+ // More: http://validatious.org/learn/references
6
+ //
7
+
8
+ // Auto-validate form with this class.
9
+ //
10
+ // v2.Form.autoValidateClass = 'validate';
11
+
12
+ // Trigger validation on action with this class.
13
+ //
14
+ v2.Form.actionButtonClass = 'commit'; // Formtastic: Use 'commit'
15
+
16
+ // Validate any/all of the validations in a block with this class.
17
+ //
18
+ // Example:
19
+ //
20
+ // <div class="validate_any">
21
+ // ...
22
+ // </div>
23
+ //
24
+ // v2.html.validateAnyClass = 'validate_any';
25
+ // v2.html.validateAnyClass = 'validate_all';
26
+
27
+ // Make generated validation classes namespaced to avoid clashes with other classes.
28
+ //
29
+ // v2.Validator.prefix = 'v2_';
30
+
31
+ // Validate instantly or on submit.
32
+ //
33
+ v2.Field.prototype.instant = true;
34
+ v2.Field.prototype.instantWhenValidated = true;
35
+
36
+ // Validate all hidden fields.
37
+ //
38
+ // v2.Field.prototype.validateHidden = false;
39
+
40
+ // Jump to first invalid field on error.
41
+ //
42
+ v2.Form.prototype.scrollToFirstWhenFail = true;
43
+
44
+ // Maximum number of errors at the same time.
45
+ //
46
+ // * -1, default value, display all messages
47
+ // * 0, display no messages, only append class names on failing elements
48
+ // * n, where n is any positive integer, display no more than this many messages
49
+ //
50
+ // v2.Field.prototype.displayErrors = 1;
51
+
52
+ // Position of errors.
53
+ //
54
+ v2.Field.prototype.positionErrorsAbove = false;
55
+ v2.Fieldset.prototype.positionErrorsAbove = false;
56
+
57
+ // Error classes.
58
+ //
59
+ // Example:
60
+ //
61
+ // <fieldset
62
+ // <div class="field error"
63
+ // <label for="name">Name</label
64
+ // <input type="text" name="name" id="name" class="required word"
65
+ // <ul class="errors"
66
+ // <li>Name is required</li
67
+ // </ul
68
+ // </div
69
+ // <div class="field error"
70
+ // <label for="email">E-mail</label
71
+ // <input type="text" name="email" id="email" class="email" value="name@"
72
+ // <ul class="errors"
73
+ // <li>E-mail should be a valid email address</li
74
+ // </ul
75
+ // </div
76
+ // </fieldset>
77
+ //
78
+ v2.Fieldset.prototype.messagesClass = 'errors'; // Formtastic: Use 'errors'
79
+ v2.Fieldset.prototype.failureClass = 'error'; // Formtastic: Use 'error'
80
+ v2.Fieldset.prototype.successClass = '';
81
+ v2.Field.prototype.messagesClass = 'errors'; // Formtastic: Use 'errors'
82
+ v2.Field.prototype.failureClass = 'error'; // Formtastic: Use 'error'
83
+ v2.Field.prototype.successClass = '';
@@ -0,0 +1,10 @@
1
+ class ValidatiousGenerator < Rails::Generator::Base
2
+
3
+ def manifest
4
+ record do |m|
5
+ m.template 'v2.standalone.full.min.js', File.join('public', 'javascripts', 'v2.standalone.full.min.js')
6
+ m.template 'validatious_config.js', File.join('public', 'javascripts', 'validatious_config.js')
7
+ end
8
+ end
9
+
10
+ end
@@ -0,0 +1,66 @@
1
+ #
2
+ # Tap into the built-in form helpers to add validatious class names from
3
+ # model validations.
4
+ #
5
+ module ActionView
6
+ module Helpers
7
+ module FormHelper
8
+
9
+ #
10
+ # Add validation class names to: text-fields.
11
+ #
12
+ def text_field_with_validation(object_name, method, options = {})
13
+ options = Validatious::RailsValidation.options_for(object_name, method, options)
14
+ text_field_without_validation(object_name, method, options)
15
+ end
16
+ alias_method_chain :text_field, :validation
17
+
18
+ #
19
+ # Add validation class names to: password-fields.
20
+ #
21
+ def password_field_with_validation(object_name, method, options = {})
22
+ options = Validatious::RailsValidation.options_for(object_name, method, options)
23
+ password_field_without_validation(object_name, method, options)
24
+ end
25
+ alias_method_chain :password_field, :validation
26
+
27
+ #
28
+ # Add validation class names to: text-areas.
29
+ #
30
+ def text_area_with_validation(object_name, method, options = {})
31
+ options = Validatious::RailsValidation.options_for(object_name, method, options)
32
+ text_area_without_validation(object_name, method, options)
33
+ end
34
+ alias_method_chain :text_area, :validation
35
+
36
+ #
37
+ # Add validation class names to: check-boxes.
38
+ #
39
+ def check_box_with_validation(object_name, method, options = {}, checked_value = '1', unchecked_value = '0')
40
+ options = Validatious::RailsValidation.options_for(object_name, method, options)
41
+ check_box_without_validation(object_name, method, options)
42
+ end
43
+ alias_method_chain :check_box, :validation
44
+
45
+ #
46
+ # Add validation class names to: radio-buttons.
47
+ #
48
+ def radio_button_with_validation(object_name, method, tag_value, options = {})
49
+ options = Validatious::RailsValidation.options_for(object_name, method, options)
50
+ radio_button_without_validation(object_name, method, tag_value, options)
51
+ end
52
+ alias_method_chain :radio_button, :validation
53
+
54
+ #
55
+ # Adds the title attribute to label tags when there is no title
56
+ # set, and the label text is provided. The title is set to object_name.humanize
57
+ #
58
+ def label_with_title(object_name, method, text = nil, options = {})
59
+ options[:title] ||= method.to_s.humanize unless text.nil?
60
+ label_without_title(object_name, method, text, options)
61
+ end
62
+ alias_method_chain :label, :title
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,167 @@
1
+ begin
2
+ require 'validation_reflection'
3
+ rescue LoadError
4
+ gem 'redinger-validation_reflection', '>= 0.3.2'
5
+ require 'validation_reflection'
6
+ end
7
+
8
+ #
9
+ # Force this, as it seems ValidationReflection don't do this correctly. =S
10
+ #
11
+ ActiveRecord::Base.class_eval do
12
+ include ::ActiveRecordExtensions::ValidationReflection
13
+ ::ActiveRecordExtensions::ValidationReflection.load_config
14
+ ::ActiveRecordExtensions::ValidationReflection.install(self)
15
+ end
16
+
17
+ #
18
+ # Validatious-Rails validation translator.
19
+ #
20
+ module Validatious
21
+ class RailsValidation
22
+ class << self
23
+
24
+ # Reference: http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html
25
+
26
+ #
27
+ # Generates form field helper options for a specified object-attribute to
28
+ # reflect on it's validations.
29
+ #
30
+ # Input may be an ActiveRecord class, a class name (string), or an object
31
+ # name along with a method/field.
32
+ #
33
+ def options_for(object_name, method, options = {})
34
+ validation = self.from_active_record(object_name, method)
35
+
36
+ # Loop validation and add/append pairs to options.
37
+ validation.each_pair do |attr, value|
38
+ options[attr] ||= ''
39
+ options[attr] << value
40
+
41
+ # Shake out duplicates.
42
+ options[attr] = options[attr].split.uniq.join(' ').strip
43
+ end
44
+ options
45
+ end
46
+
47
+ #
48
+ # Groks rails validations, and is able to convert a rails validation to
49
+ # a Validatious 2.0 compatible class string.
50
+ #
51
+ # Input may be an ActiveRecord class, a class name (string), or an object
52
+ # name along with a method/field.
53
+ #
54
+ # Returns a string that will be recognized by Validatious as a class name in
55
+ # form markup.
56
+ #
57
+ def from_active_record(object_or_class, method)
58
+ klass = object_or_class.to_s.classify.constantize
59
+ options = {:class => ''}
60
+ validation_classes = []
61
+
62
+ # Iterate thorugh the validations for the current class,
63
+ # and collect validation options.
64
+ klass.reflect_on_validations_for(method).each do |validation|
65
+ validation_options = self.send(validation.macro.to_s.sub(/^validates_/, ''), validation)
66
+ validation_classes << validation_options[:class]
67
+ end
68
+ options[:class] = [options[:class], validation_classes].flatten.compact.join(' ')
69
+ options
70
+ end
71
+
72
+ #
73
+ # Resolve validation from validates_acceptance_of.
74
+ #
75
+ # Note: acceptance_of <=> presence_of (for Validatious)
76
+ #
77
+ def acceptance_of(validation)
78
+ {:class => 'required'}
79
+ end
80
+
81
+ #
82
+ # Resolve validation from validates_associated.
83
+ #
84
+ def associated(validation)
85
+ {:class => ''}
86
+ end
87
+
88
+ #
89
+ # TODO: Resolve validation from validates_confirmation_of.
90
+ #
91
+ # Note: Should be added to "#{field}_confirmation" instead of "#{field}", i.e. non-standard approach.
92
+ #
93
+ def confirmation_of(validation)
94
+ {:class => ''}
95
+ end
96
+
97
+ #
98
+ # TODO: Resolve validation from validates_exclusion_of.
99
+ #
100
+ def exclusion_of(validation)
101
+ {:class => ''}
102
+ end
103
+
104
+ #
105
+ # TODO: Resolve validation from validates_format_of.
106
+ #
107
+ # Note: Should be implemented using "Custom validators" - generated and attached to the form on render page.
108
+ #
109
+ def format_of(validation)
110
+ # format_expression = validation.options[:with]
111
+ # Old: {:class => validation.options.key?(:name) ? validation.options[:name] : ''}
112
+ {:class => ''}
113
+ end
114
+
115
+ #
116
+ # TODO: Resolve validation from validates_inclusion_of.
117
+ #
118
+ def inclusion_of(validation)
119
+ {:class => ''}
120
+ end
121
+
122
+ #
123
+ # Resolve validation from validates_length_of.
124
+ #
125
+ def length_of(validation)
126
+ range = validation.options[:in] || validation.options[:within]
127
+ min, max = nil, nil
128
+ min, max = range.min, range.max if range
129
+ min ||= validation.options[:minimum] || validation.options[:is]
130
+ max ||= validation.options[:maximum] || validation.options[:is]
131
+
132
+ class_name = [
133
+ ("min-length_#{min}" unless min.nil?),
134
+ ("max-length_#{max}" unless max.nil?)
135
+ ].compact.join(' ')
136
+
137
+ {:class => class_name}
138
+ end
139
+
140
+ #
141
+ # Resolve validation from validates_numericality_of.
142
+ #
143
+ def numericality_of(validation)
144
+ {:class => 'numeric'}
145
+ end
146
+
147
+ #
148
+ # Resolve validation from validates_presence_of.
149
+ #
150
+ # Note: acceptance_of <=> presence_of (for Validatious)
151
+ #
152
+ def presence_of(validation)
153
+ {:class => 'required'}
154
+ end
155
+
156
+ #
157
+ # TODO: Resolve validation from validates_uniqueness_of.
158
+ #
159
+ # Note: A bit tricky on the client-side - especially with many records.
160
+ #
161
+ def uniqueness_of(validation)
162
+ {:class => ''}
163
+ end
164
+
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,9 @@
1
+ require File.join(File.dirname(__FILE__), *%w[validatious form_helper])
2
+ require File.join(File.dirname(__FILE__), *%w[validatious rails_validation])
3
+
4
+ #
5
+ # Validatious module.
6
+ #
7
+ module Validatious
8
+
9
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), *%w(.. lib validatious)))
@@ -0,0 +1,56 @@
1
+ #
2
+ # This file loads up the in-memory database needed to run the tests, and adds a few
3
+ # convenience methods.
4
+ #
5
+
6
+ begin
7
+ require File.expand_path(File.join(File.dirname(__FILE__), *%w(.. .. .. .. config environment)))
8
+ rescue LoadError
9
+ require 'rubygems'
10
+
11
+ gem 'test-unit', '1.2.3'
12
+ gem 'activerecord', '>= 1.2.3'
13
+ gem 'actionpack', '>= 1.2.3'
14
+
15
+ require 'test/unit'
16
+ require 'active_record'
17
+ require 'action_controller'
18
+ end
19
+
20
+ begin
21
+ require 'acts_as_fu'
22
+ rescue LoadError
23
+ gem 'nakajima-acts_as_fu', '>= 0.0.5'
24
+ require 'acts_as_fu'
25
+ end
26
+
27
+ require 'validatious'
28
+
29
+ build_model :bogus_items do
30
+ string :url
31
+ string :name
32
+ string :email
33
+ string :num
34
+ string :num2
35
+ string :num3
36
+
37
+ text :body
38
+ boolean :signed
39
+
40
+ validates_presence_of :name, :body
41
+ validates_acceptance_of :signed
42
+ validates_format_of :url,
43
+ :with => /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i,
44
+ :name => 'url'
45
+ end
46
+
47
+ #
48
+ # ValidationReflection seems to expect RAILS_ROOT to be defined, but it's not
49
+ # if it's tested outside of a Rails project. So, just set it to something random.
50
+ #
51
+ RAILS_ROOT = File.join(File.dirname(__FILE__)) unless defined?(RAILS_ROOT)
52
+
53
+ #
54
+ # Log file for testing only.
55
+ #
56
+ ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), 'debug.log'))
@@ -0,0 +1,61 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2
+
3
+ module Test::Unit::Assertions
4
+
5
+ #
6
+ # Assert that a piece of HTML includes the class name.
7
+ #
8
+ def assert_has_class(class_name, html, message = nil)
9
+ classes = /class="([^"]*)"/.match(html)[1].split(" ")
10
+ full_message = build_message(message, "<?>\nexpected to include class(es) <?>.\n", html, class_name)
11
+
12
+ assert_block(full_message) do
13
+ class_name.split(" ").all? { |cname| classes.include?(cname) }
14
+ end
15
+ end
16
+
17
+ end
18
+
19
+ class FormHelperTest < Test::Unit::TestCase
20
+
21
+ include ActionView::Helpers::FormHelper
22
+
23
+ def test_required_text_field
24
+ assert_has_class "required", text_field(:bogus_item, :name)
25
+ assert_has_class "required text", text_field(:bogus_item, :name, :class => "text")
26
+ end
27
+
28
+ def test_required_password_field
29
+ assert_has_class "required", password_field(:bogus_item, :name)
30
+ assert_has_class "required text", password_field(:bogus_item, :name, :class => "text")
31
+ end
32
+
33
+ def test_required_text_area
34
+ assert_has_class "required", text_field(:bogus_item, :body)
35
+ assert_has_class "required text", text_field(:bogus_item, :body, :class => "text")
36
+ end
37
+
38
+ def test_required_check_box # a.k.a. "acceptance required"
39
+ assert_has_class "required", text_field(:bogus_item, :signed)
40
+ assert_has_class "required boolean", text_field(:bogus_item, :signed, :class => "boolean")
41
+ end
42
+
43
+ def test_required_radio_button
44
+ # TODO
45
+ end
46
+
47
+ def test_normal_label
48
+ assert_equal "<label for=\"bogus_item_name\">Name</label>", label(:bogus_item, :name)
49
+ end
50
+
51
+ def test_label_with_title
52
+ assert_equal "<label for=\"bogus_item_name\" title=\"craaazy\">Name</label>",
53
+ label(:bogus_item, :name, nil, :title => "craaazy")
54
+ end
55
+
56
+ def test_label_without_title
57
+ assert_equal "<label for=\"bogus_item_name\" title=\"Name\">Your name</label>",
58
+ label(:bogus_item, :name, "Your name")
59
+ end
60
+
61
+ end
@@ -0,0 +1,87 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2
+
3
+ class RailsValidationTest < Test::Unit::TestCase
4
+
5
+ include ActionView::Helpers::FormHelper
6
+
7
+ def test_acceptance_of
8
+ validation = Validatious::RailsValidation.presence_of(validation(:validates_acceptance_of))
9
+ assert_equal 'required', validation[:class]
10
+ end
11
+
12
+ def test_associated
13
+ # TODO: not implemented
14
+ end
15
+
16
+ def test_confirmation_of
17
+ # TODO: not implemented
18
+ end
19
+
20
+ def test_exclusion_of
21
+ # TODO: not implemented
22
+ end
23
+
24
+ def test_format_of
25
+ # pattern = /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i
26
+ # validation = Validatious::RailsValidation.format_of(validation(:validates_format_of, :with => pattern, :name => "email"))
27
+ # assert_equal 'email', validation[:class]
28
+ # TODO: Not fully supported really, should
29
+ end
30
+
31
+ def test_inclusion_of
32
+ # TODO: not implemented
33
+ end
34
+
35
+ def test_length_of_with_in
36
+ validation = Validatious::RailsValidation.length_of(validation(:validates_length_of, :in => 1..10))
37
+ assert_equal 'min-length_1 max-length_10', validation[:class]
38
+
39
+ validation = Validatious::RailsValidation.length_of(validation(:validates_length_of, :in => 1...10))
40
+ assert_equal 'min-length_1 max-length_9', validation[:class]
41
+ end
42
+
43
+ def test_length_of_with_within
44
+ validation = Validatious::RailsValidation.length_of(validation(:validates_length_of, :within => 1..10))
45
+ assert_equal 'min-length_1 max-length_10', validation[:class]
46
+
47
+ validation = Validatious::RailsValidation.length_of(validation(:validates_length_of, :within => 1...10))
48
+ assert_equal 'min-length_1 max-length_9', validation[:class]
49
+ end
50
+
51
+ def test_length_of_with_minimum
52
+ validation = Validatious::RailsValidation.length_of(validation(:validates_length_of, :minimum => 1))
53
+ assert_equal 'min-length_1', validation[:class]
54
+ end
55
+
56
+ def test_length_of_with_maximum
57
+ validation = Validatious::RailsValidation.length_of(validation(:validates_length_of, :maximum => 1))
58
+ assert_equal 'max-length_1', validation[:class]
59
+ end
60
+
61
+ def test_length_of_with_min_and_max
62
+ validation = Validatious::RailsValidation.length_of(validation(:validates_length_of, :minimum => 1, :maximum => 3))
63
+ assert_equal 'min-length_1 max-length_3', validation[:class]
64
+ end
65
+
66
+ def test_numericality_of
67
+ validation = Validatious::RailsValidation.numericality_of(validation(:validates_numericality_of))
68
+ assert_equal 'numeric', validation[:class]
69
+ end
70
+
71
+ def test_presence_of
72
+ validation = Validatious::RailsValidation.presence_of(validation(:validates_presence_of))
73
+ assert_equal 'required', validation[:class]
74
+ end
75
+
76
+ def test_uniqueness_of
77
+ # TODO: not implemented
78
+ end
79
+
80
+ #
81
+ # Simulate a validation
82
+ #
83
+ def validation(macro, options = {})
84
+ ActiveRecord::Reflection::MacroReflection.new(macro, :name, options, nil)
85
+ end
86
+
87
+ end
@@ -0,0 +1,5 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ # class ValidatiousTest < Test::Unit::TestCase
4
+ #
5
+ # end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grimen-validatious_on_rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Christian Johansen
8
+ - Jonas Grimfelt
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-09-26 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: Rails plugin that maps model validations to class names on form elements to integrate with Validatious.
18
+ email: christian@cjohansen.no
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files:
24
+ - README
25
+ - Rakefile
26
+ - generators/validatious/templates/v2.standalone.full.min.js
27
+ - generators/validatious/templates/validatious_config.js
28
+ - generators/validatious/validatious_generator.rb
29
+ - lib/validatious.rb
30
+ - lib/validatious/form_helper.rb
31
+ - lib/validatious/rails_validation.rb
32
+ - rails/init.rb
33
+ - test/test_helper.rb
34
+ - test/validatious/form_helper_test.rb
35
+ - test/validatious/rails_validation_test.rb
36
+ - test/validatious_test.rb
37
+ files:
38
+ - README
39
+ - Rakefile
40
+ - generators/validatious/templates/v2.standalone.full.min.js
41
+ - generators/validatious/templates/validatious_config.js
42
+ - generators/validatious/validatious_generator.rb
43
+ - lib/validatious.rb
44
+ - lib/validatious/form_helper.rb
45
+ - lib/validatious/rails_validation.rb
46
+ - rails/init.rb
47
+ - test/test_helper.rb
48
+ - test/validatious/form_helper_test.rb
49
+ - test/validatious/rails_validation_test.rb
50
+ - test/validatious_test.rb
51
+ has_rdoc: false
52
+ homepage: http://github.com/grimen/validatious_on_rails
53
+ licenses:
54
+ post_install_message:
55
+ rdoc_options:
56
+ - --charset=UTF-8
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ requirements: []
72
+
73
+ rubyforge_project:
74
+ rubygems_version: 1.3.5
75
+ signing_key:
76
+ specification_version: 3
77
+ summary: Rails plugin that maps model validations to class names on form elements to integrate with Validatious.
78
+ test_files:
79
+ - test/test_helper.rb
80
+ - test/validatious/form_helper_test.rb
81
+ - test/validatious/rails_validation_test.rb
82
+ - test/validatious_test.rb