grimen-validatious-on-rails 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile ADDED
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'rake/testtask'
5
+ require 'rake/rdoctask'
6
+
7
+ NAME = "validatious-on-rails"
8
+ SUMMARY = %Q{Rails plugin that maps model validations to class names on form elements to integrate with Validatious.}
9
+ HOMEPAGE = "http://github.com/grimen/#{NAME}"
10
+ AUTHORS = ["Christian Johansen", "Jonas Grimfelt"]
11
+ EMAIL = "christian@cjohansen.no"
12
+ SUPPORT_FILES = %w(README)
13
+
14
+ begin
15
+ gem 'technicalpickles-jeweler', '>= 1.2.1'
16
+ require 'jeweler'
17
+ Jeweler::Tasks.new do |gemspec|
18
+ gemspec.name = NAME
19
+ gemspec.summary = SUMMARY
20
+ gemspec.description = SUMMARY
21
+ gemspec.homepage = HOMEPAGE
22
+ gemspec.authors = AUTHORS
23
+ gemspec.email = EMAIL
24
+
25
+ gemspec.require_paths = %w{lib}
26
+ gemspec.files = SUPPORT_FILES << %w(Rakefile) <<
27
+ Dir.glob(File.join('{generators,lib,test,rails}', '**', '*').to_s).reject { |v| v =~ /\.log/i }
28
+ gemspec.executables = %w()
29
+ gemspec.extra_rdoc_files = SUPPORT_FILES
30
+ end
31
+ rescue LoadError
32
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
33
+ end
34
+
35
+ desc %Q{Default: Run unit tests for "#{NAME}".}
36
+ task :default => :test
37
+
38
+ desc %Q{Run unit tests for "#{NAME}".}
39
+ Rake::TestTask.new(:test) do |test|
40
+ test.libs << %w(lib test)
41
+ test.pattern = File.join('test', '**', '*_test.rb')
42
+ test.verbose = true
43
+ end
44
+
45
+ desc %Q{Generate documentation for "#{NAME}".}
46
+ Rake::RDocTask.new(:rdoc) do |rdoc|
47
+ rdoc.rdoc_dir = 'rdoc'
48
+ rdoc.title = NAME
49
+ rdoc.options << '--line-numbers' << '--inline-source' << '--charset=UTF-8'
50
+ rdoc.rdoc_files.include(SUPPORT_FILES)
51
+ rdoc.rdoc_files.include(File.join('lib', '**', '*.rb'))
52
+ 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,12 @@
1
+ # encoding: utf-8
2
+
3
+ class ValidatiousGenerator < Rails::Generator::Base
4
+
5
+ def manifest
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
+ end
10
+ end
11
+
12
+ end
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+ require File.join(File.dirname(__FILE__), *%w[validatious form_helper])
3
+ require File.join(File.dirname(__FILE__), *%w[validatious rails_validation])
4
+
5
+ #
6
+ # Validatious module.
7
+ #
8
+ module Validatious
9
+
10
+ end
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Tap into the built-in form helpers to add validatious class names from
4
+ # model validations.
5
+ #
6
+ module ActionView
7
+ module Helpers
8
+ module FormHelper
9
+
10
+ #
11
+ # Add validation class names to: text-fields.
12
+ #
13
+ def text_field_with_validation(object_name, method, options = {})
14
+ options = Validatious::RailsValidation.options_for(object_name, method, options)
15
+ text_field_without_validation(object_name, method, options)
16
+ end
17
+ alias_method_chain :text_field, :validation
18
+
19
+ #
20
+ # Add validation class names to: password-fields.
21
+ #
22
+ def password_field_with_validation(object_name, method, options = {})
23
+ options = Validatious::RailsValidation.options_for(object_name, method, options)
24
+ password_field_without_validation(object_name, method, options)
25
+ end
26
+ alias_method_chain :password_field, :validation
27
+
28
+ #
29
+ # Add validation class names to: text-areas.
30
+ #
31
+ def text_area_with_validation(object_name, method, options = {})
32
+ options = Validatious::RailsValidation.options_for(object_name, method, options)
33
+ text_area_without_validation(object_name, method, options)
34
+ end
35
+ alias_method_chain :text_area, :validation
36
+
37
+ #
38
+ # Add validation class names to: check-boxes.
39
+ #
40
+ def check_box_with_validation(object_name, method, options = {}, checked_value = '1', unchecked_value = '0')
41
+ options = Validatious::RailsValidation.options_for(object_name, method, options)
42
+ check_box_without_validation(object_name, method, options)
43
+ end
44
+ alias_method_chain :check_box, :validation
45
+
46
+ #
47
+ # Add validation class names to: radio-buttons.
48
+ #
49
+ def radio_button_with_validation(object_name, method, tag_value, options = {})
50
+ options = Validatious::RailsValidation.options_for(object_name, method, options)
51
+ radio_button_without_validation(object_name, method, tag_value, options)
52
+ end
53
+ alias_method_chain :radio_button, :validation
54
+
55
+ #
56
+ # Adds the title attribute to label tags when there is no title
57
+ # set, and the label text is provided. The title is set to object_name.humanize
58
+ #
59
+ def label_with_title(object_name, method, text = nil, options = {})
60
+ options[:title] ||= method.to_s.humanize unless text.nil?
61
+ label_without_title(object_name, method, text, options)
62
+ end
63
+ alias_method_chain :label, :title
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,168 @@
1
+ # encoding: utf-8
2
+ begin
3
+ require 'validation_reflection'
4
+ rescue LoadError
5
+ gem 'redinger-validation_reflection', '>= 0.3.2'
6
+ require 'validation_reflection'
7
+ end
8
+
9
+ #
10
+ # Force this, as it seems ValidationReflection don't do this correctly. =S
11
+ #
12
+ ActiveRecord::Base.class_eval do
13
+ include ::ActiveRecordExtensions::ValidationReflection
14
+ ::ActiveRecordExtensions::ValidationReflection.load_config
15
+ ::ActiveRecordExtensions::ValidationReflection.install(self)
16
+ end
17
+
18
+ #
19
+ # Validatious-Rails validation translator.
20
+ #
21
+ module Validatious
22
+ class RailsValidation
23
+ class << self
24
+
25
+ # Reference: http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html
26
+
27
+ #
28
+ # Generates form field helper options for a specified object-attribute to
29
+ # reflect on it's validations.
30
+ #
31
+ # Input may be an ActiveRecord class, a class name (string), or an object
32
+ # name along with a method/field.
33
+ #
34
+ def options_for(object_name, method, options = {})
35
+ validation = self.from_active_record(object_name, method)
36
+
37
+ # Loop validation and add/append pairs to options.
38
+ validation.each_pair do |attr, value|
39
+ options[attr] ||= ''
40
+ options[attr] << value
41
+
42
+ # Shake out duplicates.
43
+ options[attr] = options[attr].split.uniq.join(' ').strip
44
+ end
45
+ options
46
+ end
47
+
48
+ #
49
+ # Groks rails validations, and is able to convert a rails validation to
50
+ # a Validatious 2.0 compatible class string.
51
+ #
52
+ # Input may be an ActiveRecord class, a class name (string), or an object
53
+ # name along with a method/field.
54
+ #
55
+ # Returns a string that will be recognized by Validatious as a class name in
56
+ # form markup.
57
+ #
58
+ def from_active_record(object_or_class, method)
59
+ klass = object_or_class.to_s.classify.constantize
60
+ options = {:class => ''}
61
+ validation_classes = []
62
+
63
+ # Iterate thorugh the validations for the current class,
64
+ # and collect validation options.
65
+ klass.reflect_on_validations_for(method).each do |validation|
66
+ validation_options = self.send(validation.macro.to_s.sub(/^validates_/, ''), validation)
67
+ validation_classes << validation_options[:class]
68
+ end
69
+ options[:class] = [options[:class], validation_classes].flatten.compact.join(' ')
70
+ options
71
+ end
72
+
73
+ #
74
+ # Resolve validation from validates_acceptance_of.
75
+ #
76
+ # Note: acceptance_of <=> presence_of (for Validatious)
77
+ #
78
+ def acceptance_of(validation)
79
+ {:class => 'required'}
80
+ end
81
+
82
+ #
83
+ # Resolve validation from validates_associated.
84
+ #
85
+ def associated(validation)
86
+ {:class => ''}
87
+ end
88
+
89
+ #
90
+ # TODO: Resolve validation from validates_confirmation_of.
91
+ #
92
+ # Note: Should be added to "#{field}_confirmation" instead of "#{field}", i.e. non-standard approach.
93
+ #
94
+ def confirmation_of(validation)
95
+ {:class => ''}
96
+ end
97
+
98
+ #
99
+ # TODO: Resolve validation from validates_exclusion_of.
100
+ #
101
+ def exclusion_of(validation)
102
+ {:class => ''}
103
+ end
104
+
105
+ #
106
+ # TODO: Resolve validation from validates_format_of.
107
+ #
108
+ # Note: Should be implemented using "Custom validators" - generated and attached to the form on render page.
109
+ #
110
+ def format_of(validation)
111
+ # format_expression = validation.options[:with]
112
+ # Old: {:class => validation.options.key?(:name) ? validation.options[:name] : ''}
113
+ {:class => ''}
114
+ end
115
+
116
+ #
117
+ # TODO: Resolve validation from validates_inclusion_of.
118
+ #
119
+ def inclusion_of(validation)
120
+ {:class => ''}
121
+ end
122
+
123
+ #
124
+ # Resolve validation from validates_length_of.
125
+ #
126
+ def length_of(validation)
127
+ range = validation.options[:in] || validation.options[:within]
128
+ min, max = nil, nil
129
+ min, max = range.min, range.max if range
130
+ min ||= validation.options[:minimum] || validation.options[:is]
131
+ max ||= validation.options[:maximum] || validation.options[:is]
132
+
133
+ class_name = [
134
+ ("min-length_#{min}" unless min.nil?),
135
+ ("max-length_#{max}" unless max.nil?)
136
+ ].compact.join(' ')
137
+
138
+ {:class => class_name}
139
+ end
140
+
141
+ #
142
+ # Resolve validation from validates_numericality_of.
143
+ #
144
+ def numericality_of(validation)
145
+ {:class => 'numeric'}
146
+ end
147
+
148
+ #
149
+ # Resolve validation from validates_presence_of.
150
+ #
151
+ # Note: acceptance_of <=> presence_of (for Validatious)
152
+ #
153
+ def presence_of(validation)
154
+ {:class => 'required'}
155
+ end
156
+
157
+ #
158
+ # TODO: Resolve validation from validates_uniqueness_of.
159
+ #
160
+ # Note: A bit tricky on the client-side - especially with many records.
161
+ #
162
+ def uniqueness_of(validation)
163
+ {:class => ''}
164
+ end
165
+
166
+ end
167
+ end
168
+ end
data/rails/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.join(File.dirname(__FILE__), *%w(.. lib validatious)))
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file loads up the in-memory database needed to run the tests, and adds a few
4
+ # convenience methods.
5
+ #
6
+
7
+ begin
8
+ require File.expand_path(File.join(File.dirname(__FILE__), *%w(.. .. .. .. config environment)))
9
+ rescue LoadError
10
+ require 'rubygems'
11
+
12
+ gem 'test-unit', '1.2.3'
13
+ gem 'activerecord', '>= 1.2.3'
14
+ gem 'actionpack', '>= 1.2.3'
15
+ gem 'sqlite3-ruby', '>= 1.2.0'
16
+
17
+ require 'test/unit'
18
+ require 'active_record'
19
+ require 'action_controller'
20
+ require 'action_controller'
21
+ require 'sqlite3'
22
+ end
23
+
24
+ begin
25
+ require 'acts_as_fu'
26
+ rescue LoadError
27
+ gem 'nakajima-acts_as_fu', '>= 0.0.5'
28
+ require 'acts_as_fu'
29
+ end
30
+
31
+ require 'validatious'
32
+
33
+ build_model :bogus_items do
34
+ string :url
35
+ string :name
36
+ string :email
37
+ string :num
38
+ string :num2
39
+ string :num3
40
+
41
+ text :body
42
+ boolean :signed
43
+
44
+ validates_presence_of :name, :body
45
+ validates_acceptance_of :signed
46
+ validates_format_of :url,
47
+ :with => /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i,
48
+ :name => 'url'
49
+ end
50
+
51
+ #
52
+ # ValidationReflection seems to expect RAILS_ROOT to be defined, but it's not
53
+ # if it's tested outside of a Rails project. So, just set it to something random.
54
+ #
55
+ RAILS_ROOT = File.join(File.dirname(__FILE__)) unless defined?(RAILS_ROOT)
56
+
57
+ #
58
+ # Log file for testing only.
59
+ #
60
+ ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), 'debug.log'))
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
3
+
4
+ module Test::Unit::Assertions
5
+
6
+ #
7
+ # Assert that a piece of HTML includes the class name.
8
+ #
9
+ def assert_has_class(class_name, html, message = nil)
10
+ classes = /class="([^"]*)"/.match(html)[1].split(" ")
11
+ full_message = build_message(message, "<?>\nexpected to include class(es) <?>.\n", html, class_name)
12
+
13
+ assert_block(full_message) do
14
+ class_name.split(" ").all? { |cname| classes.include?(cname) }
15
+ end
16
+ end
17
+
18
+ end
19
+
20
+ class FormHelperTest < Test::Unit::TestCase
21
+
22
+ include ActionView::Helpers::FormHelper
23
+
24
+ def test_required_text_field
25
+ assert_has_class "required", text_field(:bogus_item, :name)
26
+ assert_has_class "required text", text_field(:bogus_item, :name, :class => "text")
27
+ end
28
+
29
+ def test_required_password_field
30
+ assert_has_class "required", password_field(:bogus_item, :name)
31
+ assert_has_class "required text", password_field(:bogus_item, :name, :class => "text")
32
+ end
33
+
34
+ def test_required_text_area
35
+ assert_has_class "required", text_field(:bogus_item, :body)
36
+ assert_has_class "required text", text_field(:bogus_item, :body, :class => "text")
37
+ end
38
+
39
+ def test_required_check_box # a.k.a. "acceptance required"
40
+ assert_has_class "required", text_field(:bogus_item, :signed)
41
+ assert_has_class "required boolean", text_field(:bogus_item, :signed, :class => "boolean")
42
+ end
43
+
44
+ def test_required_radio_button
45
+ # TODO
46
+ end
47
+
48
+ def test_normal_label
49
+ assert_equal "<label for=\"bogus_item_name\">Name</label>", label(:bogus_item, :name)
50
+ end
51
+
52
+ def test_label_with_title
53
+ assert_equal "<label for=\"bogus_item_name\" title=\"craaazy\">Name</label>",
54
+ label(:bogus_item, :name, nil, :title => "craaazy")
55
+ end
56
+
57
+ def test_label_without_title
58
+ assert_equal "<label for=\"bogus_item_name\" title=\"Name\">Your name</label>",
59
+ label(:bogus_item, :name, "Your name")
60
+ end
61
+
62
+ end
@@ -0,0 +1,88 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
3
+
4
+ class RailsValidationTest < Test::Unit::TestCase
5
+
6
+ include ActionView::Helpers::FormHelper
7
+
8
+ def test_acceptance_of
9
+ validation = Validatious::RailsValidation.presence_of(validation(:validates_acceptance_of))
10
+ assert_equal 'required', validation[:class]
11
+ end
12
+
13
+ def test_associated
14
+ # TODO: not implemented
15
+ end
16
+
17
+ def test_confirmation_of
18
+ # TODO: not implemented
19
+ end
20
+
21
+ def test_exclusion_of
22
+ # TODO: not implemented
23
+ end
24
+
25
+ def test_format_of
26
+ # pattern = /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i
27
+ # validation = Validatious::RailsValidation.format_of(validation(:validates_format_of, :with => pattern, :name => "email"))
28
+ # assert_equal 'email', validation[:class]
29
+ # TODO: Not fully supported really, should
30
+ end
31
+
32
+ def test_inclusion_of
33
+ # TODO: not implemented
34
+ end
35
+
36
+ def test_length_of_with_in
37
+ validation = Validatious::RailsValidation.length_of(validation(:validates_length_of, :in => 1..10))
38
+ assert_equal 'min-length_1 max-length_10', validation[:class]
39
+
40
+ validation = Validatious::RailsValidation.length_of(validation(:validates_length_of, :in => 1...10))
41
+ assert_equal 'min-length_1 max-length_9', validation[:class]
42
+ end
43
+
44
+ def test_length_of_with_within
45
+ validation = Validatious::RailsValidation.length_of(validation(:validates_length_of, :within => 1..10))
46
+ assert_equal 'min-length_1 max-length_10', validation[:class]
47
+
48
+ validation = Validatious::RailsValidation.length_of(validation(:validates_length_of, :within => 1...10))
49
+ assert_equal 'min-length_1 max-length_9', validation[:class]
50
+ end
51
+
52
+ def test_length_of_with_minimum
53
+ validation = Validatious::RailsValidation.length_of(validation(:validates_length_of, :minimum => 1))
54
+ assert_equal 'min-length_1', validation[:class]
55
+ end
56
+
57
+ def test_length_of_with_maximum
58
+ validation = Validatious::RailsValidation.length_of(validation(:validates_length_of, :maximum => 1))
59
+ assert_equal 'max-length_1', validation[:class]
60
+ end
61
+
62
+ def test_length_of_with_min_and_max
63
+ validation = Validatious::RailsValidation.length_of(validation(:validates_length_of, :minimum => 1, :maximum => 3))
64
+ assert_equal 'min-length_1 max-length_3', validation[:class]
65
+ end
66
+
67
+ def test_numericality_of
68
+ validation = Validatious::RailsValidation.numericality_of(validation(:validates_numericality_of))
69
+ assert_equal 'numeric', validation[:class]
70
+ end
71
+
72
+ def test_presence_of
73
+ validation = Validatious::RailsValidation.presence_of(validation(:validates_presence_of))
74
+ assert_equal 'required', validation[:class]
75
+ end
76
+
77
+ def test_uniqueness_of
78
+ # TODO: not implemented
79
+ end
80
+
81
+ #
82
+ # Simulate a validation
83
+ #
84
+ def validation(macro, options = {})
85
+ ActiveRecord::Reflection::MacroReflection.new(macro, :name, options, nil)
86
+ end
87
+
88
+ end
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+ require File.join(File.dirname(__FILE__), 'test_helper')
3
+
4
+ # class ValidatiousTest < Test::Unit::TestCase
5
+ #
6
+ # end
metadata ADDED
@@ -0,0 +1,80 @@
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-27 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
+ - Rakefile
25
+ - generators/validatious/templates/v2.standalone.full.min.js
26
+ - generators/validatious/templates/validatious.config.js
27
+ - generators/validatious/validatious_generator.rb
28
+ - lib/validatious.rb
29
+ - lib/validatious/form_helper.rb
30
+ - lib/validatious/rails_validation.rb
31
+ - rails/init.rb
32
+ - test/test_helper.rb
33
+ - test/validatious/form_helper_test.rb
34
+ - test/validatious/rails_validation_test.rb
35
+ - test/validatious_test.rb
36
+ files:
37
+ - Rakefile
38
+ - generators/validatious/templates/v2.standalone.full.min.js
39
+ - generators/validatious/templates/validatious.config.js
40
+ - generators/validatious/validatious_generator.rb
41
+ - lib/validatious.rb
42
+ - lib/validatious/form_helper.rb
43
+ - lib/validatious/rails_validation.rb
44
+ - rails/init.rb
45
+ - test/test_helper.rb
46
+ - test/validatious/form_helper_test.rb
47
+ - test/validatious/rails_validation_test.rb
48
+ - test/validatious_test.rb
49
+ has_rdoc: false
50
+ homepage: http://github.com/grimen/validatious-on-rails
51
+ licenses:
52
+ post_install_message:
53
+ rdoc_options:
54
+ - --charset=UTF-8
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ requirements: []
70
+
71
+ rubyforge_project:
72
+ rubygems_version: 1.3.5
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: Rails plugin that maps model validations to class names on form elements to integrate with Validatious.
76
+ test_files:
77
+ - test/test_helper.rb
78
+ - test/validatious/form_helper_test.rb
79
+ - test/validatious/rails_validation_test.rb
80
+ - test/validatious_test.rb