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/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