diff options
Diffstat (limited to 'railties')
133 files changed, 2983 insertions, 2045 deletions
diff --git a/railties/lib/generators/erb/mailer/mailer_generator.rb b/railties/lib/generators/erb/mailer/mailer_generator.rb index 4ec2f4c9f4..408c942cef 100644 --- a/railties/lib/generators/erb/mailer/mailer_generator.rb +++ b/railties/lib/generators/erb/mailer/mailer_generator.rb @@ -12,7 +12,7 @@ module Erb def create_view_files actions.each do |action| @action, @path = action, File.join(file_path, action) - template "view.erb", File.join("app/views", "#{@path}.erb") + template "view.text.erb", File.join("app/views", "#{@path}.text.erb") end end end diff --git a/railties/lib/generators/erb/mailer/templates/view.erb b/railties/lib/generators/erb/mailer/templates/view.erb deleted file mode 100644 index fcce7bd805..0000000000 --- a/railties/lib/generators/erb/mailer/templates/view.erb +++ /dev/null @@ -1,3 +0,0 @@ -<%= class_name %>#<%= @action %> - -Find me in app/views/<%= @path %> diff --git a/railties/lib/generators/erb/mailer/templates/view.text.erb b/railties/lib/generators/erb/mailer/templates/view.text.erb new file mode 100644 index 0000000000..6d597256a6 --- /dev/null +++ b/railties/lib/generators/erb/mailer/templates/view.text.erb @@ -0,0 +1,3 @@ +<%= class_name %>#<%= @action %> + +<%%= @greeting %>, find me in app/views/<%= @path %> diff --git a/railties/lib/generators/rails/app/templates/Rakefile b/railties/lib/generators/rails/app/templates/Rakefile index c19ad0e945..9cb2046439 100755 --- a/railties/lib/generators/rails/app/templates/Rakefile +++ b/railties/lib/generators/rails/app/templates/Rakefile @@ -7,4 +7,4 @@ require 'rake' require 'rake/testtask' require 'rake/rdoctask' -<%= app_const %>.load_tasks +Rails::Application.load_tasks diff --git a/railties/lib/generators/rails/app/templates/config/boot.rb b/railties/lib/generators/rails/app/templates/config/boot.rb index 466e1e50ec..7fc1aeaeb8 100644 --- a/railties/lib/generators/rails/app/templates/config/boot.rb +++ b/railties/lib/generators/rails/app/templates/config/boot.rb @@ -19,18 +19,22 @@ require 'rails/all' # To pick the frameworks you want, remove 'require "rails/all"' # and list the framework railties that you want: # +# require "active_support/railtie" # require "active_model/railtie" # require "active_record/railtie" # require "action_controller/railtie" # require "action_view/railtie" # require "action_mailer/railtie" # require "active_resource/railtie" +# require "rails/test_unit/railtie" <% else -%> # Pick the frameworks you want: +# require "active_model/railtie" # require "active_record/railtie" -require "active_model/railtie" +require "active_support/railtie" require "action_controller/railtie" require "action_view/railtie" require "action_mailer/railtie" require "active_resource/railtie" +require "rails/test_unit/railtie" <% end -%>
\ No newline at end of file diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/jquery-1.4.1.min.js b/railties/lib/generators/rails/app/templates/public/javascripts/jquery-1.4.1.min.js new file mode 100644 index 0000000000..0c7294c90a --- /dev/null +++ b/railties/lib/generators/rails/app/templates/public/javascripts/jquery-1.4.1.min.js @@ -0,0 +1,152 @@ +/*! + * jQuery JavaScript Library v1.4.1 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Jan 25 19:43:33 2010 -0500 + */ +(function(z,v){function la(){if(!c.isReady){try{r.documentElement.doScroll("left")}catch(a){setTimeout(la,1);return}c.ready()}}function Ma(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,i){var j=a.length;if(typeof b==="object"){for(var n in b)X(a,n,b[n],f,e,d);return a}if(d!==v){f=!i&&f&&c.isFunction(d);for(n=0;n<j;n++)e(a[n],b,f?d.call(a[n],n,e(a[n],b)):d,i);return a}return j? +e(a[0],b):null}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function ma(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function na(a){var b,d=[],f=[],e=arguments,i,j,n,o,m,s,x=c.extend({},c.data(this,"events").live);if(!(a.button&&a.type==="click")){for(o in x){j=x[o];if(j.live===a.type||j.altLive&&c.inArray(a.type,j.altLive)>-1){i=j.data;i.beforeFilter&&i.beforeFilter[a.type]&&!i.beforeFilter[a.type](a)||f.push(j.selector)}else delete x[o]}i=c(a.target).closest(f, +a.currentTarget);m=0;for(s=i.length;m<s;m++)for(o in x){j=x[o];n=i[m].elem;f=null;if(i[m].selector===j.selector){if(j.live==="mouseenter"||j.live==="mouseleave")f=c(a.relatedTarget).closest(j.selector)[0];if(!f||f!==n)d.push({elem:n,fn:j})}}m=0;for(s=d.length;m<s;m++){i=d[m];a.currentTarget=i.elem;a.data=i.fn.data;if(i.fn.apply(i.elem,e)===false){b=false;break}}return b}}function oa(a,b){return"live."+(a?a+".":"")+b.replace(/\./g,"`").replace(/ /g,"&")}function pa(a){return!a||!a.parentNode||a.parentNode.nodeType=== +11}function qa(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var i in f)for(var j in f[i])c.event.add(this,i,f[i][j],f[i][j].data)}}})}function ra(a,b,d){var f,e,i;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&a[0].indexOf("<option")<0&&(c.support.checkClone||!sa.test(a[0]))){e=true;if(i=c.fragments[a[0]])if(i!==1)f=i}if(!f){b=b&&b[0]?b[0].ownerDocument||b[0]:r;f=b.createDocumentFragment(); +c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=i?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(ta.concat.apply([],ta.slice(0,b)),function(){d[this]=a});return d}function ua(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Na=z.jQuery,Oa=z.$,r=z.document,S,Pa=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Qa=/^.[^:#\[\.,]*$/,Ra=/\S/,Sa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Ta=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,O=navigator.userAgent, +va=false,P=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,Q=Array.prototype.slice,wa=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(typeof a==="string")if((d=Pa.exec(a))&&(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:r;if(a=Ta.exec(a))if(c.isPlainObject(b)){a=[r.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=ra([d[1]], +[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}}else{if(b=r.getElementById(d[2])){if(b.id!==d[2])return S.find(a);this.length=1;this[0]=b}this.context=r;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=r;a=r.getElementsByTagName(a)}else return!b||b.jquery?(b||S).find(a):c(b).find(a);else if(c.isFunction(a))return S.ready(a);if(a.selector!==v){this.selector=a.selector;this.context=a.context}return c.isArray(a)?this.setArray(a):c.makeArray(a, +this)},selector:"",jquery:"1.4.1",length:0,size:function(){return this.length},toArray:function(){return Q.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){a=c(a||null);a.prevObject=this;a.context=this.context;if(b==="find")a.selector=this.selector+(this.selector?" ":"")+d;else if(b)a.selector=this.selector+"."+b+"("+d+")";return a},setArray:function(a){this.length=0;ba.apply(this,a);return this},each:function(a,b){return c.each(this, +a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(r,c);else P&&P.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(Q.apply(this,arguments),"slice",Q.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice}; +c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,i,j,n;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(i in e){j=a[i];n=e[i];if(a!==n)if(f&&n&&(c.isPlainObject(n)||c.isArray(n))){j=j&&(c.isPlainObject(j)||c.isArray(j))?j:c.isArray(n)?[]:{};a[i]=c.extend(f,j,n)}else if(n!==v)a[i]=n}return a};c.extend({noConflict:function(a){z.$= +Oa;if(a)z.jQuery=Na;return c},isReady:false,ready:function(){if(!c.isReady){if(!r.body)return setTimeout(c.ready,13);c.isReady=true;if(P){for(var a,b=0;a=P[b++];)a.call(r,c);P=null}c.fn.triggerHandler&&c(r).triggerHandler("ready")}},bindReady:function(){if(!va){va=true;if(r.readyState==="complete")return c.ready();if(r.addEventListener){r.addEventListener("DOMContentLoaded",L,false);z.addEventListener("load",c.ready,false)}else if(r.attachEvent){r.attachEvent("onreadystatechange",L);z.attachEvent("onload", +c.ready);var a=false;try{a=z.frameElement==null}catch(b){}r.documentElement.doScroll&&a&&la()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,"isPrototypeOf"))return false;var b;for(b in a);return b===v||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false; +return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return z.JSON&&z.JSON.parse?z.JSON.parse(a):(new Function("return "+a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Ra.test(a)){var b=r.getElementsByTagName("head")[0]|| +r.documentElement,d=r.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(r.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,i=a.length,j=i===v||c.isFunction(a);if(d)if(j)for(f in a){if(b.apply(a[f],d)===false)break}else for(;e<i;){if(b.apply(a[e++],d)===false)break}else if(j)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d= +a[0];e<i&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Sa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!== +v;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,i=a.length;e<i;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,i=0,j=a.length;i<j;i++){e=b(a[i],i,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=v}else if(b&&!c.isFunction(b)){d=b;b=v}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b}, +uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});O=c.uaMatch(O);if(O.browser){c.browser[O.browser]=true;c.browser.version=O.version}if(c.browser.webkit)c.browser.safari=true;if(wa)c.inArray=function(a,b){return wa.call(b,a)};S=c(r);if(r.addEventListener)L=function(){r.removeEventListener("DOMContentLoaded", +L,false);c.ready()};else if(r.attachEvent)L=function(){if(r.readyState==="complete"){r.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=r.documentElement,b=r.createElement("script"),d=r.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var e=d.getElementsByTagName("*"),i=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!i)){c.support= +{leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(i.getAttribute("style")),hrefNormalized:i.getAttribute("href")==="/a",opacity:/^0.55$/.test(i.style.opacity),cssFloat:!!i.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:r.createElement("select").appendChild(r.createElement("option")).selected,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null}; +b.type="text/javascript";try{b.appendChild(r.createTextNode("window."+f+"=1;"))}catch(j){}a.insertBefore(b,a.firstChild);if(z[f]){c.support.scriptEval=true;delete z[f]}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function n(){c.support.noCloneEvent=false;d.detachEvent("onclick",n)});d.cloneNode(true).fireEvent("onclick")}d=r.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=r.createDocumentFragment();a.appendChild(d.firstChild); +c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var n=r.createElement("div");n.style.width=n.style.paddingLeft="1px";r.body.appendChild(n);c.boxModel=c.support.boxModel=n.offsetWidth===2;r.body.removeChild(n).style.display="none"});a=function(n){var o=r.createElement("div");n="on"+n;var m=n in o;if(!m){o.setAttribute(n,"return;");m=typeof o[n]==="function"}return m};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=i=null}})();c.props= +{"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ua=0,xa={},Va={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==z?xa:a;var f=a[G],e=c.cache;if(!b&&!f)return null;f||(f=++Ua);if(typeof b==="object"){a[G]=f;e=e[f]=c.extend(true, +{},b)}else e=e[f]?e[f]:typeof d==="undefined"?Va:(e[f]={});if(d!==v){a[G]=f;e[b]=d}return typeof b==="string"?e[b]:e}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==z?xa:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{try{delete a[G]}catch(i){a.removeAttribute&&a.removeAttribute(G)}delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this, +a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===v){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===v&&this.length)f=c.data(this[0],a);return f===v&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d); +return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===v)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]|| +a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var ya=/[\n\t]/g,ca=/\s+/,Wa=/\r/g,Xa=/href|src|style/,Ya=/(button|input)/i,Za=/(button|input|object|select|textarea)/i,$a=/^(a|area)$/i,za=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(o){var m= +c(this);m.addClass(a.call(this,o,m.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className)for(var i=" "+e.className+" ",j=0,n=b.length;j<n;j++){if(i.indexOf(" "+b[j]+" ")<0)e.className+=" "+b[j]}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(o){var m=c(this);m.removeClass(a.call(this,o,m.attr("class")))});if(a&&typeof a==="string"||a===v)for(var b=(a||"").split(ca), +d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var i=(" "+e.className+" ").replace(ya," "),j=0,n=b.length;j<n;j++)i=i.replace(" "+b[j]+" "," ");e.className=i.substring(1,i.length-1)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var i=c(this);i.toggleClass(a.call(this,e,i.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,i=0,j=c(this),n=b,o= +a.split(ca);e=o[i++];){n=f?n:!j.hasClass(e);j[n?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(ya," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===v){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value|| +{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var i=b?d:0;for(d=b?d+1:e.length;i<d;i++){var j=e[i];if(j.selected){a=c(j).val();if(b)return a;f.push(a)}}return f}if(za.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Wa,"")}return v}var n=c.isFunction(a);return this.each(function(o){var m=c(this),s=a;if(this.nodeType===1){if(n)s=a.call(this,o,m.val()); +if(typeof s==="number")s+="";if(c.isArray(s)&&za.test(this.type))this.checked=c.inArray(m.val(),s)>=0;else if(c.nodeName(this,"select")){var x=c.makeArray(s);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),x)>=0});if(!x.length)this.selectedIndex=-1}else this.value=s}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return v;if(f&&b in c.attrFn)return c(a)[b](d); +f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==v;b=f&&c.props[b]||b;if(a.nodeType===1){var i=Xa.test(b);if(b in a&&f&&!i){if(e){b==="type"&&Ya.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:Za.test(a.nodeName)||$a.test(a.nodeName)&&a.href?0:v;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText= +""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&i?a.getAttribute(b,2):a.getAttribute(b);return a===null?v:a}return c.style(a,b,d)}});var ab=function(a){return a.replace(/[^\w\s\.\|`]/g,function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==z&&!a.frameElement)a=z;if(!d.guid)d.guid=c.guid++;if(f!==v){d=c.proxy(d);d.data=f}var e=c.data(a,"events")||c.data(a,"events",{}),i=c.data(a,"handle"),j;if(!i){j= +function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(j.elem,arguments):v};i=c.data(a,"handle",j)}if(i){i.elem=a;b=b.split(/\s+/);for(var n,o=0;n=b[o++];){var m=n.split(".");n=m.shift();if(o>1){d=c.proxy(d);if(f!==v)d.data=f}d.type=m.slice(0).sort().join(".");var s=e[n],x=this.special[n]||{};if(!s){s=e[n]={};if(!x.setup||x.setup.call(a,f,m,d)===false)if(a.addEventListener)a.addEventListener(n,i,false);else a.attachEvent&&a.attachEvent("on"+n,i)}if(x.add)if((m=x.add.call(a, +d,f,m,s))&&c.isFunction(m)){m.guid=m.guid||d.guid;m.data=m.data||d.data;m.type=m.type||d.type;d=m}s[d.guid]=d;this.global[n]=true}a=null}}},global:{},remove:function(a,b,d){if(!(a.nodeType===3||a.nodeType===8)){var f=c.data(a,"events"),e,i,j;if(f){if(b===v||typeof b==="string"&&b.charAt(0)===".")for(i in f)this.remove(a,i+(b||""));else{if(b.type){d=b.handler;b=b.type}b=b.split(/\s+/);for(var n=0;i=b[n++];){var o=i.split(".");i=o.shift();var m=!o.length,s=c.map(o.slice(0).sort(),ab);s=new RegExp("(^|\\.)"+ +s.join("\\.(?:.*\\.)?")+"(\\.|$)");var x=this.special[i]||{};if(f[i]){if(d){j=f[i][d.guid];delete f[i][d.guid]}else for(var A in f[i])if(m||s.test(f[i][A].type))delete f[i][A];x.remove&&x.remove.call(a,o,j);for(e in f[i])break;if(!e){if(!x.teardown||x.teardown.call(a,o)===false)if(a.removeEventListener)a.removeEventListener(i,c.data(a,"handle"),false);else a.detachEvent&&a.detachEvent("on"+i,c.data(a,"handle"));e=null;delete f[i]}}}}for(e in f)break;if(!e){if(A=c.data(a,"handle"))A.elem=null;c.removeData(a, +"events");c.removeData(a,"handle")}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();this.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return v;a.result=v;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d, +b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(i){}if(!a.isPropagationStopped()&&f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){d=a.target;var j;if(!(c.nodeName(d,"a")&&e==="click")&&!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()])){try{if(d[e]){if(j=d["on"+e])d["on"+e]=null;this.triggered=true;d[e]()}}catch(n){}if(j)d["on"+e]=j;this.triggered=false}}},handle:function(a){var b, +d;a=arguments[0]=c.event.fix(a||z.event);a.currentTarget=this;d=a.type.split(".");a.type=d.shift();b=!d.length&&!a.exclusive;var f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)");d=(c.data(this,"events")||{})[a.type];for(var e in d){var i=d[e];if(b||f.test(i.type)){a.handler=i;a.data=i.data;i=i.apply(this,arguments);if(i!==v){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), +fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||r;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=r.documentElement;d=r.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop|| +d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==v)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a,b){c.extend(a,b||{});a.guid+=b.selector+b.live;b.liveProxy=a;c.event.add(this,b.live,na,b)},remove:function(a){if(a.length){var b= +0,d=new RegExp("(^|\\.)"+a[0]+"(\\.|$)");c.each(c.data(this,"events").live||{},function(){d.test(this.type)&&b++});b<1&&c.event.remove(this,a[0],na)}},special:{}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true}; +c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y};var Aa=function(a){for(var b= +a.relatedTarget;b&&b!==this;)try{b=b.parentNode}catch(d){break}if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}},Ba=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ba:Aa,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ba:Aa)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(a,b,d){if(this.nodeName.toLowerCase()!== +"form"){c.event.add(this,"click.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="submit"||i==="image")&&c(e).closest("form").length)return ma("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="text"||i==="password")&&c(e).closest("form").length&&f.keyCode===13)return ma("submit",this,arguments)})}else return false},remove:function(a,b){c.event.remove(this,"click.specialSubmit"+(b?"."+b.guid:""));c.event.remove(this, +"keypress.specialSubmit"+(b?"."+b.guid:""))}};if(!c.support.changeBubbles){var da=/textarea|input|select/i;function Ca(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d}function ea(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Ca(d);if(a.type!=="focusout"|| +d.type!=="radio")c.data(d,"_change_data",e);if(!(f===v||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}}c.event.special.change={filters:{focusout:ea,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return ea.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return ea.call(this,a)},beforeactivate:function(a){a= +a.target;a.nodeName.toLowerCase()==="input"&&a.type==="radio"&&c.data(a,"_change_data",Ca(a))}},setup:function(a,b,d){for(var f in T)c.event.add(this,f+".specialChange."+d.guid,T[f]);return da.test(this.nodeName)},remove:function(a,b){for(var d in T)c.event.remove(this,d+".specialChange"+(b?"."+b.guid:""),T[d]);return da.test(this.nodeName)}};var T=c.event.special.change.filters}r.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this, +f)}c.event.special[b]={setup:function(){this.addEventListener(a,d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var i in d)this[b](i,f,d[i],e);return this}if(c.isFunction(f)){e=f;f=v}var j=b==="one"?c.proxy(e,function(n){c(this).unbind(n,j);return e.apply(this,arguments)}):e;return d==="unload"&&b!=="one"?this.one(d,f,e):this.each(function(){c.event.add(this,d,j,f)})}});c.fn.extend({unbind:function(a, +b){if(typeof a==="object"&&!a.preventDefault){for(var d in a)this.unbind(d,a[d]);return this}return this.each(function(){c.event.remove(this,a,b)})},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+ +a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e){var i,j=0;if(c.isFunction(f)){e=f;f=v}for(d=(d||"").split(/\s+/);(i=d[j++])!=null;){i=i==="focus"?"focusin":i==="blur"?"focusout":i==="hover"?d.push("mouseleave")&&"mouseenter":i;b==="live"?c(this.context).bind(oa(i,this.selector),{data:f,selector:this.selector, +live:i},e):c(this.context).unbind(oa(i,this.selector),e?{guid:e.guid+this.selector+i}:null)}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});z.attachEvent&&!z.addEventListener&&z.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}}); +(function(){function a(g){for(var h="",k,l=0;g[l];l++){k=g[l];if(k.nodeType===3||k.nodeType===4)h+=k.nodeValue;else if(k.nodeType!==8)h+=a(k.childNodes)}return h}function b(g,h,k,l,q,p){q=0;for(var u=l.length;q<u;q++){var t=l[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===k){y=l[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=k;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}l[q]=y}}}function d(g,h,k,l,q,p){q=0;for(var u=l.length;q<u;q++){var t=l[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache=== +k){y=l[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=k;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(o.filter(h,[t]).length>0){y=t;break}}t=t[g]}l[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,i=Object.prototype.toString,j=false,n=true;[0,0].sort(function(){n=false;return 0});var o=function(g,h,k,l){k=k||[];var q=h=h||r;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g|| +typeof g!=="string")return k;for(var p=[],u,t,y,R,H=true,M=w(h),I=g;(f.exec(""),u=f.exec(I))!==null;){I=u[3];p.push(u[1]);if(u[2]){R=u[3];break}}if(p.length>1&&s.exec(g))if(p.length===2&&m.relative[p[0]])t=fa(p[0]+p[1],h);else for(t=m.relative[p[0]]?[h]:o(p.shift(),h);p.length;){g=p.shift();if(m.relative[g])g+=p.shift();t=fa(g,t)}else{if(!l&&p.length>1&&h.nodeType===9&&!M&&m.match.ID.test(p[0])&&!m.match.ID.test(p[p.length-1])){u=o.find(p.shift(),h,M);h=u.expr?o.filter(u.expr,u.set)[0]:u.set[0]}if(h){u= +l?{expr:p.pop(),set:A(l)}:o.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=u.expr?o.filter(u.expr,u.set):u.set;if(p.length>0)y=A(t);else H=false;for(;p.length;){var D=p.pop();u=D;if(m.relative[D])u=p.pop();else D="";if(u==null)u=h;m.relative[D](y,u,M)}}else y=[]}y||(y=t);y||o.error(D||g);if(i.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))k.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&& +y[g].nodeType===1&&k.push(t[g]);else k.push.apply(k,y);else A(y,k);if(R){o(R,q,k,l);o.uniqueSort(k)}return k};o.uniqueSort=function(g){if(C){j=n;g.sort(C);if(j)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};o.matches=function(g,h){return o(g,null,null,h)};o.find=function(g,h,k){var l,q;if(!g)return[];for(var p=0,u=m.order.length;p<u;p++){var t=m.order[p];if(q=m.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");l=m.find[t](q, +h,k);if(l!=null){g=g.replace(m.match[t],"");break}}}}l||(l=h.getElementsByTagName("*"));return{set:l,expr:g}};o.filter=function(g,h,k,l){for(var q=g,p=[],u=h,t,y,R=h&&h[0]&&w(h[0]);g&&h.length;){for(var H in m.filter)if((t=m.leftMatch[H].exec(g))!=null&&t[2]){var M=m.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-1)!=="\\"){if(u===p)p=[];if(m.preFilter[H])if(t=m.preFilter[H](t,u,k,p,l,R)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=u[U])!=null;U++)if(D){I=M(D,t,U,u);var Da= +l^!!I;if(k&&I!=null)if(Da)y=true;else u[U]=false;else if(Da){p.push(D);y=true}}if(I!==v){k||(u=p);g=g.replace(m.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)o.error(g);else break;q=g}return u};o.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var m=o.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, +TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},relative:{"+":function(g,h){var k=typeof h==="string",l=k&&!/\W/.test(h);k=k&&!l;if(l)h=h.toLowerCase();l=0;for(var q=g.length, +p;l<q;l++)if(p=g[l]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[l]=k||p&&p.nodeName.toLowerCase()===h?p||false:p===h}k&&o.filter(h,g,true)},">":function(g,h){var k=typeof h==="string";if(k&&!/\W/.test(h)){h=h.toLowerCase();for(var l=0,q=g.length;l<q;l++){var p=g[l];if(p){k=p.parentNode;g[l]=k.nodeName.toLowerCase()===h?k:false}}}else{l=0;for(q=g.length;l<q;l++)if(p=g[l])g[l]=k?p.parentNode:p.parentNode===h;k&&o.filter(h,g,true)}},"":function(g,h,k){var l=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p= +h=h.toLowerCase();q=b}q("parentNode",h,l,g,p,k)},"~":function(g,h,k){var l=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,l,g,p,k)}},find:{ID:function(g,h,k){if(typeof h.getElementById!=="undefined"&&!k)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var k=[];h=h.getElementsByName(g[1]);for(var l=0,q=h.length;l<q;l++)h[l].getAttribute("name")===g[1]&&k.push(h[l]);return k.length===0?null:k}}, +TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,k,l,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var u;(u=h[p])!=null;p++)if(u)if(q^(u.className&&(" "+u.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))k||l.push(u);else if(k)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&& +"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,k,l,q,p){h=g[1].replace(/\\/g,"");if(!p&&m.attrMap[h])g[1]=m.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,k,l,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=o(g[3],null,null,h);else{g=o.filter(g[3],h,k,true^q);k||l.push.apply(l,g);return false}else if(m.match.POS.test(g[0])||m.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true); +return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,k){return!!o(k[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"=== +g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,h){return h===0},last:function(g,h,k,l){return h===l.length-1},even:function(g,h){return h%2=== +0},odd:function(g,h){return h%2===1},lt:function(g,h,k){return h<k[3]-0},gt:function(g,h,k){return h>k[3]-0},nth:function(g,h,k){return k[3]-0===h},eq:function(g,h,k){return k[3]-0===h}},filter:{PSEUDO:function(g,h,k,l){var q=h[1],p=m.filters[q];if(p)return p(g,k,h,l);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=h[3];k=0;for(l=h.length;k<l;k++)if(h[k]===g)return false;return true}else o.error("Syntax error, unrecognized expression: "+ +q)},CHILD:function(g,h){var k=h[1],l=g;switch(k){case "only":case "first":for(;l=l.previousSibling;)if(l.nodeType===1)return false;if(k==="first")return true;l=g;case "last":for(;l=l.nextSibling;)if(l.nodeType===1)return false;return true;case "nth":k=h[2];var q=h[3];if(k===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var u=0;for(l=p.firstChild;l;l=l.nextSibling)if(l.nodeType===1)l.nodeIndex=++u;p.sizcache=h}g=g.nodeIndex-q;return k===0?g===0:g%k===0&&g/k>= +0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var k=h[1];g=m.attrHandle[k]?m.attrHandle[k](g):g[k]!=null?g[k]:g.getAttribute(k);k=g+"";var l=h[2];h=h[4];return g==null?l==="!=":l==="="?k===h:l==="*="?k.indexOf(h)>=0:l==="~="?(" "+k+" ").indexOf(h)>=0:!h?k&&g!==false:l==="!="?k!==h:l==="^="? +k.indexOf(h)===0:l==="$="?k.substr(k.length-h.length)===h:l==="|="?k===h||k.substr(0,h.length+1)===h+"-":false},POS:function(g,h,k,l){var q=m.setFilters[h[2]];if(q)return q(g,k,h,l)}}},s=m.match.POS;for(var x in m.match){m.match[x]=new RegExp(m.match[x].source+/(?![^\[]*\])(?![^\(]*\))/.source);m.leftMatch[x]=new RegExp(/(^(?:.|\r|\n)*?)/.source+m.match[x].source.replace(/\\(\d+)/g,function(g,h){return"\\"+(h-0+1)}))}var A=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g}; +try{Array.prototype.slice.call(r.documentElement.childNodes,0)}catch(B){A=function(g,h){h=h||[];if(i.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var k=0,l=g.length;k<l;k++)h.push(g[k]);else for(k=0;g[k];k++)h.push(g[k]);return h}}var C;if(r.documentElement.compareDocumentPosition)C=function(g,h){if(!g.compareDocumentPosition||!h.compareDocumentPosition){if(g==h)j=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g=== +h?0:1;if(g===0)j=true;return g};else if("sourceIndex"in r.documentElement)C=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)j=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)j=true;return g};else if(r.createRange)C=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)j=true;return g.ownerDocument?-1:1}var k=g.ownerDocument.createRange(),l=h.ownerDocument.createRange();k.setStart(g,0);k.setEnd(g,0);l.setStart(h,0);l.setEnd(h,0);g=k.compareBoundaryPoints(Range.START_TO_END, +l);if(g===0)j=true;return g};(function(){var g=r.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var k=r.documentElement;k.insertBefore(g,k.firstChild);if(r.getElementById(h)){m.find.ID=function(l,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(l[1]))?q.id===l[1]||typeof q.getAttributeNode!=="undefined"&&q.getAttributeNode("id").nodeValue===l[1]?[q]:v:[]};m.filter.ID=function(l,q){var p=typeof l.getAttributeNode!=="undefined"&&l.getAttributeNode("id"); +return l.nodeType===1&&p&&p.nodeValue===q}}k.removeChild(g);k=g=null})();(function(){var g=r.createElement("div");g.appendChild(r.createComment(""));if(g.getElementsByTagName("*").length>0)m.find.TAG=function(h,k){k=k.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var l=0;k[l];l++)k[l].nodeType===1&&h.push(k[l]);k=h}return k};g.innerHTML="<a href='#'></a>";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")m.attrHandle.href=function(h){return h.getAttribute("href", +2)};g=null})();r.querySelectorAll&&function(){var g=o,h=r.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){o=function(l,q,p,u){q=q||r;if(!u&&q.nodeType===9&&!w(q))try{return A(q.querySelectorAll(l),p)}catch(t){}return g(l,q,p,u)};for(var k in g)o[k]=g[k];h=null}}();(function(){var g=r.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length=== +0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){m.order.splice(1,0,"CLASS");m.find.CLASS=function(h,k,l){if(typeof k.getElementsByClassName!=="undefined"&&!l)return k.getElementsByClassName(h[1])};g=null}}})();var E=r.compareDocumentPosition?function(g,h){return g.compareDocumentPosition(h)&16}:function(g,h){return g!==h&&(g.contains?g.contains(h):true)},w=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},fa=function(g,h){var k=[], +l="",q;for(h=h.nodeType?[h]:h;q=m.match.PSEUDO.exec(g);){l+=q[0];g=g.replace(m.match.PSEUDO,"")}g=m.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)o(g,h[q],k);return o.filter(l,k)};c.find=o;c.expr=o.selectors;c.expr[":"]=c.expr.filters;c.unique=o.uniqueSort;c.getText=a;c.isXMLDoc=w;c.contains=E})();var bb=/Until$/,cb=/^(?:parents|prevUntil|prevAll)/,db=/,/;Q=Array.prototype.slice;var Ea=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,i){return!!b.call(e,i,e)===d});else if(b.nodeType)return c.grep(a, +function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Qa.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;c.find(a,this[f],b);if(f>0)for(var i=d;i<b.length;i++)for(var j=0;j<d;j++)if(b[j]===b[i]){b.splice(i--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d= +0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ea(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ea(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,i={},j;if(f&&a.length){e=0;for(var n=a.length;e<n;e++){j=a[e];i[j]||(i[j]=c.expr.match.POS.test(j)?c(j,b||this.context):j)}for(;f&&f.ownerDocument&&f!==b;){for(j in i){e=i[j];if(e.jquery?e.index(f)> +-1:c(f).is(e)){d.push({selector:j,elem:f});delete i[j]}}f=f.parentNode}}return d}var o=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(m,s){for(;s&&s.ownerDocument&&s!==b;){if(o?o.index(s)>-1:c(s).is(a))return s;s=s.parentNode}return null})},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(), +a);return this.pushStack(pa(a[0])||pa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")}, +nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);bb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e): +e;if((this.length>1||db.test(f))&&cb.test(a))e=e.reverse();return this.pushStack(e,a,Q.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===v||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!== +b&&d.push(a);return d}});var Fa=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ga=/(<([\w:]+)[^>]*?)\/>/g,eb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,Ha=/<([\w:]+)/,fb=/<tbody/i,gb=/<|&\w+;/,sa=/checked\s*(?:[^=]|=\s*.checked.)/i,Ia=function(a,b,d){return eb.test(d)?a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"], +col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==v)return this.empty().append((this[0]&&this[0].ownerDocument||r).createTextNode(a));return c.getText(this)}, +wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length? +d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments, +false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&& +!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Fa,"").replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){qa(this,b);qa(this.find("*"),b.find("*"))}return b},html:function(a){if(a===v)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Fa,""):null;else if(typeof a==="string"&&!/<script/i.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(Ha.exec(a)|| +["",""])[1].toLowerCase()]){a=a.replace(Ga,Ia);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var i=c(this),j=i.html();i.empty().append(function(){return a.call(this,e,j)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this, +b,f))});else a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(s){return c.nodeName(s,"table")?s.getElementsByTagName("tbody")[0]||s.appendChild(s.ownerDocument.createElement("tbody")):s}var e,i,j=a[0],n=[];if(!c.support.checkClone&&arguments.length===3&&typeof j=== +"string"&&sa.test(j))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(j))return this.each(function(s){var x=c(this);a[0]=j.call(this,s,b?x.html():v);x.domManip(a,b,d)});if(this[0]){e=a[0]&&a[0].parentNode&&a[0].parentNode.nodeType===11?{fragment:a[0].parentNode}:ra(a,this,n);if(i=e.fragment.firstChild){b=b&&c.nodeName(i,"tr");for(var o=0,m=this.length;o<m;o++)d.call(b?f(this[o],i):this[o],e.cacheable||this.length>1||o>0?e.fragment.cloneNode(true):e.fragment)}n&&c.each(n, +Ma)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);for(var e=0,i=d.length;e<i;e++){var j=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),j);f=f.concat(j)}return this.pushStack(f,a,d.selector)}});c.each({remove:function(a,b){if(!a||c.filter(a,[this]).length){if(!b&&this.nodeType===1){c.cleanData(this.getElementsByTagName("*"));c.cleanData([this])}this.parentNode&& +this.parentNode.removeChild(this)}},empty:function(){for(this.nodeType===1&&c.cleanData(this.getElementsByTagName("*"));this.firstChild;)this.removeChild(this.firstChild)}},function(a,b){c.fn[a]=function(){return this.each(b,arguments)}});c.extend({clean:function(a,b,d,f){b=b||r;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||r;var e=[];c.each(a,function(i,j){if(typeof j==="number")j+="";if(j){if(typeof j==="string"&&!gb.test(j))j=b.createTextNode(j);else if(typeof j=== +"string"){j=j.replace(Ga,Ia);var n=(Ha.exec(j)||["",""])[1].toLowerCase(),o=F[n]||F._default,m=o[0];i=b.createElement("div");for(i.innerHTML=o[1]+j+o[2];m--;)i=i.lastChild;if(!c.support.tbody){m=fb.test(j);n=n==="table"&&!m?i.firstChild&&i.firstChild.childNodes:o[1]==="<table>"&&!m?i.childNodes:[];for(o=n.length-1;o>=0;--o)c.nodeName(n[o],"tbody")&&!n[o].childNodes.length&&n[o].parentNode.removeChild(n[o])}!c.support.leadingWhitespace&&V.test(j)&&i.insertBefore(b.createTextNode(V.exec(j)[0]),i.firstChild); +j=c.makeArray(i.childNodes)}if(j.nodeType)e.push(j);else e=c.merge(e,j)}});if(d)for(a=0;e[a];a++)if(f&&c.nodeName(e[a],"script")&&(!e[a].type||e[a].type.toLowerCase()==="text/javascript"))f.push(e[a].parentNode?e[a].parentNode.removeChild(e[a]):e[a]);else{e[a].nodeType===1&&e.splice.apply(e,[a+1,0].concat(c.makeArray(e[a].getElementsByTagName("script"))));d.appendChild(e[a])}return e},cleanData:function(a){for(var b=0,d;(d=a[b])!=null;b++){c.event.remove(d);c.removeData(d)}}});var hb=/z-?index|font-?weight|opacity|zoom|line-?height/i, +Ja=/alpha\([^)]*\)/,Ka=/opacity=([^)]*)/,ga=/float/i,ha=/-([a-z])/ig,ib=/([A-Z])/g,jb=/^-?\d+(?:px)?$/i,kb=/^-?\d/,lb={position:"absolute",visibility:"hidden",display:"block"},mb=["Left","Right"],nb=["Top","Bottom"],ob=r.defaultView&&r.defaultView.getComputedStyle,La=c.support.cssFloat?"cssFloat":"styleFloat",ia=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===v)return c.curCSS(d,f);if(typeof e==="number"&&!hb.test(f))e+="px";c.style(d,f,e)})}; +c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return v;if((b==="width"||b==="height")&&parseFloat(d)<0)d=v;var f=a.style||a,e=d!==v;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=Ja.test(a)?a.replace(Ja,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Ka.exec(f.filter)[1])/100+"":""}if(ga.test(b))b=La;b=b.replace(ha,ia);if(e)f[b]=d;return f[b]},css:function(a, +b,d,f){if(b==="width"||b==="height"){var e,i=b==="width"?mb:nb;function j(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(i,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,"border"+this+"Width",true))||0})}a.offsetWidth!==0?j():c.swap(a,lb,j);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&& +a.currentStyle){f=Ka.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ga.test(b))b=La;if(!d&&e&&e[b])f=e[b];else if(ob){if(ga.test(b))b="float";b=b.replace(ib,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ha,ia);f=a.currentStyle[b]||a.currentStyle[d];if(!jb.test(f)&&kb.test(f)){b=e.left;var i=a.runtimeStyle.left;a.runtimeStyle.left= +a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=i}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var pb= +J(),qb=/<script(.|\s)*?\/script>/gi,rb=/select|textarea/i,sb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ja=/\?/,tb=/(\?|&)_=.*?(&|$)/,ub=/^(\w+:)?\/\/([^\/?#]+)/,vb=/%20/g;c.fn.extend({_load:c.fn.load,load:function(a,b,d){if(typeof a!=="string")return this._load(a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b= +c.param(b,c.ajaxSettings.traditional);f="POST"}var i=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(j,n){if(n==="success"||n==="notmodified")i.html(e?c("<div />").append(j.responseText.replace(qb,"")).find(e):j.responseText);d&&i.each(d,[j.responseText,n,j])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&& +(this.checked||rb.test(this.nodeName)||sb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a, +b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:z.XMLHttpRequest&&(z.location.protocol!=="file:"||!z.ActiveXObject)?function(){return new z.XMLHttpRequest}: +function(){try{return new z.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&e.success.call(o,n,j,w);e.global&&f("ajaxSuccess",[w,e])}function d(){e.complete&&e.complete.call(o,w,j);e.global&&f("ajaxComplete",[w,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")} +function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),i,j,n,o=a&&a.context||e,m=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(m==="GET")N.test(e.url)||(e.url+=(ja.test(e.url)?"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)|| +N.test(e.url))){i=e.jsonpCallback||"jsonp"+pb++;if(e.data)e.data=(e.data+"").replace(N,"="+i+"$1");e.url=e.url.replace(N,"="+i+"$1");e.dataType="script";z[i]=z[i]||function(q){n=q;b();d();z[i]=v;try{delete z[i]}catch(p){}A&&A.removeChild(B)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===false&&m==="GET"){var s=J(),x=e.url.replace(tb,"$1_="+s+"$2");e.url=x+(x===e.url?(ja.test(e.url)?"&":"?")+"_="+s:"")}if(e.data&&m==="GET")e.url+=(ja.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&& +c.event.trigger("ajaxStart");s=(s=ub.exec(e.url))&&(s[1]&&s[1]!==location.protocol||s[2]!==location.host);if(e.dataType==="script"&&m==="GET"&&s){var A=r.getElementsByTagName("head")[0]||r.documentElement,B=r.createElement("script");B.src=e.url;if(e.scriptCharset)B.charset=e.scriptCharset;if(!i){var C=false;B.onload=B.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;b();d();B.onload=B.onreadystatechange=null;A&&B.parentNode&& +A.removeChild(B)}}}A.insertBefore(B,A.firstChild);return v}var E=false,w=e.xhr();if(w){e.username?w.open(m,e.url,e.async,e.username,e.password):w.open(m,e.url,e.async);try{if(e.data||a&&a.contentType)w.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[e.url]);c.etag[e.url]&&w.setRequestHeader("If-None-Match",c.etag[e.url])}s||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept", +e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(fa){}if(e.beforeSend&&e.beforeSend.call(o,w,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");w.abort();return false}e.global&&f("ajaxSend",[w,e]);var g=w.onreadystatechange=function(q){if(!w||w.readyState===0||q==="abort"){E||d();E=true;if(w)w.onreadystatechange=c.noop}else if(!E&&w&&(w.readyState===4||q==="timeout")){E=true;w.onreadystatechange=c.noop;j=q==="timeout"?"timeout":!c.httpSuccess(w)? +"error":e.ifModified&&c.httpNotModified(w,e.url)?"notmodified":"success";var p;if(j==="success")try{n=c.httpData(w,e.dataType,e)}catch(u){j="parsererror";p=u}if(j==="success"||j==="notmodified")i||b();else c.handleError(e,w,j,p);d();q==="timeout"&&w.abort();if(e.async)w=null}};try{var h=w.abort;w.abort=function(){w&&h.call(w);g("abort")}}catch(k){}e.async&&e.timeout>0&&setTimeout(function(){w&&!E&&g("timeout")},e.timeout);try{w.send(m==="POST"||m==="PUT"||m==="DELETE"?e.data:null)}catch(l){c.handleError(e, +w,null,l);d()}e.async||g();return w}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]= +f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(j,n){if(c.isArray(n))c.each(n, +function(o,m){b?f(j,m):d(j+"["+(typeof m==="object"||c.isArray(m)?o:"")+"]",m)});else!b&&n!=null&&typeof n==="object"?c.each(n,function(o,m){d(j+"["+o+"]",m)}):f(j,n)}function f(j,n){n=c.isFunction(n)?n():n;e[e.length]=encodeURIComponent(j)+"="+encodeURIComponent(n)}var e=[];if(b===v)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var i in a)d(i,a[i]);return e.join("&").replace(vb,"+")}});var ka={},wb=/toggle|show|hide/,xb=/^([+-]=)?([\d+-.]+)(.*)$/, +W,ta=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(ka[d])f=ka[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove(); +ka[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&& +c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var i=c.extend({},e),j,n=this.nodeType===1&&c(this).is(":hidden"), +o=this;for(j in a){var m=j.replace(ha,ia);if(j!==m){a[m]=a[j];delete a[j];j=m}if(a[j]==="hide"&&n||a[j]==="show"&&!n)return i.complete.call(this);if((j==="height"||j==="width")&&this.style){i.display=c.css(this,"display");i.overflow=this.style.overflow}if(c.isArray(a[j])){(i.specialEasing=i.specialEasing||{})[j]=a[j][1];a[j]=a[j][0]}}if(i.overflow!=null)this.style.overflow="hidden";i.curAnim=c.extend({},a);c.each(a,function(s,x){var A=new c.fx(o,i,s);if(wb.test(x))A[x==="toggle"?n?"show":"hide":x](a); +else{var B=xb.exec(x),C=A.cur(true)||0;if(B){x=parseFloat(B[2]);var E=B[3]||"px";if(E!=="px"){o.style[s]=(x||1)+E;C=(x||1)/A.cur(true)*C;o.style[s]=C+E}if(B[1])x=(B[1]==="-="?-1:1)*x+C;A.custom(C,x,E)}else A.custom(C,x,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle", +1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration==="number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a, +b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]== +null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(i){return e.step(i)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop=== +"width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow= +this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos= +c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!= +null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in r.documentElement?function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(), +f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=this[0];if(a)return this.each(function(s){c.offset.setOffset(this,a,s)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f= +b,e=b.ownerDocument,i,j=e.documentElement,n=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var o=b.offsetTop,m=b.offsetLeft;(b=b.parentNode)&&b!==n&&b!==j;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;i=e?e.getComputedStyle(b,null):b.currentStyle;o-=b.scrollTop;m-=b.scrollLeft;if(b===d){o+=b.offsetTop;m+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){o+=parseFloat(i.borderTopWidth)|| +0;m+=parseFloat(i.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&i.overflow!=="visible"){o+=parseFloat(i.borderTopWidth)||0;m+=parseFloat(i.borderLeftWidth)||0}f=i}if(f.position==="relative"||f.position==="static"){o+=n.offsetTop;m+=n.offsetLeft}if(c.offset.supportsFixedPosition&&f.position==="fixed"){o+=Math.max(j.scrollTop,n.scrollTop);m+=Math.max(j.scrollLeft,n.scrollLeft)}return{top:o,left:m}};c.offset={initialize:function(){var a=r.body,b=r.createElement("div"), +d,f,e,i=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.insertBefore(b,a.firstChild); +d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i;a.removeChild(b);c.offset.initialize=c.noop}, +bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),i=parseInt(c.curCSS(a,"top",true),10)||0,j=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,d,e);d={top:b.top-e.top+i,left:b.left- +e.left+j};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a= +this.offsetParent||r.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],i;if(!e)return null;if(f!==v)return this.each(function(){if(i=ua(this))i.scrollTo(!a?f:c(i).scrollLeft(),a?f:c(i).scrollTop());else this[d]=f});else return(i=ua(e))?"pageXOffset"in i?i[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&i.document.documentElement[d]||i.document.body[d]:e[d]}}); +c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(i){var j=c(this);j[d](f.call(this,i,j[d]()))});return"scrollTo"in e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]|| +e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===v?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});z.jQuery=z.$=c})(window); diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/jquery.rails.js b/railties/lib/generators/rails/app/templates/public/javascripts/jquery.rails.js new file mode 100644 index 0000000000..887da514e2 --- /dev/null +++ b/railties/lib/generators/rails/app/templates/public/javascripts/jquery.rails.js @@ -0,0 +1,239 @@ +jQuery(function ($) { + var rails = { + update: function (selector, content, position) { + var element = $('#' + selector); + if (position) { + switch (position) { + case "before": + element.before(content); + break; + case "after": + element.after(content); + break; + case "top": + element.prepend(content); + break; + case "bottom": + element.append(content); + break; + default: + element.append(content); + break; + } + } else { + element.html(content); + } + }, + remote: function (e) { + var el = $(this), + data = [], + condition = el.attr('data-condition') ? eval(el.attr('data-condition')) : true, + method = el.attr('method') || el.attr('data-method') || 'GET', + url = el.attr('action') || el.attr('data-url') || '#', + async = el.attr('data-remote-type') === 'synchronous' ? false : true; + + if (el.attr('data-submit')) { + data = $('#' + el.attr('data-submit')).serializeArray(); + } else if (el.attr('data-with')) { + + if (e && e.target.tagName.toUpperCase() == 'SCRIPT' && el.attr('data-observed') !== null) { + var observed = $('#' + el.attr('data-observed')); + if(observed[0].tagName.toUpperCase() === 'FORM'){ + data = el.attr('data-with') + '=' + observed.serialize(); + } else if(observed[0].tagName.toUpperCase() === 'INPUT' && observed.attr('type').toUpperCase() !== "BUTTON" && observed.attr('type').toUpperCase() !== "SUBMIT") { + data = el.attr('data-with') + '=' + observed.val(); + } + } else { + // TODO: remove eval when deprecated + data = eval(el.attr('data-with')); + } + } else if (e && e.target.tagName.toUpperCase() == 'FORM') { + data = el.serializeArray(); + } else if (e && e.target.tagName.toUpperCase() == 'INPUT') { + data = el.closest('form').serializeArray(); + } + + if (condition) { + el.trigger('rails:before'); + + $.ajax({ + async: async, + url: url, + data: data, + type: method.toUpperCase(), + beforeSend: function (xhr) { + xhr.setRequestHeader("Accept", "text/javascript") + el.trigger('rails:after', xhr); + el.trigger('rails:loading', xhr); + }, + success: function (data, status, xhr) { + el.trigger('rails:success', [data, status, xhr]); + if (el.attr('data-update-success')) { + rails.update(el.attr('data-update-success'), data, el.attr('data-update-position')); + } + }, + complete: function (xhr) { + // enable disabled_with buttons + if (el[0].tagName.toUpperCase() == 'FORM') { + el.children('input[type="button"][data-enable-with],input[type="submit"][data-enable-with]').each(function(i, button){ + button = $(button); + button.attr('value', button.attr('data-enable-with')); + button.removeAttr('data-enable-with'); + button.removeAttr('disabled'); + + }); + } else { + el.attr('value', el.attr('data-enable-with')); + el.removeAttr('data-enable-with'); + el.removeAttr('disabled'); + } + + el.trigger('rails:complete', xhr); + el.trigger('rails:loaded', xhr); + }, + error: function (xhr, status, error) { + el.trigger('rails:failure', [xhr, status, error]); + if (el.attr('data-update-failure')) { + rails.update(el.attr('data-update-failure'), xhr.responseText, el.attr('data-update-position')); + } + } + }); + } + e.preventDefault(); + } + } + + /** + * observe_form, and observe_field + */ + $('script[data-observe="true"]').each(function (index, e) { + var el = $(e), + observed = $('#' + $(e).attr('data-observed')); + frequency = el.attr('data-frequency') ? el.attr('data-frequency') : 10, + value = observed[0].tagName.toUpperCase() === 'FORM' ? observed.serialize() : observed.val(); + + var observe = function (observed, frequency, value, e) { + return function () { + var event = new jQuery.Event('periodical'), + newValue = observed[0].tagName.toUpperCase() === 'FORM' ? observed.serialize() : observed.val(); + event.target = e; + + if(value !== newValue) { + value = newValue; + $(e).trigger('rails:observe'); + rails.remote.call(el, event); + } + } + }(observed, frequency, value, e); + + setInterval(observe, frequency * 1000); + }); + + /** + * confirm + * make sure this event is first! + */ + $('a[data-confirm],input[type="submit"][data-confirm],input[type="button"][data-confirm]').live('click', function(e){ + var el = $(this); + + if(!confirm(el.attr('data-confirm'))){ + return false; + } + }); + + /** + * periodically_call_remote + */ + $('script[data-periodical="true"]').each(function (index, e) { + var el = $(e), + frequency = el.attr('data-frequency') ? el.attr('data-frequency') : 10; + + setInterval(function () { + return function () { + var event = new jQuery.Event('periodical'); + event.target = e; + + rails.remote.call(el, event); + } + }(e, el), frequency * 1000); + }); + + /** + * disable_with + */ + $('input[type="button"][data-disable-with],input[type="submit"][data-disable-with]').live('click', function(e){ + var el = $(this); + + el.attr('data-enable-with', el.attr('value')); + el.attr('disabled', 'disabled'); + el.attr('value', el.attr('data-disable-with')); + }); + + /** + * remote_form_tag, and remote_form_for + */ + $('form[data-remote="true"]').live('submit', rails.remote); + + /** + * link_to_remote, button_to_remote, and submit_to_remote + */ + $('a[data-remote="true"],input[data-remote="true"],input[data-remote-submit="true"]').live('click', rails.remote); + + /* + * popup + */ + $('a[data-popup],input[type="button"][data-popup]').live('click', function(e){ + var el = $(this), + url = el.attr('data-url') || el.attr('href'); + + e.preventDefault(); + + if(el.attr('data-popup') === "true"){ + window.open(url); + } else { + window.open(url, el.attr('data-popup')); + } + }); + + /** + * + * Rails 2.x Helper / Event Handlers + * By default we listen to all callbacks, and status code callbacks and + * check the element for data-<callback> attribute and eval it. + * + */ + rails.compat = { + evalAttribute: function (element, attribute) { + var el = $(element), + attr = el.attr('data-' + attribute); + return (attr) ? eval(attr) : true; + } + }; + + $('form[data-remote="true"],a[data-remote="true"],input[data-remote="true"],script[data-observe="true"]') + .live('rails:before', function (e) { + rails.compat.evalAttribute(this, 'onbefore'); + }) + .live('rails:after', function (e, xhr) { + rails.compat.evalAttribute(this, 'onafter'); + }) + .live('rails:loading', function (e, xhr) { + rails.compat.evalAttribute(this, 'onloading'); + }) + .live('rails:loaded', function (e, xhr) { + rails.compat.evalAttribute(this, 'onloaded'); + }) + .live('rails:complete', function (e, xhr) { + rails.compat.evalAttribute(this, 'oncomplete'); + rails.compat.evalAttribute(this, 'on' + xhr.status); + }) + .live('rails:success', function (e, data, status, xhr) { + rails.compat.evalAttribute(this, 'onsuccess'); + }) + .live('rails:failure', function (e, xhr, status, error) { + rails.compat.evalAttribute(this, 'onfailure'); + }) + .live('rails:observe', function (e) { + rails.compat.evalAttribute(this, 'onobserve'); + }); +}); diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/prototype.rails.js b/railties/lib/generators/rails/app/templates/public/javascripts/prototype.rails.js new file mode 100644 index 0000000000..aaed677fda --- /dev/null +++ b/railties/lib/generators/rails/app/templates/public/javascripts/prototype.rails.js @@ -0,0 +1,324 @@ +Event.observe(document, 'dom:loaded', function() { + function handle_remote(el, e){ + var data = null, + method = el.readAttribute('method') || el.readAttribute('data-method') || 'GET', + url = el.readAttribute('action') || el.readAttribute('data-url') || '#', + async = el.readAttribute('data-remote-type') === 'synchronous' ? false : true, + update = el.readAttribute('data-update-success'), + position = el.readAttribute('data-update-position'); + + if (el.readAttribute('data-submit')) { + var submit_el = $(el.readAttribute('data-submit')); + if(submit_el !== undefined && submit_el.tagName.toUpperCase() == 'FORM'){ + data = submit_el.serialize(); + } + } else if (el.readAttribute('data-with')) { + // It seems there is a big inconsistency between what :with means depending on the element type + // so this is going to look a bit crazy + if(el.tagName.toUpperCase() === 'SCRIPT' && el.readAttribute('data-observed') !== null){ + // Handle observe_field and observe_form + var observed_element = $(el.readAttribute('data-observed')); + + if(observed_element.tagName.toUpperCase() === 'FORM'){ + data = el.readAttribute('data-with') + '=' + observed_element.serialize(); + } else if(observed_element.tagName.toUpperCase() === 'INPUT' && observed_element.readAttribute('type').toUpperCase() !== "BUTTON" && observed_element.readAttribute('type').toUpperCase() !== "SUBMIT") { + data = el.readAttribute('data-with') + '=' + observed_element.getValue(); + } + } else { + // Handle link_to and button_to + data = evalAttribute(el, 'data-with'); + } + } else if(el.tagName.toUpperCase() === 'FORM') { + data = el.serialize(); + } + + document.fire('rails:before'); + + var request = new Ajax.Request(url, { + method: method, + asynchronous: async, + parameters: data, + evalJS: true, + evalJSON: true, + onComplete: function(xhr){ + document.fire('rails:complete', {xhr: xhr, element: el, submitted_button: getEventProperty(e, 'submitted_button')}); + }, + onLoading: function(xhr){ + document.fire('rails:after', {xhr: xhr, element: el}); + document.fire('rails:loading', {xhr: xhr, element: el}); + }, + onLoaded: function(xhr){ + document.fire('rails:loaded', {xhr: xhr, element: el}); + }, + onSuccess: function(xhr){ + document.fire('rails:success', {xhr: xhr, element: el}); + }, + onFailure: function(xhr){ + document.fire('rails:failure', {xhr: xhr, element: el}); + } + }); + + } + + function setEventProperty(e, property, value){ + if(e.memo === undefined){ + e.memo = {}; + } + + e.memo[property] = value; + } + + function getEventProperty(e, property){ + if(e !== null && e.memo !== undefined && e.memo[property] !== undefined){ + return e.memo[property]; + } + } + + function confirmed(e, el){ + if(getEventProperty(e,'confirm_checked') !== true){ + setEventProperty(e, 'confirm_checked', true); + + el = Event.findElement(e, 'form') || el; + var confirm_msg = el.readAttribute('data-confirm'); + + if(confirm_msg !== null){ + var result = el.fire('rails:confirm', {confirm_msg: confirm_msg}); + if(result.memo.stop_event === true){ + Event.stop(e); + return false; + } + } + } + return true; + } + + function disable_button(el){ + var disable_with = el.readAttribute('data-disable-with'); + if(disable_with !== null){ + el.writeAttribute('data-enable-with', el.readAttribute('value')); + el.writeAttribute('value', disable_with); + el.writeAttribute('disabled', true); + } + } + + function enable_button(el){ + var enable_with = el.readAttribute('data-enable-with'); + if(enable_with !== null){ + el.writeAttribute('value', enable_with); + } + el.writeAttribute('disabled', false); + } + + function updateHTML(el, content, result){ + var element_id = null; + + if(result === 'success'){ + element_id = el.readAttribute('data-update-success'); + } else if(result === 'failure'){ + element_id = el.readAttribute('data-update-failure'); + } + + var element_to_update = $(element_id); + if(element_to_update !== null){ + var position = el.readAttribute('data-update-position'); + if(position !== null){ + var options = {}; + options[position] = content; + element_to_update.insert(options); + } else { + element_to_update.update(content); + } + } + } + + $$("script[data-periodical=true]").each(function(el){ + var executor = new PeriodicalExecuter(function() { handle_remote(el);}, el.readAttribute('data-frequency')); + }); + + $$("script[data-observe=true]").each(function(el){ + var observed_element = $(el.readAttribute('data-observed')); + var original_value = observed_element.tagName.toUpperCase() === 'FORM' ? observed_element.serialize() : observed_element.getValue(); + var callback = el.readAttribute('data-onobserve'); + var executor = new PeriodicalExecuter(function() { + var value = observed_element.tagName.toUpperCase() === 'FORM' ? observed_element.serialize() : observed_element.getValue(); + + if(original_value !== value){ + original_value = value; + + if(callback !== null){ + evalAttribute(el, 'onobserve'); + } else if(el.readAttribute('data-url') !== null){ + handle_remote(el); + } + } + }, el.readAttribute('data-frequency')); + + }); + + /** + * + * Event Listeners + * + * the original element is contained inside the event, + * for some reason prototype wont let me listen for custom events on document + * if the event wasn't fired on document + * + */ + + Event.observe(document, 'submit', function (e) { + var form = Event.findElement(e, 'form'); + // Make sure conditions and confirm have not already run + if(form !== undefined && conditions_met(e, form) && confirmed(e, form)){ + + var button = form.down('input[data-submitted=true]'); + button.writeAttribute('data-submitted', null); + setEventProperty(e, 'submitted_button', button); + disable_button(button); + + if(form.readAttribute('data-remote') === 'true'){ + Event.stop(e); + handle_remote(form, e); + } + } + }); + + Event.observe(document, 'click', function (e) { + var el = Event.findElement(e, 'a') || Event.findElement(e, 'input'); + + if(el !== undefined && el.tagName.toUpperCase() === 'INPUT' && el.readAttribute('type').toUpperCase() === 'SUBMIT'){ + el.writeAttribute('data-submitted', 'true'); + + // Submit is handled by submit event, don't continue on this path + el = undefined; + } else if(el !== undefined && el.tagName.toUpperCase() === 'INPUT' && el.readAttribute('type').toUpperCase() !== 'BUTTON'){ + // Make sure other inputs do not send this event + el = undefined; + } + + if(el !== undefined && conditions_met(e, el) && confirmed(e, el)){ + if(el.tagName.toUpperCase() === 'INPUT' && el.readAttribute('type').toUpperCase() === 'BUTTON'){ + disable_button(el); + } + + if(el.readAttribute('data-remote') === 'true'){ + Event.stop(e); + handle_remote(el, e); + } else if(el.readAttribute('data-popup') !== null){ + Event.stop(e); + document.fire('rails:popup', {element: el}); + } + } + }); + + /** + * + * Default Event Handlers + * + */ + Event.observe(document, 'rails:confirm', function(e){ + setEventProperty(e, 'stop_event', !confirm(getEventProperty(e,'confirm_msg'))); + }); + + Event.observe(document, 'rails:popup', function(e){ + var el = getEventProperty(e, 'element'); + var url = el.readAttribute('href') || el.readAttribute('data-url'); + + if(el.readAttribute('data-popup') === true){ + window.open(url); + } else { + window.open(url, el.readAttribute('data-popup')); + } + }); + + Event.observe(document, 'rails:complete', function(e){ + var el = getEventProperty(e, 'element'); + + if(el.tagName.toUpperCase() === 'FORM'){ + var button = getEventProperty(e, 'submitted_button') ; + enable_button(button); + } + }); + + Event.observe(document, 'rails:success', function(e){ + var el = getEventProperty(e, 'element'), + xhr = getEventProperty(e, 'xhr'); + + if(xhr.responseText !== null){ + updateHTML(el, xhr.responseText, 'success'); + } + }); + + Event.observe(document, 'rails:failure', function(e){ + var el = getEventProperty(e, 'element'), + xhr = getEventProperty(e, 'xhr'); + + if(xhr.responseText !== null){ + updateHTML(el, xhr.responseText, 'failure'); + } + }); + + /** + * + * Rails 2.x Helpers / Event Handlers + * + */ + function evalAttribute(el, attribute){ + var js = el.readAttribute('data-' + attribute); + + if(js){ + eval(js); + } + } + + function conditions_met(e, el){ + if(getEventProperty(e,'condition_checked') !== true){ + setEventProperty(e, 'condition_checked', true); + + el = Event.findElement(e, 'form') || el; + var conditions = el.readAttribute('data-condition'); + + if(conditions !== null){ + if(eval(conditions) === false){ + Event.stop(e); + return false; + } + } + } + return true; + } + + Event.observe(document, 'rails:success', function(e){ + evalAttribute(el, 'onsuccess'); + }); + + Event.observe(document, 'rails:failure', function(e){ + evalAttribute(el, 'onfailure'); + }); + + Event.observe(document, 'rails:complete', function(e){ + var el = getEventProperty(e, 'element'); + + evalAttribute(el, 'oncomplete'); + evalAttribute(el, 'on' + getEventProperty('xhr', xhr.status)); + + if(el.readAttribute('data-periodical') === 'true'){ + evalAttribute(el, 'onobserve'); + } + }); + + Event.observe(document, 'rails:loading', function(e){ + evalAttribute(el, 'onloading'); + }); + + Event.observe(document, 'rails:loaded', function(e){ + evalAttribute(el, 'onloaded'); + }); + + Event.observe(document, 'rails:before', function(e){ + evalAttribute(el, 'onbefore'); + }); + + Event.observe(document, 'rails:after', function(e){ + evalAttribute(el, 'onafter'); + }); +}); diff --git a/railties/lib/generators/rails/app/templates/script/console.tt b/railties/lib/generators/rails/app/templates/script/console.tt index 915c5b8294..47aa254f9f 100755 --- a/railties/lib/generators/rails/app/templates/script/console.tt +++ b/railties/lib/generators/rails/app/templates/script/console.tt @@ -2,4 +2,4 @@ require File.expand_path('../../config/boot', __FILE__) require 'rails/commands/console' require File.expand_path('../../config/application', __FILE__) -Rails::Console.start(<%= app_const %>) +Rails::Console.start(Rails::Application) diff --git a/railties/lib/generators/rails/app/templates/script/dbconsole.tt b/railties/lib/generators/rails/app/templates/script/dbconsole.tt index a92f6f2844..1e53c1d761 100755 --- a/railties/lib/generators/rails/app/templates/script/dbconsole.tt +++ b/railties/lib/generators/rails/app/templates/script/dbconsole.tt @@ -2,4 +2,4 @@ require File.expand_path('../../config/boot', __FILE__) require 'rails/commands/dbconsole' require File.expand_path('../../config/application', __FILE__) -Rails::DBConsole.start(<%= app_const %>) +Rails::DBConsole.start(Rails::Application) diff --git a/railties/lib/generators/rails/mailer/templates/mailer.rb b/railties/lib/generators/rails/mailer/templates/mailer.rb index 90e0b712d6..7343eb28b3 100644 --- a/railties/lib/generators/rails/mailer/templates/mailer.rb +++ b/railties/lib/generators/rails/mailer/templates/mailer.rb @@ -1,14 +1,16 @@ class <%= class_name %> < ActionMailer::Base + default :from => "from@example.com" <% for action in actions -%> - def <%= action %>(sent_at = Time.now) - subject '<%= class_name %>#<%= action %>' - recipients '' - from '' - sent_on sent_at - - body :greeting => 'Hi,' - end + # Subject can be set in your I18n file at config/locales/en.yml + # with the following lookup: + # + # en.actionmailer.<%= file_name %>.<%= action %>.subject + # + def <%= action %> + @greeting = "Hi" + mail :to => "to@example.org" + end <% end -%> end diff --git a/railties/lib/generators/rails/metal/templates/metal.rb b/railties/lib/generators/rails/metal/templates/metal.rb index 2f5d4e7593..8cc3f1f258 100644 --- a/railties/lib/generators/rails/metal/templates/metal.rb +++ b/railties/lib/generators/rails/metal/templates/metal.rb @@ -1,5 +1,5 @@ # Allow the metal piece to run in isolation -require File.expand_path('../../../config/environment', __FILE__) +require File.expand_path('../../../config/environment', __FILE__) unless defined?(Rails) class <%= class_name %> def self.call(env) diff --git a/railties/lib/generators/rails/plugin/plugin_generator.rb b/railties/lib/generators/rails/plugin/plugin_generator.rb index b68b8691db..8f01dcd589 100644 --- a/railties/lib/generators/rails/plugin/plugin_generator.rb +++ b/railties/lib/generators/rails/plugin/plugin_generator.rb @@ -17,7 +17,7 @@ module Rails def create_tasks_files return unless options[:tasks] - directory 'tasks', plugin_dir('tasks') + directory 'lib/tasks', plugin_dir('lib/tasks') end hook_for :generator do |generator| diff --git a/railties/lib/generators/rails/plugin/templates/tasks/%file_name%_tasks.rake.tt b/railties/lib/generators/rails/plugin/templates/lib/tasks/%file_name%_tasks.rake.tt index 72920a9d3a..72920a9d3a 100644 --- a/railties/lib/generators/rails/plugin/templates/tasks/%file_name%_tasks.rake.tt +++ b/railties/lib/generators/rails/plugin/templates/lib/tasks/%file_name%_tasks.rake.tt diff --git a/railties/lib/generators/rails/resource/resource_generator.rb b/railties/lib/generators/rails/resource/resource_generator.rb index 43c7cc85f4..5acb839f39 100644 --- a/railties/lib/generators/rails/resource/resource_generator.rb +++ b/railties/lib/generators/rails/resource/resource_generator.rb @@ -6,8 +6,8 @@ module Rails class ResourceGenerator < ModelGenerator #metagenerator include ResourceHelpers - hook_for :resource_controller, :required => true do |base, controller| - base.invoke controller, [ base.controller_name, base.options[:actions] ] + hook_for :resource_controller, :required => true do |controller| + invoke controller, [ controller_name, options[:actions] ] end class_option :actions, :type => :array, :banner => "ACTION ACTION", :default => [], diff --git a/railties/lib/generators/rails/scaffold_controller/scaffold_controller_generator.rb b/railties/lib/generators/rails/scaffold_controller/scaffold_controller_generator.rb index e544e29892..49af2974cd 100644 --- a/railties/lib/generators/rails/scaffold_controller/scaffold_controller_generator.rb +++ b/railties/lib/generators/rails/scaffold_controller/scaffold_controller_generator.rb @@ -18,9 +18,9 @@ module Rails hook_for :template_engine, :test_framework, :as => :scaffold - # Invoke the helper using the controller (pluralized) name. - hook_for :helper, :as => :scaffold do |base, invoked| - base.invoke invoked, [ base.controller_name ] + # Invoke the helper using the controller name (pluralized) + hook_for :helper, :as => :scaffold do |invoked| + invoke invoked, [ controller_name ] end end end diff --git a/railties/lib/generators/test_unit/mailer/templates/fixture b/railties/lib/generators/test_unit/mailer/templates/fixture index fcce7bd805..171648d6fd 100644 --- a/railties/lib/generators/test_unit/mailer/templates/fixture +++ b/railties/lib/generators/test_unit/mailer/templates/fixture @@ -1,3 +1,3 @@ <%= class_name %>#<%= @action %> -Find me in app/views/<%= @path %> +Hi, find me in app/views/<%= @path %> diff --git a/railties/lib/generators/test_unit/mailer/templates/functional_test.rb b/railties/lib/generators/test_unit/mailer/templates/functional_test.rb index 4de94076e9..e1aeb2db90 100644 --- a/railties/lib/generators/test_unit/mailer/templates/functional_test.rb +++ b/railties/lib/generators/test_unit/mailer/templates/functional_test.rb @@ -3,11 +3,13 @@ require 'test_helper' class <%= class_name %>Test < ActionMailer::TestCase <% for action in actions -%> test "<%= action %>" do - @expected.subject = '<%= class_name %>#<%= action %>' - @expected.body = read_fixture('<%= action %>') + @expected.subject = <%= action.to_s.humanize.inspect %> + @expected.to = "to@example.org" + @expected.from = "from@example.com" + @expected.body = read_fixture("<%= action %>") @expected.date = Time.now - assert_equal @expected.encoded, <%= class_name %>.create_<%= action %>(@expected.date).encoded + assert_equal @expected, <%= class_name %>.<%= action %> end <% end -%> diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb index 0bc7160815..b7a39fd5a7 100644 --- a/railties/lib/rails.rb +++ b/railties/lib/rails.rb @@ -4,19 +4,13 @@ require 'active_support' require 'active_support/core_ext/kernel/reporting' require 'active_support/core_ext/logger' -require 'rails/initializable' require 'rails/application' -require 'rails/railtie' -require 'rails/plugin' -require 'rails/railties_path' require 'rails/version' -require 'rails/rack' -require 'rails/paths' -require 'rails/configuration' require 'rails/deprecation' require 'rails/subscriber' require 'rails/ruby_version_check' +require 'active_support/railtie' require 'action_dispatch/railtie' # For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the @@ -32,8 +26,6 @@ else end module Rails - autoload :Bootstrap, 'rails/bootstrap' - class << self def application @@application ||= nil diff --git a/railties/lib/rails/all.rb b/railties/lib/rails/all.rb index 7dfe2b8b63..1a0b4a8d73 100644 --- a/railties/lib/rails/all.rb +++ b/railties/lib/rails/all.rb @@ -1,12 +1,14 @@ require "rails" %w( + active_support active_model active_record action_controller action_view action_mailer active_resource + rails/test_unit ).each do |framework| begin require "#{framework}/railtie" diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 8366127476..9384492486 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -1,118 +1,93 @@ -require "fileutils" -require 'active_support/core_ext/module/delegation' +require 'fileutils' +require 'rails/railties_path' +require 'rails/plugin' +require 'rails/engine' module Rails - class Application - include Initializable + class Application < Engine + autoload :Bootstrap, 'rails/application/bootstrap' + autoload :Configurable, 'rails/application/configurable' + autoload :Configuration, 'rails/application/configuration' + autoload :Finisher, 'rails/application/finisher' + autoload :MetalLoader, 'rails/application/metal_loader' + autoload :Railties, 'rails/application/railties' + autoload :RoutesReloader, 'rails/application/routes_reloader' class << self - attr_writer :config - alias configure class_eval - delegate :call, - :initialize!, - :load_generators, - :load_tasks, - :middleware, - :root, - :to => :instance - private :new + alias :configure :class_eval + def instance - @instance ||= new + if self == Rails::Application + Rails.application + else + @@instance ||= new + end end - def config - @config ||= Configuration.new(Plugin::Configuration.default) + def inherited(base) + raise "You cannot have more than one Rails::Application" if Rails.application + super + Rails.application = base.instance end - def routes - ActionController::Routing::Routes + def respond_to?(*args) + super || instance.respond_to?(*args) end - end - delegate :config, :routes, :to => :'self.class' - delegate :root, :middleware, :to => :config - attr_reader :route_configuration_files + protected - def initialize - require_environment - Rails.application ||= self - @route_configuration_files = [] + def method_missing(*args, &block) + instance.send(*args, &block) + end end - def initialize! - run_initializers(self) - self + def require_environment! + environment = config.paths.config.environment.to_a.first + require environment if environment end - def require_environment - require config.environment_path - rescue LoadError + def routes + ::ActionController::Routing::Routes end - def routes_changed_at - routes_changed_at = nil - - route_configuration_files.each do |config| - config_changed_at = File.stat(config).mtime + def railties + @railties ||= Railties.new(config) + end - if routes_changed_at.nil? || config_changed_at > routes_changed_at - routes_changed_at = config_changed_at - end - end + def metal_loader + @metal_laoder ||= MetalLoader.new + end - routes_changed_at + def routes_reloader + @routes_reloader ||= RoutesReloader.new end def reload_routes! - routes.disable_clear_and_finalize = true - - routes.clear! - route_configuration_files.each { |config| load(config) } - routes.finalize! + routes_reloader.reload! + end - nil - ensure - routes.disable_clear_and_finalize = false + def initialize! + run_initializers(self) + self end def load_tasks - require "rails/tasks" - plugins.each { |p| p.load_tasks } - # Load all application tasks - # TODO: extract out the path to the rake tasks - Dir["#{root}/lib/tasks/**/*.rake"].sort.each { |ext| load ext } - task :environment do - $rails_rake_task = true - initialize! - end + initialize_tasks + super + railties.all { |r| r.load_tasks } + self end def load_generators - plugins.each { |p| p.load_generators } - end - - def initializers - initializers = Bootstrap.new(self).initializers - plugins.each { |p| initializers += p.initializers } - initializers += super - initializers - end - - # TODO: Fix this method. It loads all railties independent if :all is given - # or not, otherwise frameworks are never loaded. - def plugins - @plugins ||= begin - plugin_names = (config.plugins || [:all]).map { |p| p.to_sym } - Railtie.plugins.map(&:new) + Plugin.all(plugin_names, config.paths.vendor.plugins) - end + initialize_generators + super + railties.all { |r| r.load_generators } + self end def app - @app ||= begin - reload_routes! - middleware.build(routes) - end + @app ||= middleware.build(routes) end def call(env) @@ -120,42 +95,31 @@ module Rails app.call(env) end - initializer :load_application_initializers do - Dir["#{root}/config/initializers/**/*.rb"].sort.each do |initializer| - load(initializer) - end + def initializers + initializers = Bootstrap.initializers_for(self) + railties.all { |r| initializers += r.initializers } + initializers += super + initializers += Finisher.initializers_for(self) + initializers end - initializer :build_middleware_stack do - app - end + protected - # Fires the user-supplied after_initialize block (Configuration#after_initialize) - initializer :after_initialize do - config.after_initialize_blocks.each do |block| - block.call + def initialize_tasks + require "rails/tasks" + task :environment do + $rails_rake_task = true + initialize! end end - # Eager load application classes - initializer :load_application_classes do - next if $rails_rake_task - - if config.cache_classes - config.eager_load_paths.each do |load_path| - matcher = /\A#{Regexp.escape(load_path)}(.*)\.rb\Z/ - Dir.glob("#{load_path}/**/*.rb").sort.each do |file| - require_dependency file.sub(matcher, '\1') - end - end - end + def initialize_generators + require "rails/generators" end - # Disable dependency loading during request cycle - initializer :disable_dependency_loading do - if config.cache_classes && !config.dependency_loading - ActiveSupport::Dependencies.unhook! - end + # Application is always reloadable when config.cache_classes is false. + def reloadable?(app) + true end end end diff --git a/railties/lib/rails/application/bootstrap.rb b/railties/lib/rails/application/bootstrap.rb new file mode 100644 index 0000000000..b20e53f2de --- /dev/null +++ b/railties/lib/rails/application/bootstrap.rb @@ -0,0 +1,85 @@ +module Rails + class Application + module Bootstrap + include Initializable + + initializer :load_environment_config do + require_environment! + end + + initializer :load_all_active_support do + require "active_support/all" unless config.active_support.bare + end + + # Preload all frameworks specified by the Configuration#frameworks. + # Used by Passenger to ensure everything's loaded before forking and + # to avoid autoload race conditions in JRuby. + initializer :preload_frameworks do + require 'active_support/dependencies' + ActiveSupport::Autoload.eager_autoload! if config.preload_frameworks + end + + # Initialize the logger early in the stack in case we need to log some deprecation. + initializer :initialize_logger do + Rails.logger ||= config.logger || begin + path = config.paths.log.to_a.first + logger = ActiveSupport::BufferedLogger.new(path) + logger.level = ActiveSupport::BufferedLogger.const_get(config.log_level.to_s.upcase) + logger.auto_flushing = false if Rails.env.production? + logger + rescue StandardError => e + logger = ActiveSupport::BufferedLogger.new(STDERR) + logger.level = ActiveSupport::BufferedLogger::WARN + logger.warn( + "Rails Error: Unable to access log file. Please ensure that #{path} exists and is chmod 0666. " + + "The log level has been raised to WARN and the output directed to STDERR until the problem is fixed." + ) + logger + end + end + + # Initialize cache early in the stack so railties can make use of it. + initializer :initialize_cache do + unless defined?(RAILS_CACHE) + silence_warnings { Object.const_set "RAILS_CACHE", ActiveSupport::Cache.lookup_store(config.cache_store) } + + if RAILS_CACHE.respond_to?(:middleware) + config.middleware.insert_after(:"Rack::Lock", RAILS_CACHE.middleware) + end + end + end + + # Initialize rails subscriber on top of notifications. + initializer :initialize_subscriber do + require 'active_support/notifications' + + if config.colorize_logging == false + Rails::Subscriber.colorize_logging = false + config.generators.colorize_logging = false + end + + ActiveSupport::Notifications.subscribe do |*args| + Rails::Subscriber.dispatch(args) + end + end + + initializer :set_clear_dependencies_hook do + unless config.cache_classes + ActionDispatch::Callbacks.after do + ActiveSupport::Dependencies.clear + end + end + end + + # Sets the dependency loading mechanism. + # TODO: Remove files from the $" and always use require. + initializer :initialize_dependency_mechanism do + ActiveSupport::Dependencies.mechanism = config.cache_classes ? :require : :load + end + + initializer :bootstrap_load_path do + # This is just an initializer used as hook so all load paths are loaded together + end + end + end +end
\ No newline at end of file diff --git a/railties/lib/rails/application/configurable.rb b/railties/lib/rails/application/configurable.rb new file mode 100644 index 0000000000..f598e33965 --- /dev/null +++ b/railties/lib/rails/application/configurable.rb @@ -0,0 +1,19 @@ +module Rails + class Application + module Configurable + def self.included(base) + base.extend ClassMethods + end + + module ClassMethods + def inherited(base) + raise "You cannot inherit from a Rails::Application child" + end + end + + def config + @config ||= Application::Configuration.new(self.class.find_root_with_flag("config.ru", Dir.pwd)) + end + end + end +end
\ No newline at end of file diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb new file mode 100644 index 0000000000..31787b5cc9 --- /dev/null +++ b/railties/lib/rails/application/configuration.rb @@ -0,0 +1,84 @@ +require 'rails/engine/configuration' + +module Rails + class Application + class Configuration < ::Rails::Engine::Configuration + include ::Rails::Configuration::Deprecated + + attr_accessor :cache_classes, :cache_store, :colorize_logging, + :consider_all_requests_local, :dependency_loading, + :filter_parameters, :log_level, :logger, :metals, + :plugins, :preload_frameworks, :reload_engines, :reload_plugins, + :serve_static_assets, :time_zone, :whiny_nils + + def initialize(*) + super + @colorize_logging = true + @filter_parameters = [] + @dependency_loading = true + @serve_static_assets = true + @time_zone = "UTC" + end + + def paths + @paths ||= begin + paths = super + paths.app.controllers << builtin_controller if builtin_controller + paths.config.database "config/database.yml" + paths.config.environment "config/environments", :glob => "#{Rails.env}.rb" + paths.log "log/#{Rails.env}.log" + paths.tmp "tmp" + paths.tmp.cache "tmp/cache" + paths.vendor "vendor", :load_path => true + paths.vendor.plugins "vendor/plugins" + + if File.exists?("#{root}/test/mocks/#{Rails.env}") + ActiveSupport::Deprecation.warn "\"RAILS_ROOT/test/mocks/#{Rails.env}\" won't be added " << + "automatically to load paths anymore in future releases" + paths.mocks_path "test/mocks", :load_path => true, :glob => Rails.env + end + + paths + end + end + + # Enable threaded mode. Allows concurrent requests to controller actions and + # multiple database connections. Also disables automatic dependency loading + # after boot, and disables reloading code on every request, as these are + # fundamentally incompatible with thread safety. + def threadsafe! + self.preload_frameworks = true + self.cache_classes = true + self.dependency_loading = false + self.action_controller.allow_concurrency = true if respond_to?(:action_controller) + self + end + + # Loads and returns the contents of the #database_configuration_file. The + # contents of the file are processed via ERB before being sent through + # YAML::load. + def database_configuration + require 'erb' + YAML::load(ERB.new(IO.read(paths.config.database.to_a.first)).result) + end + + def cache_store + @cache_store ||= begin + if File.exist?("#{root}/tmp/cache/") + [ :file_store, "#{root}/tmp/cache/" ] + else + :memory_store + end + end + end + + def builtin_controller + File.join(RAILTIES_PATH, "builtin", "rails_info") if Rails.env.development? + end + + def log_level + @log_level ||= Rails.env.production? ? :info : :debug + end + end + end +end
\ No newline at end of file diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb new file mode 100644 index 0000000000..b722679ec2 --- /dev/null +++ b/railties/lib/rails/application/finisher.rb @@ -0,0 +1,49 @@ +module Rails + class Application + module Finisher + include Initializable + + initializer :ensure_load_once_paths_as_subset do + extra = ActiveSupport::Dependencies.load_once_paths - + ActiveSupport::Dependencies.load_paths + + unless extra.empty? + abort <<-end_error + load_once_paths must be a subset of the load_paths. + Extra items in load_once_paths: #{extra * ','} + end_error + end + end + + initializer :add_to_prepare_blocks do + config.to_prepare_blocks.each do |block| + ActionDispatch::Callbacks.to_prepare(&block) + end + end + + initializer :add_builtin_route do |app| + if Rails.env.development? + app.routes_reloader.paths << File.join(RAILTIES_PATH, 'builtin', 'routes.rb') + end + end + + initializer :build_middleware_stack do + app + end + + # Fires the user-supplied after_initialize block (config.after_initialize) + initializer :after_initialize do + config.after_initialize_blocks.each do |block| + block.call(self) + end + end + + # Disable dependency loading during request cycle + initializer :disable_dependency_loading do + if config.cache_classes && !config.dependency_loading + ActiveSupport::Dependencies.unhook! + end + end + end + end +end
\ No newline at end of file diff --git a/railties/lib/rails/application/metal_loader.rb b/railties/lib/rails/application/metal_loader.rb new file mode 100644 index 0000000000..c0f2e4f948 --- /dev/null +++ b/railties/lib/rails/application/metal_loader.rb @@ -0,0 +1,50 @@ +require 'action_dispatch' + +module Rails + class Application + class MetalLoader + attr_reader :paths, :metals + + def initialize + @paths, @metals = [], [] + end + + def build_middleware(list=nil) + load_metals!(list) + self + end + + def new(app) + ActionDispatch::Cascade.new(@metals, app) + end + + def name + ActionDispatch::Cascade.name + end + alias :to_s :name + + protected + + def load_metals!(list) + metals = [] + list = Array(list || :all).map(&:to_sym) + + paths.each do |path| + matcher = /\A#{Regexp.escape(path)}\/(.*)\.rb\Z/ + Dir.glob("#{path}/**/*.rb").sort.each do |metal_path| + metal = metal_path.sub(matcher, '\1').to_sym + next unless list.include?(metal) || list.include?(:all) + require_dependency metal + metals << metal + end + end + + metals = metals.sort_by do |m| + [list.index(m) || list.index(:all), m.to_s] + end + + @metals = metals.map { |m| m.to_s.camelize.constantize } + end + end + end +end diff --git a/railties/lib/rails/application/railties.rb b/railties/lib/rails/application/railties.rb new file mode 100644 index 0000000000..b3e6693f89 --- /dev/null +++ b/railties/lib/rails/application/railties.rb @@ -0,0 +1,31 @@ +module Rails + class Application + class Railties + # TODO Write tests for this behavior extracted from Application + def initialize(config) + @config = config + end + + def all(&block) + @all ||= railties + engines + plugins + @all.each(&block) if block + @all + end + + def railties + @railties ||= ::Rails::Railtie.subclasses.map(&:new) + end + + def engines + @engines ||= ::Rails::Engine.subclasses.map(&:new) + end + + def plugins + @plugins ||= begin + plugin_names = (@config.plugins || [:all]).map { |p| p.to_sym } + Plugin.all(plugin_names, @config.paths.vendor.plugins) + end + end + end + end +end
\ No newline at end of file diff --git a/railties/lib/rails/application/routes_reloader.rb b/railties/lib/rails/application/routes_reloader.rb new file mode 100644 index 0000000000..fde6211c5d --- /dev/null +++ b/railties/lib/rails/application/routes_reloader.rb @@ -0,0 +1,46 @@ +module Rails + class Application + class RoutesReloader + attr_reader :paths + + def initialize + @paths, @last_change_at = [], nil + end + + def changed_at + routes_changed_at = nil + + paths.each do |path| + config_changed_at = File.stat(path).mtime + + if routes_changed_at.nil? || config_changed_at > routes_changed_at + routes_changed_at = config_changed_at + end + end + + routes_changed_at + end + + def reload! + routes = Rails::Application.routes + routes.disable_clear_and_finalize = true + + routes.clear! + paths.each { |path| load(path) } + routes.finalize! + + nil + ensure + routes.disable_clear_and_finalize = false + end + + def reload_if_changed + current_change_at = changed_at + if @last_change_at != current_change_at + @last_change_at = current_change_at + reload! + end + end + end + end +end
\ No newline at end of file diff --git a/railties/lib/rails/bootstrap.rb b/railties/lib/rails/bootstrap.rb deleted file mode 100644 index 5db663f9ef..0000000000 --- a/railties/lib/rails/bootstrap.rb +++ /dev/null @@ -1,161 +0,0 @@ -module Rails - class Bootstrap #< Railtie - include Initializable - - def initialize(application) - @application = application - end - - delegate :config, :root, :to => :'@application' - - initializer :load_all_active_support do - require "active_support/all" unless config.active_support.bare - end - - # Set the <tt>$LOAD_PATH</tt> based on the value of - # Configuration#load_paths. Duplicates are removed. - initializer :set_load_path do - config.paths.add_to_load_path - $LOAD_PATH.uniq! - end - - # Set the paths from which Rails will automatically load source files, and - # the load_once paths. - initializer :set_autoload_paths do - require 'active_support/dependencies' - ActiveSupport::Dependencies.load_paths = expand_load_path(config.load_paths) - ActiveSupport::Dependencies.load_once_paths = expand_load_path(config.load_once_paths) - - extra = ActiveSupport::Dependencies.load_once_paths - ActiveSupport::Dependencies.load_paths - unless extra.empty? - abort <<-end_error - load_once_paths must be a subset of the load_paths. - Extra items in load_once_paths: #{extra * ','} - end_error - end - - # Freeze the arrays so future modifications will fail rather than do nothing mysteriously - config.load_once_paths.freeze - end - - # Create tmp directories - initializer :ensure_tmp_directories_exist do - %w(cache pids sessions sockets).each do |dir_to_make| - FileUtils.mkdir_p(File.join(root, 'tmp', dir_to_make)) - end - end - - # Preload all frameworks specified by the Configuration#frameworks. - # Used by Passenger to ensure everything's loaded before forking and - # to avoid autoload race conditions in JRuby. - initializer :preload_frameworks do - ActiveSupport::Autoload.eager_autoload! if config.preload_frameworks - end - - initializer :initialize_cache do - unless defined?(RAILS_CACHE) - silence_warnings { Object.const_set "RAILS_CACHE", ActiveSupport::Cache.lookup_store(config.cache_store) } - - if RAILS_CACHE.respond_to?(:middleware) - # Insert middleware to setup and teardown local cache for each request - config.middleware.insert_after(:"Rack::Lock", RAILS_CACHE.middleware) - end - end - end - - initializer :initialize_logger do - Rails.logger ||= config.logger || begin - logger = ActiveSupport::BufferedLogger.new(config.log_path) - logger.level = ActiveSupport::BufferedLogger.const_get(config.log_level.to_s.upcase) - logger.auto_flushing = false if Rails.env.production? - logger - rescue StandardError => e - logger = ActiveSupport::BufferedLogger.new(STDERR) - logger.level = ActiveSupport::BufferedLogger::WARN - logger.warn( - "Rails Error: Unable to access log file. Please ensure that #{config.log_path} exists and is chmod 0666. " + - "The log level has been raised to WARN and the output directed to STDERR until the problem is fixed." - ) - logger - end - end - - # Sets the logger for dependencies and cache store. - initializer :initialize_framework_logging do - ActiveSupport::Dependencies.logger ||= Rails.logger - Rails.cache.logger ||= Rails.logger - end - - # Sets the dependency loading mechanism based on the value of - # Configuration#cache_classes. - initializer :initialize_dependency_mechanism do - # TODO: Remove files from the $" and always use require - ActiveSupport::Dependencies.mechanism = config.cache_classes ? :require : :load - end - - # Loads support for "whiny nil" (noisy warnings when methods are invoked - # on +nil+ values) if Configuration#whiny_nils is true. - initializer :initialize_whiny_nils do - require 'active_support/whiny_nil' if config.whiny_nils - end - - # Sets the default value for Time.zone - # If assigned value cannot be matched to a TimeZone, an exception will be raised. - initializer :initialize_time_zone do - require 'active_support/core_ext/time/zones' - zone_default = Time.__send__(:get_zone, config.time_zone) - - unless zone_default - raise \ - 'Value assigned to config.time_zone not recognized.' + - 'Run "rake -D time" for a list of tasks for finding appropriate time zone names.' - end - - Time.zone_default = zone_default - end - - # Set the i18n configuration from config.i18n but special-case for the load_path which should be - # appended to what's already set instead of overwritten. - initializer :initialize_i18n do - require 'active_support/i18n' - - config.i18n.each do |setting, value| - if setting == :load_path - I18n.load_path += value - else - I18n.send("#{setting}=", value) - end - end - - ActionDispatch::Callbacks.to_prepare do - I18n.reload! - end - end - - initializer :set_clear_dependencies_hook do - unless config.cache_classes - ActionDispatch::Callbacks.after do - ActiveSupport::Dependencies.clear - end - end - end - - initializer :initialize_notifications do - require 'active_support/notifications' - - if config.colorize_logging == false - Rails::Subscriber.colorize_logging = false - config.generators.colorize_logging = false - end - - ActiveSupport::Notifications.subscribe do |*args| - Rails::Subscriber.dispatch(args) - end - end - - private - def expand_load_path(load_paths) - load_paths.map { |path| Dir.glob(path.to_s) }.flatten.uniq - end - end -end diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb index 27ac7fd20a..a984eff6e2 100644 --- a/railties/lib/rails/commands/console.rb +++ b/railties/lib/rails/commands/console.rb @@ -1,6 +1,6 @@ require 'optparse' require 'irb' -require "irb/completion" +require 'irb/completion' module Rails class Console @@ -24,9 +24,9 @@ module Rails end @app.initialize! - require "rails/console_app" - require "rails/console_sandbox" if options[:sandbox] - require "rails/console_with_helpers" + require "rails/console/app" + require "rails/console/sandbox" if options[:sandbox] + require "rails/console/helpers" if options[:debugger] begin diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 7f1783a6b9..a95075562f 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -1,294 +1,90 @@ require 'active_support/ordered_options' +require 'rails/paths' +require 'rails/rack' module Rails - # Temporarily separate the plugin configuration class from the main - # configuration class while this bit is being cleaned up. - class Railtie::Configuration - def self.default - @default ||= new - end - - def self.default_middleware_stack - ActionDispatch::MiddlewareStack.new.tap do |middleware| - middleware.use('::ActionDispatch::Static', lambda { Rails.public_path }, :if => lambda { Rails.application.config.serve_static_assets }) - middleware.use('::Rack::Lock', :if => lambda { !ActionController::Base.allow_concurrency }) - middleware.use('::Rack::Runtime') - middleware.use('::Rails::Rack::Logger') - middleware.use('::ActionDispatch::ShowExceptions', lambda { ActionController::Base.consider_all_requests_local }) - middleware.use('::ActionDispatch::Callbacks', lambda { !Rails.application.config.cache_classes }) - middleware.use('::ActionDispatch::Cookies') - middleware.use(lambda { ActionController::Base.session_store }, lambda { ActionController::Base.session_options }) - middleware.use('::ActionDispatch::Flash', :if => lambda { ActionController::Base.session_store }) - middleware.use(lambda { Rails::Rack::Metal.new(Rails.application.config.paths.app.metals.to_a, Rails.application.config.metals) }) - middleware.use('ActionDispatch::ParamsParser') - middleware.use('::Rack::MethodOverride') - middleware.use('::ActionDispatch::Head') - end - end - - attr_reader :middleware - - def initialize(base = nil) - if base - @options = base.options.dup - @middleware = base.middleware.dup - else - @options = Hash.new { |h,k| h[k] = ActiveSupport::OrderedOptions.new } - @middleware = self.class.default_middleware_stack - end - end - - def respond_to?(name) - super || name.to_s =~ config_key_regexp - end - - protected - - attr_reader :options - - private - - def method_missing(name, *args, &blk) - if name.to_s =~ config_key_regexp - return $2 == '=' ? @options[$1] = args.first : @options[$1] + module Configuration + module Shared + def middleware + @@default_middleware_stack ||= ActionDispatch::MiddlewareStack.new.tap do |middleware| + middleware.use('::ActionDispatch::Static', lambda { Rails.public_path }, :if => lambda { Rails.application.config.serve_static_assets }) + middleware.use('::Rack::Lock', :if => lambda { !ActionController::Base.allow_concurrency }) + middleware.use('::Rack::Runtime') + middleware.use('::Rails::Rack::Logger') + middleware.use('::ActionDispatch::ShowExceptions', lambda { ActionController::Base.consider_all_requests_local }) + middleware.use('::ActionDispatch::Callbacks', lambda { !Rails.application.config.cache_classes }) + middleware.use('::ActionDispatch::Cookies') + middleware.use(lambda { ActionController::Base.session_store }, lambda { ActionController::Base.session_options }) + middleware.use('::ActionDispatch::Flash', :if => lambda { ActionController::Base.session_store }) + middleware.use(lambda { Rails.application.metal_loader.build_middleware(Rails.application.config.metals) }, :if => lambda { Rails.application.metal_loader.metals.any? }) + middleware.use('ActionDispatch::ParamsParser') + middleware.use('::Rack::MethodOverride') + middleware.use('::ActionDispatch::Head') + end end - super - end - - def config_key_regexp - bits = config_keys.map { |n| Regexp.escape(n.to_s) }.join('|') - /^(#{bits})(?:=)?$/ - end - - def config_keys - ([ :active_support, :action_view ] + - Railtie.plugin_names).map { |n| n.to_s }.uniq - end - end - - class Configuration < Railtie::Configuration - attr_accessor :after_initialize_blocks, :cache_classes, :colorize_logging, - :consider_all_requests_local, :dependency_loading, :filter_parameters, - :load_once_paths, :logger, :metals, :plugins, - :preload_frameworks, :reload_plugins, :serve_static_assets, - :time_zone, :whiny_nils - - attr_writer :cache_store, :controller_paths, - :database_configuration_file, :eager_load_paths, - :i18n, :load_paths, :log_level, :log_path, :paths, - :routes_configuration_file, :view_path - - def initialize(base = nil) - super - @load_once_paths = [] - @after_initialize_blocks = [] - @filter_parameters = [] - @dependency_loading = true - @serve_static_assets = true - end - - def after_initialize(&blk) - @after_initialize_blocks << blk if blk - end - - def root - @root ||= begin - call_stack = caller.map { |p| p.split(':').first } - root_path = call_stack.detect { |p| p !~ %r[railties/lib/rails|rack/lib/rack] } - root_path = File.dirname(root_path) - - while root_path && File.directory?(root_path) && !File.exist?("#{root_path}/config.ru") - parent = File.dirname(root_path) - root_path = parent != root_path && parent + # Holds generators configuration: + # + # config.generators do |g| + # g.orm :datamapper, :migration => true + # g.template_engine :haml + # g.test_framework :rspec + # end + # + # If you want to disable color in console, do: + # + # config.generators.colorize_logging = false + # + def generators + @@generators ||= Rails::Configuration::Generators.new + if block_given? + yield @@generators + else + @@generators end - - root = File.exist?("#{root_path}/config.ru") ? root_path : Dir.pwd - - RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? - Pathname.new(root).expand_path : - Pathname.new(root).realpath end - end - - def root=(root) - @root = Pathname.new(root).expand_path - end - def paths - @paths ||= begin - paths = Rails::Application::Root.new(root) - paths.app "app", :load_path => true - paths.app.metals "app/metal", :eager_load => true - paths.app.models "app/models", :eager_load => true - paths.app.controllers "app/controllers", builtin_directories, :eager_load => true - paths.app.helpers "app/helpers", :eager_load => true - paths.app.services "app/services", :load_path => true - paths.lib "lib", :load_path => true - paths.vendor "vendor", :load_path => true - paths.vendor.plugins "vendor/plugins" - paths.tmp "tmp" - paths.tmp.cache "tmp/cache" - paths.config "config" - paths.config.locales "config/locales" - paths.config.environments "config/environments", :glob => "#{Rails.env}.rb" - paths + def after_initialize_blocks + @@after_initialize_blocks ||= [] end - end - - def frameworks(*args) - raise "config.frameworks in no longer supported. See the generated " \ - "config/boot.rb for steps on how to limit the frameworks that " \ - "will be loaded" - end - alias frameworks= frameworks - - # Enable threaded mode. Allows concurrent requests to controller actions and - # multiple database connections. Also disables automatic dependency loading - # after boot, and disables reloading code on every request, as these are - # fundamentally incompatible with thread safety. - def threadsafe! - self.preload_frameworks = true - self.cache_classes = true - self.dependency_loading = false - if respond_to?(:action_controller) - action_controller.allow_concurrency = true + def after_initialize(&blk) + after_initialize_blocks << blk if blk end - self - end - - # Loads and returns the contents of the #database_configuration_file. The - # contents of the file are processed via ERB before being sent through - # YAML::load. - def database_configuration - require 'erb' - YAML::load(ERB.new(IO.read(database_configuration_file)).result) - end - - def routes_configuration_file - @routes_configuration_file ||= File.join(root, 'config', 'routes.rb') - end - - def builtin_routes_configuration_file - @builtin_routes_configuration_file ||= File.join(RAILTIES_PATH, 'builtin', 'routes.rb') - end - def controller_paths - @controller_paths ||= begin - paths = [File.join(root, 'app', 'controllers')] - paths.concat builtin_directories - paths + def to_prepare_blocks + @@to_prepare_blocks ||= [] end - end - def cache_store - @cache_store ||= begin - if File.exist?("#{root}/tmp/cache/") - [ :file_store, "#{root}/tmp/cache/" ] - else - :memory_store - end + def to_prepare(&blk) + to_prepare_blocks << blk if blk end - end - - def database_configuration_file - @database_configuration_file ||= File.join(root, 'config', 'database.yml') - end - - def view_path - @view_path ||= File.join(root, 'app', 'views') - end - - def eager_load_paths - @eager_load_paths ||= ["#{root}/app/*"] - end - def load_paths - @load_paths ||= begin - paths = [] - - # Add the old mock paths only if the directories exists - paths.concat(Dir["#{root}/test/mocks/#{Rails.env}"]) if File.exists?("#{root}/test/mocks/#{Rails.env}") - - # Followed by the standard includes. - paths.concat %w( - app - app/* - lib - vendor - ).map { |dir| "#{root}/#{dir}" } - - paths.concat builtin_directories + def respond_to?(name) + super || name.to_s =~ config_key_regexp end - end - def builtin_directories - # Include builtins only in the development environment. - Rails.env.development? ? Dir["#{RAILTIES_PATH}/builtin/*/"] : [] - end + private - def log_path - @log_path ||= File.join(root, 'log', "#{Rails.env}.log") - end - - def log_level - @log_level ||= Rails.env.production? ? :info : :debug - end - - def time_zone - @time_zone ||= "UTC" - end - - def i18n - @i18n ||= begin - i18n = ActiveSupport::OrderedOptions.new - i18n.load_path = [] - - if File.exist?(File.join(root, 'config', 'locales')) - i18n.load_path << Dir[File.join(root, 'config', 'locales', '*.{rb,yml}')] - i18n.load_path.flatten! + def method_missing(name, *args, &blk) + if name.to_s =~ config_key_regexp + return $2 == '=' ? options[$1] = args.first : options[$1] end - - i18n + super end - end - def environment_path - "#{root}/config/environments/#{Rails.env}.rb" - end + def config_key_regexp + bits = config_keys.map { |n| Regexp.escape(n.to_s) }.join('|') + /^(#{bits})(?:=)?$/ + end - # Holds generators configuration: - # - # config.generators do |g| - # g.orm :datamapper, :migration => true - # g.template_engine :haml - # g.test_framework :rspec - # end - # - # If you want to disable color in console, do: - # - # config.generators.colorize_logging = false - # - def generators - @generators ||= Generators.new - if block_given? - yield @generators - else - @generators + def config_keys + (Railtie.railtie_names + Engine.engine_names).map { |n| n.to_s }.uniq end - end - # Allow Notifications queue to be modified or add subscriptions: - # - # config.notifications.queue = MyNewQueue.new - # - # config.notifications.subscribe /action_dispatch.show_exception/ do |*args| - # ExceptionDeliver.deliver_exception(args) - # end - # - def notifications - ActiveSupport::Notifications + def options + @@options ||= Hash.new { |h,k| h[k] = ActiveSupport::OrderedOptions.new } + end end class Generators #:nodoc: @@ -303,6 +99,8 @@ module Rails def method_missing(method, *args) method = method.to_s.sub(/=$/, '').to_sym + return @options[method] if args.empty? + if method == :rails namespace, configuration = :rails, args.shift elsif args.first.is_a?(Hash) @@ -319,5 +117,74 @@ module Rails end end end + + module Deprecated + def frameworks(*args) + raise "config.frameworks in no longer supported. See the generated " \ + "config/boot.rb for steps on how to limit the frameworks that " \ + "will be loaded" + end + alias :frameworks= :frameworks + + def view_path=(value) + ActiveSupport::Deprecation.warn "config.view_path= is deprecated, " << + "please do config.paths.app.views= instead", caller + paths.app.views = value + end + + def view_path + ActiveSupport::Deprecation.warn "config.view_path is deprecated, " << + "please do config.paths.app.views instead", caller + paths.app.views.to_a.first + end + + def routes_configuration_file=(value) + ActiveSupport::Deprecation.warn "config.routes_configuration_file= is deprecated, " << + "please do config.paths.config.routes= instead", caller + paths.config.routes = value + end + + def routes_configuration_file + ActiveSupport::Deprecation.warn "config.routes_configuration_file is deprecated, " << + "please do config.paths.config.routes instead", caller + paths.config.routes.to_a.first + end + + def database_configuration_file=(value) + ActiveSupport::Deprecation.warn "config.database_configuration_file= is deprecated, " << + "please do config.paths.config.database= instead", caller + paths.config.database = value + end + + def database_configuration_file + ActiveSupport::Deprecation.warn "config.database_configuration_file is deprecated, " << + "please do config.paths.config.database instead", caller + paths.config.database.to_a.first + end + + def log_path=(value) + ActiveSupport::Deprecation.warn "config.log_path= is deprecated, " << + "please do config.paths.log= instead", caller + paths.config.log = value + end + + def log_path + ActiveSupport::Deprecation.warn "config.log_path is deprecated, " << + "please do config.paths.log instead", caller + paths.config.log.to_a.first + end + + def controller_paths=(value) + ActiveSupport::Deprecation.warn "config.controller_paths= is deprecated, " << + "please do config.paths.app.controllers= instead", caller + paths.app.controllers = value + end + + def controller_paths + ActiveSupport::Deprecation.warn "config.controller_paths is deprecated, " << + "please do config.paths.app.controllers instead", caller + paths.app.controllers.to_a.uniq + end + end end end diff --git a/railties/lib/rails/console_app.rb b/railties/lib/rails/console/app.rb index 2c4a7a51e8..7e8fd027e6 100644 --- a/railties/lib/rails/console_app.rb +++ b/railties/lib/rails/console/app.rb @@ -23,10 +23,11 @@ def new_session session end -#reloads the environment -def reload! - puts "Reloading..." - ActionDispatch::Callbacks.new(lambda {}, true) - Rails.application.reload_routes! +# reloads the environment +def reload!(print=true) + puts "Reloading..." if print + ActionDispatch::Callbacks.new(lambda {}, false) true end + +reload!(false) diff --git a/railties/lib/rails/console_with_helpers.rb b/railties/lib/rails/console/helpers.rb index 039db667c4..039db667c4 100644 --- a/railties/lib/rails/console_with_helpers.rb +++ b/railties/lib/rails/console/helpers.rb diff --git a/railties/lib/rails/console_sandbox.rb b/railties/lib/rails/console/sandbox.rb index 65a3d68619..65a3d68619 100644 --- a/railties/lib/rails/console_sandbox.rb +++ b/railties/lib/rails/console/sandbox.rb diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb new file mode 100644 index 0000000000..33d62c8155 --- /dev/null +++ b/railties/lib/rails/engine.rb @@ -0,0 +1,130 @@ +require 'active_support/core_ext/module/delegation' +require 'rails/railtie' + +module Rails + class Engine < Railtie + autoload :Configurable, "rails/engine/configurable" + autoload :Configuration, "rails/engine/configuration" + + class << self + attr_accessor :called_from + + alias :engine_name :railtie_name + alias :engine_names :railtie_names + + def inherited(base) + unless abstract_railtie?(base) + base.called_from = begin + call_stack = caller.map { |p| p.split(':').first } + File.dirname(call_stack.detect { |p| p !~ %r[railties/lib/rails|rack/lib/rack] }) + end + end + + super + end + + def find_root_with_flag(flag, default=nil) + root_path = self.called_from + + while root_path && File.directory?(root_path) && !File.exist?("#{root_path}/#{flag}") + parent = File.dirname(root_path) + root_path = parent != root_path && parent + end + + root = File.exist?("#{root_path}/#{flag}") ? root_path : default + raise "Could not find root path for #{self}" unless root + + RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? + Pathname.new(root).expand_path : Pathname.new(root).realpath + end + end + + delegate :middleware, :paths, :root, :to => :config + + def load_tasks + super + config.paths.lib.tasks.to_a.sort.each { |ext| load(ext) } + end + + # Add configured load paths to ruby load paths and remove duplicates. + initializer :set_load_path, :before => :bootstrap_load_path do + config.load_paths.reverse_each do |path| + $LOAD_PATH.unshift(path) if File.directory?(path) + end + $LOAD_PATH.uniq! + end + + # Set the paths from which Rails will automatically load source files, + # and the load_once paths. + initializer :set_autoload_paths, :before => :bootstrap_load_path do |app| + ActiveSupport::Dependencies.load_paths.unshift(*config.load_paths) + + if reloadable?(app) + ActiveSupport::Dependencies.load_once_paths.unshift(*config.load_once_paths) + else + ActiveSupport::Dependencies.load_once_paths.unshift(*config.load_paths) + end + + # Freeze so future modifications will fail rather than do nothing mysteriously + config.load_paths.freeze + config.load_once_paths.freeze + end + + initializer :add_routing_paths do |app| + paths.config.routes.to_a.each do |route| + app.routes_reloader.paths.unshift(route) if File.exists?(route) + end + end + + initializer :add_routing_namespaces do |app| + paths.app.controllers.to_a.each do |load_path| + load_path = File.expand_path(load_path) + Dir["#{load_path}/*/*_controller.rb"].collect do |path| + namespace = File.dirname(path).sub(/#{load_path}\/?/, '') + app.routes.controller_namespaces << namespace unless namespace.empty? + end + end + end + + # I18n load paths are a special case since the ones added + # later have higher priority. + initializer :add_locales do + config.i18n.engines_load_path.concat(paths.config.locales.to_a) + end + + initializer :add_view_paths do + views = paths.app.views.to_a + ActionController::Base.view_paths.unshift(*views) if defined?(ActionController) + ActionMailer::Base.view_paths.unshift(*views) if defined?(ActionMailer) + end + + initializer :add_metals do |app| + app.metal_loader.paths.unshift(*paths.app.metals.to_a) + end + + initializer :load_application_initializers do + paths.config.initializers.to_a.sort.each do |initializer| + load(initializer) + end + end + + initializer :load_application_classes do |app| + next if $rails_rake_task + + if app.config.cache_classes + config.eager_load_paths.each do |load_path| + matcher = /\A#{Regexp.escape(load_path)}\/(.*)\.rb\Z/ + Dir.glob("#{load_path}/**/*.rb").sort.each do |file| + require_dependency file.sub(matcher, '\1') + end + end + end + end + + protected + + def reloadable?(app) + app.config.reload_engines + end + end +end
\ No newline at end of file diff --git a/railties/lib/rails/engine/configurable.rb b/railties/lib/rails/engine/configurable.rb new file mode 100644 index 0000000000..9a370f0abb --- /dev/null +++ b/railties/lib/rails/engine/configurable.rb @@ -0,0 +1,25 @@ +module Rails + class Engine + module Configurable + def self.included(base) + base.extend ClassMethods + end + + module ClassMethods + delegate :middleware, :root, :paths, :to => :config + + def config + @config ||= Engine::Configuration.new(find_root_with_flag("lib")) + end + + def inherited(base) + raise "You cannot inherit from a Rails::Engine child" + end + end + + def config + self.class.config + end + end + end +end
\ No newline at end of file diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb new file mode 100644 index 0000000000..7d6de91430 --- /dev/null +++ b/railties/lib/rails/engine/configuration.rb @@ -0,0 +1,49 @@ +require 'rails/railtie/configuration' + +module Rails + class Engine + class Configuration < ::Rails::Railtie::Configuration + attr_reader :root + attr_writer :eager_load_paths, :load_once_paths, :load_paths + + def initialize(root=nil) + @root = root + end + + def paths + @paths ||= begin + paths = Rails::Paths::Root.new(@root) + paths.app "app", :eager_load => true, :glob => "*" + paths.app.controllers "app/controllers", :eager_load => true + paths.app.helpers "app/helpers", :eager_load => true + paths.app.models "app/models", :eager_load => true + paths.app.metals "app/metal" + paths.app.views "app/views" + paths.lib "lib", :load_path => true + paths.lib.tasks "lib/tasks", :glob => "**/*.rake" + paths.config "config" + paths.config.initializers "config/initializers", :glob => "**/*.rb" + paths.config.locales "config/locales", :glob => "*.{rb,yml}" + paths.config.routes "config/routes.rb" + paths + end + end + + def root=(value) + @root = paths.path = Pathname.new(value).expand_path + end + + def eager_load_paths + @eager_load_paths ||= paths.eager_load + end + + def load_once_paths + @eager_load_paths ||= paths.load_once + end + + def load_paths + @load_paths ||= paths.load_paths + end + end + end +end
\ No newline at end of file diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 83b8c74966..1271de7af9 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -38,11 +38,6 @@ module Rails } DEFAULT_OPTIONS = { - :active_record => { - :migration => true, - :timestamps => true - }, - :erb => { :layout => true }, @@ -51,20 +46,15 @@ module Rails :force_plural => false, :helper => true, :layout => true, - :orm => :active_record, - :integration_tool => :test_unit, - :performance_tool => :test_unit, + :orm => nil, + :integration_tool => nil, + :performance_tool => nil, :resource_controller => :controller, :scaffold_controller => :scaffold_controller, :singleton => false, :stylesheets => true, - :template_engine => :erb, - :test_framework => :test_unit - }, - - :test_unit => { - :fixture => true, - :fixture_replacement => nil + :test_framework => nil, + :template_engine => :erb }, :plugin => { @@ -200,6 +190,7 @@ module Rails # Print Rails defaults first. rails = groups.delete("rails") rails.map! { |n| n.sub(/^rails:/, '') } + rails.delete("app") print_list("rails", rails) groups.sort.each { |b, n| print_list(b, n) } diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb index 3e851bf888..12e918731e 100644 --- a/railties/lib/rails/generators/named_base.rb +++ b/railties/lib/rails/generators/named_base.rb @@ -6,17 +6,9 @@ module Rails class NamedBase < Base argument :name, :type => :string - no_tasks { - attr_reader :class_name, :singular_name, :plural_name, :table_name, - :class_path, :file_path, :class_nesting_depth - - alias :file_name :singular_name - } - def initialize(args, *options) #:nodoc: # Unfreeze name in case it's given as a frozen string args[0] = args[0].dup if args[0].is_a?(String) && args[0].frozen? - super assign_names!(self.name) parse_attributes! if respond_to?(:attributes) @@ -24,28 +16,48 @@ module Rails protected - def assign_names!(given_name) #:nodoc: - base_name, @class_path, @file_path, class_nesting, @class_nesting_depth = extract_modules(given_name) - class_name_without_nesting, @singular_name, @plural_name = inflect_names(base_name) + attr_reader :class_path, :file_name + alias :singular_name :file_name - @table_name = if pluralize_table_names? - plural_name - else - singular_name + def file_path + @file_path ||= (class_path + [file_name]).join('/') + end + + def class_name + @class_name ||= (class_path + [file_name]).map!{ |m| m.camelize }.join('::') + end + + def plural_name + @plural_name ||= singular_name.pluralize + end + + def i18n_scope + @i18n_scope ||= file_path.gsub('/', '.') + end + + def table_name + @table_name ||= begin + base = pluralize_table_names? ? plural_name : singular_name + (class_path + [base]).join('_') end + end - if class_nesting.empty? - @class_name = class_name_without_nesting + # Tries to retrieve the application name or simple return application. + def application_name + if defined?(Rails) && Rails.application + Rails.application.class.name.split('::').first.underscore else - @table_name = class_nesting.underscore << "_" << @table_name - @class_name = "#{class_nesting}::#{class_name_without_nesting}" + "application" end + end - @table_name.gsub!('/', '_') + def assign_names!(name) #:nodoc: + @class_path = name.include?('/') ? name.split('/') : name.split('::') + @class_path.map! { |m| m.underscore } + @file_name = @class_path.pop end - # Convert attributes hash into an array with GeneratedAttribute objects. - # + # Convert attributes array into GeneratedAttribute objects. def parse_attributes! #:nodoc: self.attributes = (attributes || []).map do |key_value| name, type = key_value.split(':') @@ -53,29 +65,6 @@ module Rails end end - # Extract modules from filesystem-style or ruby-style path. Both - # good/fun/stuff and Good::Fun::Stuff produce the same results. - # - def extract_modules(name) #:nodoc: - modules = name.include?('/') ? name.split('/') : name.split('::') - name = modules.pop - path = modules.map { |m| m.underscore } - - file_path = (path + [name.underscore]).join('/') - nesting = modules.map { |m| m.camelize }.join('::') - - [name, path, file_path, nesting, modules.size] - end - - # Receives name and return camelized, underscored and pluralized names. - # - def inflect_names(name) #:nodoc: - camel = name.camelize - under = camel.underscore - plural = under.pluralize - [camel, under, plural] - end - def pluralize_table_names? !defined?(ActiveRecord::Base) || ActiveRecord::Base.pluralize_table_names end diff --git a/railties/lib/rails/generators/resource_helpers.rb b/railties/lib/rails/generators/resource_helpers.rb index 7e00a222ed..3a98a8f9c1 100644 --- a/railties/lib/rails/generators/resource_helpers.rb +++ b/railties/lib/rails/generators/resource_helpers.rb @@ -9,14 +9,7 @@ module Rails mattr_accessor :skip_warn def self.included(base) #:nodoc: - base.class_eval do - class_option :force_plural, :type => :boolean, :desc => "Forces the use of a plural ModelName" - - no_tasks { - attr_reader :controller_name, :controller_class_name, :controller_file_name, - :controller_class_path, :controller_file_path - } - end + base.class_option :force_plural, :type => :boolean, :desc => "Forces the use of a plural ModelName" end # Set controller variables on initialization. @@ -29,29 +22,40 @@ module Rails say "Plural version of the model detected, using singularized version. Override with --force-plural." ResourceHelpers.skip_warn = true end - name.replace name.singularize - assign_names!(self.name) + assign_names!(name) end @controller_name = name.pluralize + end - base_name, @controller_class_path, @controller_file_path, class_nesting, class_nesting_depth = extract_modules(@controller_name) - class_name_without_nesting, @controller_file_name, controller_plural_name = inflect_names(base_name) + protected + + attr_reader :controller_name - @controller_class_name = if class_nesting.empty? - class_name_without_nesting - else - "#{class_nesting}::#{class_name_without_nesting}" + def controller_class_path + @class_path end - end - protected + def controller_file_name + @controller_file_name ||= file_name.pluralize + end + + def controller_file_path + @controller_file_path ||= (controller_class_path + [controller_file_name]).join('/') + end + + def controller_class_name + @controller_class_name ||= (controller_class_path + [controller_file_name]).map!{ |m| m.camelize }.join('::') + end + + def controller_i18n_scope + @controller_i18n_scope ||= controller_file_path.gsub('/', '.') + end # Loads the ORM::Generators::ActiveModel class. This class is responsable # to tell scaffold entities how to generate an specific method for the # ORM. Check Rails::Generators::ActiveModel for more information. - # def orm_class @orm_class ||= begin # Raise an error if the class_option :orm was not defined. @@ -68,7 +72,6 @@ module Rails end # Initialize ORM::Generators::ActiveModel to access instance methods. - # def orm_instance(name=file_name) @orm_instance ||= @orm_class.new(name) end diff --git a/railties/lib/rails/initializable.rb b/railties/lib/rails/initializable.rb index 8fcb254590..d91f67823f 100644 --- a/railties/lib/rails/initializable.rb +++ b/railties/lib/rails/initializable.rb @@ -19,12 +19,6 @@ module Rails @options[:after] end - def global - @options[:global] - end - - alias global? global - def run(*args) @context.instance_exec(*args, &block) end @@ -70,10 +64,7 @@ module Rails end def initializers - @initializers ||= begin - initializers = self.class.initializers_for(:instance) - Collection.new(initializers.map { |i| i.bind(self) }) - end + @initializers ||= self.class.initializers_for(self) end module ClassMethods @@ -81,26 +72,27 @@ module Rails @initializers ||= [] end - def initializers_for(scope = :global) + def initializers_chain initializers = Collection.new ancestors.reverse_each do |klass| next unless klass.respond_to?(:initializers) - initializers = initializers + klass.initializers.select { |i| - (scope == :global) == !!i.global? - } + initializers = initializers + klass.initializers end initializers end + def initializers_for(binding) + Collection.new(initializers_chain.map { |i| i.bind(binding) }) + end + def initializer(name, opts = {}, &blk) raise ArgumentError, "A block must be passed when defining an initializer" unless blk - @initializers ||= [] - @initializers << Initializer.new(name, nil, opts, &blk) + initializers << Initializer.new(name, nil, opts, &blk) end def run_initializers(*args) return if @ran - initializers_for(:global).each do |initializer| + initializers_chain.each do |initializer| instance_exec(*args, &initializer.block) end @ran = true diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb index b3d105d8c7..55874813da 100644 --- a/railties/lib/rails/paths.rb +++ b/railties/lib/rails/paths.rb @@ -1,7 +1,7 @@ require 'set' module Rails - class Application + module Paths module PathParent def method_missing(id, *args) name = id.to_s @@ -31,27 +31,21 @@ module Rails @all_paths = [] end - def load_once - all_paths.map { |path| path.paths if path.load_once? }.compact.flatten.uniq - end - - def eager_load - all_paths.map { |path| path.paths if path.eager_load? }.compact.flatten.uniq - end - def all_paths @all_paths.uniq! @all_paths end - def load_paths - all_paths.map { |path| path.paths if path.load_path? }.compact.flatten.uniq + def load_once + filter { |path| path.paths if path.load_once? } end - def add_to_load_path - load_paths.reverse_each do |path| - $LOAD_PATH.unshift(path) if File.directory?(path) - end + def eager_load + filter { |path| path.paths if path.eager_load? } + end + + def load_paths + filter { |path| path.paths if path.load_path? } end def push(*) @@ -61,6 +55,12 @@ module Rails alias unshift push alias << push alias concat push + + protected + + def filter(&block) + all_paths.map(&block).compact.flatten.uniq.select { |p| File.exists?(p) } + end end class Path @@ -74,11 +74,11 @@ module Rails @children = {} @root = root @paths = paths.flatten - @glob = @options[:glob] || "**/*.rb" + @glob = @options.delete(:glob) @load_once = @options[:load_once] @eager_load = @options[:eager_load] - @load_path = @options[:load_path] || @eager_load + @load_path = @options[:load_path] || @eager_load || @load_once @root.all_paths << self end @@ -103,6 +103,7 @@ module Rails def load_once! @load_once = true + @load_path = true end def load_once? @@ -128,10 +129,13 @@ module Rails def paths raise "You need to set a path root" unless @root.path - - @paths.map do |path| - path.index('/') == 0 ? path : File.expand_path(File.join(@root.path, path)) + result = @paths.map do |p| + path = File.expand_path(p, @root.path) + @glob ? Dir[File.join(path, @glob)] : path end + result.flatten! + result.uniq! + result end alias to_a paths diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index c3b81bcd3e..881c97f02d 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -1,5 +1,11 @@ +require 'rails/engine' + module Rails - class Plugin < Railtie + class Plugin < Engine + def self.inherited(base) + raise "You cannot inherit from Rails::Plugin" + end + def self.all(list, paths) plugins = [] paths.each do |path| @@ -17,53 +23,42 @@ module Rails attr_reader :name, :path - def initialize(path) - @name = File.basename(path).to_sym - @path = path - end + def load_tasks + super + extra_tasks = Dir["#{root}/{tasks,rails/tasks}/**/*.rake"] - def load_paths - Dir["#{path}/{lib}", "#{path}/app/{models,controllers,helpers}"] + unless extra_tasks.empty? + ActiveSupport::Deprecation.warn "Having rake tasks in PLUGIN_PATH/tasks or " << + "PLUGIN_PATH/rails/tasks is deprecated. Use to PLUGIN_PATH/lib/tasks instead" + extra_tasks.sort.each { |ext| load(ext) } + end end - def load_tasks - Dir["#{path}/{tasks,lib/tasks,rails/tasks}/**/*.rake"].sort.each { |ext| load ext } + def initialize(root) + @name = File.basename(root).to_sym + config.root = root end - initializer :add_to_load_path, :after => :set_autoload_paths do |app| - load_paths.each do |path| - $LOAD_PATH << path - require "active_support/dependencies" - - ActiveSupport::Dependencies.load_paths << path - - unless app.config.reload_plugins - ActiveSupport::Dependencies.load_once_paths << path - end - end + def config + @config ||= Engine::Configuration.new end - initializer :load_init_rb, :before => :load_application_initializers do |app| - file = "#{@path}/init.rb" + initializer :load_init_rb do |app| + file = Dir["#{root}/{rails/init,init}.rb"].first config = app.config - eval File.read(file), binding, file if File.file?(file) + eval(File.read(file), binding, file) if file && File.file?(file) end - initializer :add_view_paths, :after => :initialize_framework_views do - plugin_views = "#{path}/app/views" - if File.directory?(plugin_views) - ActionController::Base.view_paths.concat([plugin_views]) if defined? ActionController - ActionMailer::Base.view_paths.concat([plugin_views]) if defined? ActionMailer + initializer :sanity_check_railties_collision do + if Engine.subclasses.map { |k| k.root.to_s }.include?(root.to_s) + raise "\"#{name}\" is a Railtie/Engine and cannot be installed as plugin" end end - # TODO Isn't it supposed to be :after => "action_controller.initialize_routing" ? - initializer :add_routing_file, :after => :initialize_routing do |app| - routing_file = "#{path}/config/routes.rb" - if File.exist?(routing_file) - app.route_configuration_files << routing_file - app.reload_routes! - end + protected + + def reloadable?(app) + app.config.reload_plugins end end end diff --git a/railties/lib/rails/rack.rb b/railties/lib/rails/rack.rb index 4bc0c2c88b..1f20ceae44 100644 --- a/railties/lib/rails/rack.rb +++ b/railties/lib/rails/rack.rb @@ -3,7 +3,6 @@ module Rails autoload :Debugger, "rails/rack/debugger" autoload :Logger, "rails/rack/logger" autoload :LogTailer, "rails/rack/log_tailer" - autoload :Metal, "rails/rack/metal" autoload :Static, "rails/rack/static" end end diff --git a/railties/lib/rails/rack/logger.rb b/railties/lib/rails/rack/logger.rb index 91a613092f..de21fb4f10 100644 --- a/railties/lib/rails/rack/logger.rb +++ b/railties/lib/rails/rack/logger.rb @@ -9,27 +9,23 @@ module Rails end def call(env) - @env = env - before_dispatch - result = @app.call(@env) - after_dispatch - result + before_dispatch(env) + @app.call(env) + ensure + after_dispatch(env) end protected - def request - @request ||= ActionDispatch::Request.new(@env) - end - - def before_dispatch + def before_dispatch(env) + request = ActionDispatch::Request.new(env) path = request.request_uri.inspect rescue "unknown" info "\n\nStarted #{request.method.to_s.upcase} #{path} " << "for #{request.remote_ip} at #{Time.now.to_s(:db)}" end - def after_dispatch + def after_dispatch(env) Rails::Subscriber.flush_all! end diff --git a/railties/lib/rails/rack/metal.rb b/railties/lib/rails/rack/metal.rb deleted file mode 100644 index 565f95d7c4..0000000000 --- a/railties/lib/rails/rack/metal.rb +++ /dev/null @@ -1,26 +0,0 @@ -require 'action_dispatch' - -module Rails - module Rack - class Metal - def initialize(metal_roots, metals=nil) - load_list = metals || Dir["{#{metal_roots.join(",")}}/**/*.rb"] - - @metals = load_list.map { |metal| - metal = File.basename(metal, '.rb') - require_dependency metal - metal.camelize.constantize - }.compact - end - - def new(app) - ActionDispatch::Cascade.new(@metals, app) - end - - def name - ActionDispatch::Cascade.name - end - alias_method :to_s, :name - end - end -end diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb index 611688cef1..2dc2ba1002 100644 --- a/railties/lib/rails/railtie.rb +++ b/railties/lib/rails/railtie.rb @@ -1,3 +1,6 @@ +require 'rails/initializable' +require 'rails/configuration' + module Rails # Railtie is the core of the Rails Framework and provides all the hooks and # methods you need to link your plugin into Rails. @@ -108,52 +111,56 @@ module Rails # gem "my_gem", :require_as => ["my_gem", "my_gem/railtie"] # class Railtie + autoload :Configurable, "rails/railtie/configurable" + autoload :Configuration, "rails/railtie/configuration" + include Initializable - # Pass in the name of your plugin. This is passed in as an underscored symbol. - # - # module MyPlugin - # class Railtie < Rails::Railtie - # plugin_name :my_plugin - # end - # end - def self.plugin_name(plugin_name = nil) - @plugin_name ||= name.demodulize.underscore - @plugin_name = plugin_name if plugin_name - @plugin_name - end + ABSTRACT_RAILTIES = %w(Rails::Plugin Rails::Engine Rails::Application) - def self.inherited(klass) - @plugins ||= [] - @plugins << klass unless klass == Plugin - end + class << self + def subclasses + @subclasses ||= [] + end - def self.plugins - @plugins - end + def inherited(base) + unless abstract_railtie?(base) + base.send(:include, self::Configurable) + subclasses << base + end + end - def self.plugin_names - plugins.map { |p| p.plugin_name } - end + def railtie_name(railtie_name = nil) + @railtie_name ||= name.demodulize.underscore + @railtie_name = railtie_name if railtie_name + @railtie_name + end - def self.config - Configuration.default - end + def railtie_names + subclasses.map { |p| p.railtie_name } + end - def self.subscriber(subscriber) - Rails::Subscriber.add(plugin_name, subscriber) - end + def subscriber(subscriber) + Rails::Subscriber.add(railtie_name, subscriber) + end - def self.rake_tasks(&blk) - @rake_tasks ||= [] - @rake_tasks << blk if blk - @rake_tasks - end + def rake_tasks(&blk) + @rake_tasks ||= [] + @rake_tasks << blk if blk + @rake_tasks + end + + def generators(&blk) + @generators ||= [] + @generators << blk if blk + @generators + end + + protected - def self.generators(&blk) - @generators ||= [] - @generators << blk if blk - @generators + def abstract_railtie?(base) + ABSTRACT_RAILTIES.include?(base.name) + end end def rake_tasks @@ -165,12 +172,10 @@ module Rails end def load_tasks - return unless rake_tasks rake_tasks.each { |blk| blk.call } end def load_generators - return unless generators generators.each { |blk| blk.call } end end diff --git a/railties/lib/rails/railtie/configurable.rb b/railties/lib/rails/railtie/configurable.rb new file mode 100644 index 0000000000..a2eb938c5a --- /dev/null +++ b/railties/lib/rails/railtie/configurable.rb @@ -0,0 +1,23 @@ +module Rails + class Railtie + module Configurable + def self.included(base) + base.extend ClassMethods + end + + module ClassMethods + def config + @config ||= Railtie::Configuration.new + end + + def inherited(base) + raise "You cannot inherit from a Rails::Railtie child" + end + end + + def config + self.class.config + end + end + end +end diff --git a/railties/lib/rails/railtie/configuration.rb b/railties/lib/rails/railtie/configuration.rb new file mode 100644 index 0000000000..bfb43f7041 --- /dev/null +++ b/railties/lib/rails/railtie/configuration.rb @@ -0,0 +1,9 @@ +require 'rails/configuration' + +module Rails + class Railtie + class Configuration + include Rails::Configuration::Shared + end + end +end
\ No newline at end of file diff --git a/railties/lib/rails/tasks.rb b/railties/lib/rails/tasks.rb index 44c014efe8..9807000578 100644 --- a/railties/lib/rails/tasks.rb +++ b/railties/lib/rails/tasks.rb @@ -10,7 +10,6 @@ $VERBOSE = nil misc routes statistics - testing tmp ).each do |task| load "rails/tasks/#{task}.rake" diff --git a/railties/lib/rails/tasks/documentation.rake b/railties/lib/rails/tasks/documentation.rake index 65d0d476ba..3f49a9a720 100644 --- a/railties/lib/rails/tasks/documentation.rake +++ b/railties/lib/rails/tasks/documentation.rake @@ -11,35 +11,43 @@ namespace :doc do rdoc.rdoc_files.include('lib/**/*.rb') } - desc "Generate documentation for the Rails framework" + desc 'Generate documentation for the Rails framework. Specify path with PATH="/path/to/rails"' Rake::RDocTask.new("rails") { |rdoc| + path = ENV['RAILS_PATH'] || 'vendor/gems/gems' + version = '-3.0.pre' unless ENV['RAILS_PATH'] rdoc.rdoc_dir = 'doc/api' rdoc.template = "#{ENV['template']}.rb" if ENV['template'] rdoc.title = "Rails Framework Documentation" rdoc.options << '--line-numbers' << '--inline-source' rdoc.rdoc_files.include('README') - rdoc.rdoc_files.include('vendor/rails/railties/CHANGELOG') - rdoc.rdoc_files.include('vendor/rails/railties/MIT-LICENSE') - rdoc.rdoc_files.include('vendor/rails/railties/README') - rdoc.rdoc_files.include('vendor/rails/railties/lib/{*.rb,commands/*.rb,generators/*.rb}') - rdoc.rdoc_files.include('vendor/rails/activerecord/README') - rdoc.rdoc_files.include('vendor/rails/activerecord/CHANGELOG') - rdoc.rdoc_files.include('vendor/rails/activerecord/lib/active_record/**/*.rb') - rdoc.rdoc_files.exclude('vendor/rails/activerecord/lib/active_record/vendor/*') - rdoc.rdoc_files.include('vendor/rails/activeresource/README') - rdoc.rdoc_files.include('vendor/rails/activeresource/CHANGELOG') - rdoc.rdoc_files.include('vendor/rails/activeresource/lib/active_resource.rb') - rdoc.rdoc_files.include('vendor/rails/activeresource/lib/active_resource/*') - rdoc.rdoc_files.include('vendor/rails/actionpack/README') - rdoc.rdoc_files.include('vendor/rails/actionpack/CHANGELOG') - rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_controller/**/*.rb') - rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_view/**/*.rb') - rdoc.rdoc_files.include('vendor/rails/actionmailer/README') - rdoc.rdoc_files.include('vendor/rails/actionmailer/CHANGELOG') - rdoc.rdoc_files.include('vendor/rails/actionmailer/lib/action_mailer/base.rb') - rdoc.rdoc_files.include('vendor/rails/activesupport/README') - rdoc.rdoc_files.include('vendor/rails/activesupport/CHANGELOG') - rdoc.rdoc_files.include('vendor/rails/activesupport/lib/active_support/**/*.rb') + + %w(README CHANGELOG lib/action_mailer/base.rb).each do |file| + rdoc.rdoc_files.include("#{path}/actionmailer#{version}/#{file}") + end + + %w(README CHANGELOG lib/action_controller/**/*.rb lib/action_view/**/*.rb).each do |file| + rdoc.rdoc_files.include("#{path}/actionpack#{version}/#{file}") + end + + %w(README CHANGELOG lib/active_model/**/*.rb).each do |file| + rdoc.rdoc_files.include("#{path}/activemodel#{version}/#{file}") + end + + %w(README CHANGELOG lib/active_record/**/*.rb).each do |file| + rdoc.rdoc_files.include("#{path}/activerecord#{version}/#{file}") + end + + %w(README CHANGELOG lib/active_resource.rb lib/active_resource/*).each do |file| + rdoc.rdoc_files.include("#{path}/activeresource#{version}/#{file}") + end + + %w(README CHANGELOG lib/active_support/**/*.rb).each do |file| + rdoc.rdoc_files.include("#{path}/activesupport#{version}/#{file}") + end + + %w(README CHANGELOG MIT-LICENSE lib/{*.rb,commands/*.rb,generators/*.rb}).each do |file| + rdoc.rdoc_files.include("#{path}/railties#{version}/#{file}") + end } plugins = FileList['vendor/plugins/**'].collect { |plugin| File.basename(plugin) } diff --git a/railties/lib/rails/tasks/middleware.rake b/railties/lib/rails/tasks/middleware.rake index 5a5bd7a7e9..251da67c96 100644 --- a/railties/lib/rails/tasks/middleware.rake +++ b/railties/lib/rails/tasks/middleware.rake @@ -3,5 +3,5 @@ task :middleware => :environment do Rails.configuration.middleware.active.each do |middleware| puts "use #{middleware.inspect}" end - puts "run #{Rails.application.class.name}" + puts "run #{Rails::Application.instance.class.name}.routes" end diff --git a/railties/lib/rails/tasks/routes.rake b/railties/lib/rails/tasks/routes.rake index 2395d73b2f..e8da72db4d 100644 --- a/railties/lib/rails/tasks/routes.rake +++ b/railties/lib/rails/tasks/routes.rake @@ -1,5 +1,6 @@ desc 'Print out all defined routes in match order, with names. Target specific controller with CONTROLLER=x.' task :routes => :environment do + Rails::Application.reload_routes! all_routes = ENV['CONTROLLER'] ? ActionController::Routing::Routes.routes.select { |route| route.defaults[:controller] == ENV['CONTROLLER'] } : ActionController::Routing::Routes.routes routes = all_routes.collect do |route| name = ActionController::Routing::Routes.named_routes.routes.index(route).to_s diff --git a/railties/lib/rails/test_unit/railtie.rb b/railties/lib/rails/test_unit/railtie.rb new file mode 100644 index 0000000000..f93dace9bb --- /dev/null +++ b/railties/lib/rails/test_unit/railtie.rb @@ -0,0 +1,17 @@ +module Rails + class TestUnitRailtie < Rails::Railtie + railtie_name :test_unit + + config.generators do |c| + c.test_framework :test_unit, :fixture => true, + :fixture_replacement => nil + + c.integration_tool :test_unit + c.performance_tool :test_unit + end + + rake_tasks do + load "rails/tasks/testing.rake" + end + end +end
\ No newline at end of file diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index 6968e87986..57bd797ef0 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -1,7 +1,7 @@ require "isolation/abstract_unit" module ApplicationTests - class InitializerTest < Test::Unit::TestCase + class ConfigurationTest < Test::Unit::TestCase include ActiveSupport::Testing::Isolation def new_app @@ -12,13 +12,33 @@ module ApplicationTests FileUtils.cp_r(app_path, new_app) end + def app + @app ||= Rails.application + end + def setup - FileUtils.rm_rf(new_app) if File.directory?(new_app) build_app boot_rails FileUtils.rm_rf("#{app_path}/config/environments") end + def teardown + FileUtils.rm_rf(new_app) if File.directory?(new_app) + end + + test "Rails::Application.instance is nil until app is initialized" do + require 'rails' + assert_nil Rails::Application.instance + require "#{app_path}/config/environment" + assert_equal AppTemplate::Application.instance, Rails::Application.instance + end + + test "Rails::Application responds to all instance methods" do + require "#{app_path}/config/environment" + assert_respond_to Rails::Application, :routes_reloader + assert_equal Rails::Application.routes_reloader, Rails.application.routes_reloader + end + test "the application root is set correctly" do require "#{app_path}/config/environment" assert_equal Pathname.new(app_path), Rails.application.root @@ -52,21 +72,12 @@ module ApplicationTests end end - test "if there's no config.active_support.bare, all of ActiveSupport is required" do - use_frameworks [] + test "Rails.root should be a Pathname" do + add_to_config <<-RUBY + config.root = "#{app_path}" + RUBY require "#{app_path}/config/environment" - assert_nothing_raised { [1,2,3].rand } - end - - test "config.active_support.bare does not require all of ActiveSupport" do - add_to_config "config.active_support.bare = true" - - use_frameworks [] - - Dir.chdir("#{app_path}/app") do - require "#{app_path}/config/environment" - assert_raises(NoMethodError) { [1,2,3].rand } - end + assert_instance_of Pathname, Rails.root end test "marking the application as threadsafe sets the correct config variables" do @@ -129,10 +140,29 @@ module ApplicationTests value = value.reverse if key =~ /baz/ }] RUBY - + assert_nothing_raised do require "#{app_path}/config/application" end end + + test "config.to_prepare is forwarded to ActionDispatch" do + $prepared = false + + add_to_config <<-RUBY + config.to_prepare do + $prepared = true + end + RUBY + + assert !$prepared + + require "#{app_path}/config/environment" + require 'rack/test' + extend Rack::Test::Methods + + get "/" + assert $prepared + end end end diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb index e8a4a4e158..22ab60f4a0 100644 --- a/railties/test/application/console_test.rb +++ b/railties/test/application/console_test.rb @@ -9,8 +9,8 @@ class ConsoleTest < Test::Unit::TestCase # Load steps taken from rails/commands/console.rb require "#{rails_root}/config/environment" - require 'rails/console_app' - require 'rails/console_with_helpers' + require 'rails/console/app' + require 'rails/console/helpers' end def test_app_method_should_return_integration_session diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb index e1e51c318c..e54edea07c 100644 --- a/railties/test/application/generators_test.rb +++ b/railties/test/application/generators_test.rb @@ -19,8 +19,14 @@ module ApplicationTests yield app_const.config end + def with_bare_config + require "rails" + require "rails/generators" + yield app_const.config + end + test "generators default values" do - with_config do |c| + with_bare_config do |c| assert_equal(true, c.generators.colorize_logging) assert_equal({}, c.generators.aliases) assert_equal({}, c.generators.options) @@ -28,7 +34,7 @@ module ApplicationTests end test "generators set rails options" do - with_config do |c| + with_bare_config do |c| c.generators.orm = :datamapper c.generators.test_framework = :rspec c.generators.helper = false @@ -75,7 +81,7 @@ module ApplicationTests end test "generators with hashes for options and aliases" do - with_config do |c| + with_bare_config do |c| c.generators do |g| g.orm :datamapper, :migration => false g.plugin :aliases => { :generator => "-g" }, @@ -92,18 +98,5 @@ module ApplicationTests assert_equal({ :plugin => { :generator => "-g" } }, c.generators.aliases) end end - - test "generators with hashes are deep merged" do - with_config do |c| - c.generators do |g| - g.orm :datamapper, :migration => false - g.plugin :aliases => { :generator => "-g" }, - :generator => true - end - end - - assert Rails::Generators.aliases.size >= 1 - assert Rails::Generators.options.size >= 1 - end end end diff --git a/railties/test/application/initializer_test.rb b/railties/test/application/initializer_test.rb deleted file mode 100644 index 754c0f1839..0000000000 --- a/railties/test/application/initializer_test.rb +++ /dev/null @@ -1,185 +0,0 @@ -require "isolation/abstract_unit" - -module ApplicationTests - class InitializerTest < Test::Unit::TestCase - include ActiveSupport::Testing::Isolation - - def setup - build_app - boot_rails - FileUtils.rm_rf "#{app_path}/config/environments" - end - - test "initializing an application adds the application paths to the load path" do - add_to_config <<-RUBY - config.root = "#{app_path}" - RUBY - - require "#{app_path}/config/environment" - assert $:.include?("#{app_path}/app/models") - end - - test "eager loading loads parent classes before children" do - app_file "lib/zoo.rb", <<-ZOO - class Zoo ; include ReptileHouse ; end - ZOO - app_file "lib/zoo/reptile_house.rb", <<-ZOO - module Zoo::ReptileHouse ; end - ZOO - - add_to_config <<-RUBY - config.root = "#{app_path}" - config.eager_load_paths = "#{app_path}/lib" - RUBY - - require "#{app_path}/config/environment" - - assert Zoo - end - - test "load environment with global" do - app_file "config/environments/development.rb", "$initialize_test_set_from_env = 'success'" - assert_nil $initialize_test_set_from_env - add_to_config <<-RUBY - config.root = "#{app_path}" - RUBY - require "#{app_path}/config/environment" - assert_equal "success", $initialize_test_set_from_env - end - - test "action_controller load paths set only if action controller in use" do - assert_nothing_raised NameError do - add_to_config <<-RUBY - config.root = "#{app_path}" - RUBY - - use_frameworks [] - require "#{app_path}/config/environment" - end - end - - test "after_initialize block works correctly" do - add_to_config <<-RUBY - config.root = "#{app_path}" - config.after_initialize { $test_after_initialize_block1 = "success" } - config.after_initialize { $test_after_initialize_block2 = "congratulations" } - RUBY - require "#{app_path}/config/environment" - - assert_equal "success", $test_after_initialize_block1 - assert_equal "congratulations", $test_after_initialize_block2 - end - - test "after_initialize block works correctly when no block is passed" do - add_to_config <<-RUBY - config.root = "#{app_path}" - config.after_initialize { $test_after_initialize_block1 = "success" } - config.after_initialize # don't pass a block, this is what we're testing! - config.after_initialize { $test_after_initialize_block2 = "congratulations" } - RUBY - require "#{app_path}/config/environment" - - assert_equal "success", $test_after_initialize_block1 - assert_equal "congratulations", $test_after_initialize_block2 - end - - test "after_initialize runs after frameworks have been initialized" do - $activerecord_configurations = nil - add_to_config <<-RUBY - config.after_initialize { $activerecord_configurations = ActiveRecord::Base.configurations } - RUBY - - require "#{app_path}/config/environment" - assert $activerecord_configurations - assert $activerecord_configurations['development'] - end - - # i18n - test "setting another default locale" do - add_to_config <<-RUBY - config.root = "#{app_path}" - config.i18n.default_locale = :de - RUBY - require "#{app_path}/config/environment" - - assert_equal :de, I18n.default_locale - end - - test "no config locales dir present should return empty load path" do - FileUtils.rm_rf "#{app_path}/config/locales" - add_to_config <<-RUBY - config.root = "#{app_path}" - RUBY - require "#{app_path}/config/environment" - - assert_equal [], Rails.application.config.i18n.load_path - end - - test "config locales dir present should be added to load path" do - add_to_config <<-RUBY - config.root = "#{app_path}" - RUBY - - require "#{app_path}/config/environment" - assert_equal ["#{app_path}/config/locales/en.yml"], Rails.application.config.i18n.load_path - end - - test "config defaults should be added with config settings" do - add_to_config <<-RUBY - config.root = "#{app_path}" - config.i18n.load_path << "my/other/locale.yml" - RUBY - require "#{app_path}/config/environment" - - assert_equal [ - "#{app_path}/config/locales/en.yml", "my/other/locale.yml" - ], Rails.application.config.i18n.load_path - end - - # DB middleware - test "database middleware doesn't initialize when session store is not active_record" do - add_to_config <<-RUBY - config.root = "#{app_path}" - config.action_controller.session_store = :cookie_store - RUBY - require "#{app_path}/config/environment" - - assert !Rails.application.config.middleware.include?(ActiveRecord::SessionStore) - end - - test "database middleware initializes when session store is active record" do - add_to_config "config.action_controller.session_store = :active_record_store" - - require "#{app_path}/config/environment" - - expects = [ActiveRecord::ConnectionAdapters::ConnectionManagement, ActiveRecord::QueryCache, ActiveRecord::SessionStore] - middleware = Rails.application.config.middleware.map { |m| m.klass } - assert_equal expects, middleware & expects - end - - test "Rails.root should be a Pathname" do - add_to_config <<-RUBY - config.root = "#{app_path}" - RUBY - require "#{app_path}/config/environment" - assert_instance_of Pathname, Rails.root - end - end - - class InitializerCustomFrameworkExtensionsTest < Test::Unit::TestCase - include ActiveSupport::Testing::Isolation - - def setup - build_app - boot_rails - FileUtils.rm_rf "#{app_path}/config/environments" - end - - test "database middleware doesn't initialize when activerecord is not in frameworks" do - use_frameworks [] - require "#{app_path}/config/environment" - - assert_nil defined?(ActiveRecord) - end - end -end diff --git a/railties/test/initializer/boot_test.rb b/railties/test/application/initializers/boot_test.rb index 5ee3c45b21..5ec562f12f 100644 --- a/railties/test/initializer/boot_test.rb +++ b/railties/test/application/initializers/boot_test.rb @@ -1,6 +1,6 @@ require "isolation/abstract_unit" -module BootTests +module ApplicationTests class GemBooting < Test::Unit::TestCase include ActiveSupport::Testing::Isolation diff --git a/railties/test/initializer/check_ruby_version_test.rb b/railties/test/application/initializers/check_ruby_version_test.rb index 311f19a28a..58782b2511 100644 --- a/railties/test/initializer/check_ruby_version_test.rb +++ b/railties/test/application/initializers/check_ruby_version_test.rb @@ -1,6 +1,6 @@ require "isolation/abstract_unit" -module InitializerTests +module ApplicationTests class CheckRubyVersionTest < Test::Unit::TestCase include ActiveSupport::Testing::Isolation diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb new file mode 100644 index 0000000000..1e7b9c9997 --- /dev/null +++ b/railties/test/application/initializers/frameworks_test.rb @@ -0,0 +1,86 @@ +require "isolation/abstract_unit" + +module ApplicationTests + class FrameworlsTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + FileUtils.rm_rf "#{app_path}/config/environments" + end + + # AC & AM + test "set load paths set only if action controller or action mailer are in use" do + assert_nothing_raised NameError do + add_to_config <<-RUBY + config.root = "#{app_path}" + RUBY + + use_frameworks [] + require "#{app_path}/config/environment" + end + end + + test "sets action_controller and action_mailer load paths" do + add_to_config <<-RUBY + config.root = "#{app_path}" + RUBY + + require "#{app_path}/config/environment" + ActionController::Base.view_paths.include?(File.expand_path("app/views", app_path)) + ActionMailer::Base.view_paths.include?(File.expand_path("app/views", app_path)) + end + + # AS + test "if there's no config.active_support.bare, all of ActiveSupport is required" do + use_frameworks [] + require "#{app_path}/config/environment" + assert_nothing_raised { [1,2,3].rand } + end + + test "config.active_support.bare does not require all of ActiveSupport" do + add_to_config "config.active_support.bare = true" + + use_frameworks [] + + Dir.chdir("#{app_path}/app") do + require "#{app_path}/config/environment" + assert_raises(NoMethodError) { [1,2,3].rand } + end + end + + # AR + test "database middleware doesn't initialize when session store is not active_record" do + add_to_config <<-RUBY + config.root = "#{app_path}" + config.action_controller.session_store = :cookie_store + RUBY + require "#{app_path}/config/environment" + + assert !Rails.application.config.middleware.include?(ActiveRecord::SessionStore) + end + + test "database middleware initializes when session store is active record" do + add_to_config "config.action_controller.session_store = :active_record_store" + + require "#{app_path}/config/environment" + + expects = [ActiveRecord::ConnectionAdapters::ConnectionManagement, ActiveRecord::QueryCache, ActiveRecord::SessionStore] + middleware = Rails.application.config.middleware.map { |m| m.klass } + assert_equal expects, middleware & expects + end + + test "active_record extensions are applied to ActiveRecord" do + add_to_config "config.active_record.table_name_prefix = 'tbl_'" + require "#{app_path}/config/environment" + assert_equal 'tbl_', ActiveRecord::Base.table_name_prefix + end + + test "database middleware doesn't initialize when activerecord is not in frameworks" do + use_frameworks [] + require "#{app_path}/config/environment" + assert_nil defined?(ActiveRecord) + end + end +end diff --git a/railties/test/application/initializers/i18n_test.rb b/railties/test/application/initializers/i18n_test.rb new file mode 100644 index 0000000000..99b2d86013 --- /dev/null +++ b/railties/test/application/initializers/i18n_test.rb @@ -0,0 +1,55 @@ +require "isolation/abstract_unit" + +module ApplicationTests + class I18nTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + FileUtils.rm_rf "#{app_path}/config/environments" + end + + # i18n + test "setting another default locale" do + add_to_config <<-RUBY + config.root = "#{app_path}" + config.i18n.default_locale = :de + RUBY + require "#{app_path}/config/environment" + + assert_equal :de, I18n.default_locale + end + + test "no config locales dir present should return empty load path" do + FileUtils.rm_rf "#{app_path}/config/locales" + add_to_config <<-RUBY + config.root = "#{app_path}" + RUBY + require "#{app_path}/config/environment" + + assert_equal [], Rails.application.config.i18n.load_path + end + + test "config locales dir present should be added to load path" do + add_to_config <<-RUBY + config.root = "#{app_path}" + RUBY + + require "#{app_path}/config/environment" + assert_equal ["#{app_path}/config/locales/en.yml"], Rails.application.config.i18n.load_path + end + + test "config defaults should be added with config settings" do + add_to_config <<-RUBY + config.root = "#{app_path}" + config.i18n.load_path << "my/other/locale.yml" + RUBY + require "#{app_path}/config/environment" + + assert_equal [ + "#{app_path}/config/locales/en.yml", "my/other/locale.yml" + ], Rails.application.config.i18n.load_path + end + end +end
\ No newline at end of file diff --git a/railties/test/application/initializers/initializers_test.rb b/railties/test/application/initializers/initializers_test.rb new file mode 100644 index 0000000000..0c3de7ce33 --- /dev/null +++ b/railties/test/application/initializers/initializers_test.rb @@ -0,0 +1,55 @@ +require "isolation/abstract_unit" + +module ApplicationTests + class InitializersTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + FileUtils.rm_rf "#{app_path}/config/environments" + end + + test "load initializers" do + app_file "config/initializers/foo.rb", "$foo = true" + require "#{app_path}/config/environment" + assert $foo + end + + test "after_initialize block works correctly" do + add_to_config <<-RUBY + config.root = "#{app_path}" + config.after_initialize { $test_after_initialize_block1 = "success" } + config.after_initialize { $test_after_initialize_block2 = "congratulations" } + RUBY + require "#{app_path}/config/environment" + + assert_equal "success", $test_after_initialize_block1 + assert_equal "congratulations", $test_after_initialize_block2 + end + + test "after_initialize block works correctly when no block is passed" do + add_to_config <<-RUBY + config.root = "#{app_path}" + config.after_initialize { $test_after_initialize_block1 = "success" } + config.after_initialize # don't pass a block, this is what we're testing! + config.after_initialize { $test_after_initialize_block2 = "congratulations" } + RUBY + require "#{app_path}/config/environment" + + assert_equal "success", $test_after_initialize_block1 + assert_equal "congratulations", $test_after_initialize_block2 + end + + test "after_initialize runs after frameworks have been initialized" do + $activerecord_configurations = nil + add_to_config <<-RUBY + config.after_initialize { $activerecord_configurations = ActiveRecord::Base.configurations } + RUBY + + require "#{app_path}/config/environment" + assert $activerecord_configurations + assert $activerecord_configurations['development'] + end + end +end diff --git a/railties/test/application/initializers/load_path_test.rb b/railties/test/application/initializers/load_path_test.rb new file mode 100644 index 0000000000..b39b9ecaae --- /dev/null +++ b/railties/test/application/initializers/load_path_test.rb @@ -0,0 +1,74 @@ +require "isolation/abstract_unit" + +module ApplicationTests + class LoadPathTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + FileUtils.rm_rf "#{app_path}/config/environments" + end + + test "initializing an application adds the application paths to the load path" do + add_to_config <<-RUBY + config.root = "#{app_path}" + RUBY + + require "#{app_path}/config/environment" + assert $:.include?("#{app_path}/app/models") + end + + test "initializing an application eager load any path under app" do + app_file "app/anything/foo.rb", <<-RUBY + module Foo; end + RUBY + + add_to_config <<-RUBY + config.root = "#{app_path}" + RUBY + + require "#{app_path}/config/environment" + assert Foo + end + + test "eager loading loads parent classes before children" do + app_file "lib/zoo.rb", <<-ZOO + class Zoo ; include ReptileHouse ; end + ZOO + + app_file "lib/zoo/reptile_house.rb", <<-ZOO + module Zoo::ReptileHouse ; end + ZOO + + add_to_config <<-RUBY + config.root = "#{app_path}" + config.eager_load_paths << "#{app_path}/lib" + RUBY + + require "#{app_path}/config/environment" + assert Zoo + end + + test "load environment with global" do + app_file "config/environments/development.rb", <<-RUBY + $initialize_test_set_from_env = 'success' + AppTemplate::Application.configure do + config.cache_classes = true + config.time_zone = "Brasilia" + end + RUBY + + assert_nil $initialize_test_set_from_env + add_to_config <<-RUBY + config.root = "#{app_path}" + config.time_zone = "UTC" + RUBY + + require "#{app_path}/config/environment" + assert_equal "success", $initialize_test_set_from_env + assert AppTemplate::Application.config.cache_classes + assert_equal "Brasilia", AppTemplate::Application.config.time_zone + end + end +end diff --git a/railties/test/application/notifications_test.rb b/railties/test/application/initializers/notifications_test.rb index db8605edbe..061bb34c19 100644 --- a/railties/test/application/notifications_test.rb +++ b/railties/test/application/initializers/notifications_test.rb @@ -1,17 +1,6 @@ require "isolation/abstract_unit" module ApplicationTests - class MyQueue - def publish(name, *args) - raise name - end - - # Not a full queue implementation - def method_missing(name, *args, &blk) - self - end - end - class MockLogger def method_missing(*args) @logged ||= [] @@ -39,22 +28,6 @@ module ApplicationTests ActiveSupport::Notifications.notifier.wait end - test "new queue is set" do - # We don't want to load all frameworks, so remove them and clean up environments. - use_frameworks [] - FileUtils.rm_rf("#{app_path}/config/environments") - - add_to_config <<-RUBY - config.notifications.notifier = ActiveSupport::Notifications::Notifier.new(ApplicationTests::MyQueue.new) - RUBY - - require "#{app_path}/config/environment" - - assert_raise RuntimeError do - ActiveSupport::Notifications.publish('foo') - end - end - test "rails subscribers are added" do add_to_config <<-RUBY config.colorize_logging = false diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb index 31696598ce..0b92cdba54 100644 --- a/railties/test/application/middleware_test.rb +++ b/railties/test/application/middleware_test.rb @@ -23,7 +23,6 @@ module ApplicationTests "ActionDispatch::Cookies", "ActionDispatch::Session::CookieStore", "ActionDispatch::Flash", - "ActionDispatch::Cascade", "ActionDispatch::ParamsParser", "Rack::MethodOverride", "ActionDispatch::Head", @@ -70,6 +69,12 @@ module ApplicationTests assert_equal "Rack::Config", middleware.first end + test "shows cascade if any metal exists" do + app_file "app/metal/foo.rb", "class Foo; end" + boot! + assert middleware.include?("ActionDispatch::Cascade") + end + private def boot! require "#{app_path}/config/environment" diff --git a/railties/test/initializer/path_test.rb b/railties/test/application/paths_test.rb index 328dda6d2c..ac0aa27c64 100644 --- a/railties/test/initializer/path_test.rb +++ b/railties/test/application/paths_test.rb @@ -1,13 +1,14 @@ require "isolation/abstract_unit" -module InitializerTests - class PathTest < Test::Unit::TestCase +module ApplicationTests + class PathsTest < Test::Unit::TestCase include ActiveSupport::Testing::Isolation def setup build_app boot_rails FileUtils.rm_rf("#{app_path}/config/environments") + app_file "config/environments/development.rb", "" add_to_config <<-RUBY config.root = "#{app_path}" config.after_initialize do @@ -36,19 +37,18 @@ module InitializerTests end test "booting up Rails yields a valid paths object" do - assert_path @paths.app, "app" - assert_path @paths.app.metals, "app", "metal" assert_path @paths.app.models, "app", "models" + assert_path @paths.app.metals, "app", "metal" assert_path @paths.app.helpers, "app", "helpers" - assert_path @paths.app.services, "app", "services" + assert_path @paths.app.views, "app", "views" assert_path @paths.lib, "lib" assert_path @paths.vendor, "vendor" assert_path @paths.vendor.plugins, "vendor", "plugins" assert_path @paths.tmp, "tmp" assert_path @paths.tmp.cache, "tmp", "cache" assert_path @paths.config, "config" - assert_path @paths.config.locales, "config", "locales" - assert_path @paths.config.environments, "config", "environments" + assert_path @paths.config.locales, "config", "locales", "en.yml" + assert_path @paths.config.environment, "config", "environments", "development.rb" assert_equal root("app", "controllers"), @paths.app.controllers.to_a.first assert_equal Pathname.new(File.dirname(__FILE__)).join("..", "..", "builtin", "rails_info").expand_path, @@ -56,27 +56,23 @@ module InitializerTests end test "booting up Rails yields a list of paths that are eager" do - assert @paths.app.models.eager_load? + assert @paths.app.eager_load? assert @paths.app.controllers.eager_load? assert @paths.app.helpers.eager_load? - assert @paths.app.metals.eager_load? end test "environments has a glob equal to the current environment" do - assert_equal "#{Rails.env}.rb", @paths.config.environments.glob + assert_equal "#{Rails.env}.rb", @paths.config.environment.glob end test "load path includes each of the paths in config.paths as long as the directories exist" do - assert_in_load_path "app" assert_in_load_path "app", "controllers" assert_in_load_path "app", "models" assert_in_load_path "app", "helpers" assert_in_load_path "lib" assert_in_load_path "vendor" - assert_not_in_load_path "app", "views" assert_not_in_load_path "app", "metal" - assert_not_in_load_path "app", "services" assert_not_in_load_path "config" assert_not_in_load_path "config", "locales" assert_not_in_load_path "config", "environments" @@ -86,17 +82,17 @@ module InitializerTests test "controller paths include builtin in development mode" do Rails.env.replace "development" - assert Rails::Configuration.new.paths.app.controllers.paths.any? { |p| p =~ /builtin/ } + assert Rails::Application::Configuration.new("/").paths.app.controllers.paths.any? { |p| p =~ /builtin/ } end test "controller paths does not have builtin_directories in test mode" do Rails.env.replace "test" - assert !Rails::Configuration.new.paths.app.controllers.paths.any? { |p| p =~ /builtin/ } + assert !Rails::Application::Configuration.new("/").paths.app.controllers.paths.any? { |p| p =~ /builtin/ } end test "controller paths does not have builtin_directories in production mode" do Rails.env.replace "production" - assert !Rails::Configuration.new.paths.app.controllers.paths.any? { |p| p =~ /builtin/ } + assert !Rails::Application::Configuration.new("/").paths.app.controllers.paths.any? { |p| p =~ /builtin/ } end end diff --git a/railties/test/application/load_test.rb b/railties/test/application/rackup_test.rb index 1c5811b07a..f909c1b282 100644 --- a/railties/test/application/load_test.rb +++ b/railties/test/application/rackup_test.rb @@ -1,7 +1,7 @@ require "isolation/abstract_unit" module ApplicationTests - class LoadTest < Test::Unit::TestCase + class RackupTest < Test::Unit::TestCase include ActiveSupport::Testing::Isolation def rackup diff --git a/railties/test/application/routing_test.rb b/railties/test/application/routing_test.rb index 50cb9e3acc..b93e349a46 100644 --- a/railties/test/application/routing_test.rb +++ b/railties/test/application/routing_test.rb @@ -14,7 +14,6 @@ module ApplicationTests def app @app ||= begin require "#{app_path}/config/environment" - Rails.application end end @@ -26,7 +25,7 @@ module ApplicationTests test "simple controller" do controller :foo, <<-RUBY - class FooController < ActionController::Base + class FooController < ApplicationController def index render :text => "foo" end @@ -43,9 +42,36 @@ module ApplicationTests assert_equal 'foo', last_response.body end + test "simple controller with helper" do + controller :foo, <<-RUBY + class FooController < ApplicationController + def index + render :inline => "<%= foo_or_bar? %>" + end + end + RUBY + + app_file 'app/helpers/bar_helper.rb', <<-RUBY + module BarHelper + def foo_or_bar? + "bar" + end + end + RUBY + + app_file 'config/routes.rb', <<-RUBY + AppTemplate::Application.routes.draw do |map| + match ':controller(/:action)' + end + RUBY + + get '/foo' + assert_equal 'bar', last_response.body + end + test "multiple controllers" do controller :foo, <<-RUBY - class FooController < ActionController::Base + class FooController < ApplicationController def index render :text => "foo" end @@ -75,7 +101,7 @@ module ApplicationTests test "nested controller" do controller 'foo', <<-RUBY - class FooController < ActionController::Base + class FooController < ApplicationController def index render :text => "foo" end @@ -84,7 +110,7 @@ module ApplicationTests controller 'admin/foo', <<-RUBY module Admin - class FooController < ActionController::Base + class FooController < ApplicationController def index render :text => "admin::foo" end @@ -105,47 +131,9 @@ module ApplicationTests assert_equal 'admin::foo', last_response.body end - test "merges with plugin routes" do - controller 'foo', <<-RUBY - class FooController < ActionController::Base - def index - render :text => "foo" - end - end - RUBY - - app_file 'config/routes.rb', <<-RUBY - AppTemplate::Application.routes.draw do |map| - match 'foo', :to => 'foo#index' - end - RUBY - - plugin 'bar', 'require File.dirname(__FILE__) + "/app/controllers/bar"' do |plugin| - plugin.write 'app/controllers/bar.rb', <<-RUBY - class BarController < ActionController::Base - def index - render :text => "bar" - end - end - RUBY - - plugin.write 'config/routes.rb', <<-RUBY - AppTemplate::Application.routes.draw do |map| - match 'bar', :to => 'bar#index' - end - RUBY - end - - get '/foo' - assert_equal 'foo', last_response.body - - get '/bar' - assert_equal 'bar', last_response.body - end - test "reloads routes when configuration is changed" do controller :foo, <<-RUBY - class FooController < ActionController::Base + class FooController < ApplicationController def bar render :text => "bar" end @@ -191,7 +179,7 @@ module ApplicationTests RUBY controller 'yazilar', <<-RUBY - class YazilarController < ActionController::Base + class YazilarController < ApplicationController def index render :text => 'yazilar#index' end diff --git a/railties/test/fixtures/eager/zoo.rb b/railties/test/fixtures/eager/zoo.rb deleted file mode 100644 index 8b10ef984b..0000000000 --- a/railties/test/fixtures/eager/zoo.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Zoo - include ReptileHouse -end
\ No newline at end of file diff --git a/railties/test/fixtures/eager/zoo/reptile_house.rb b/railties/test/fixtures/eager/zoo/reptile_house.rb deleted file mode 100644 index 82bbafce79..0000000000 --- a/railties/test/fixtures/eager/zoo/reptile_house.rb +++ /dev/null @@ -1,2 +0,0 @@ -module Zoo::ReptileHouse -end
\ No newline at end of file diff --git a/railties/test/fixtures/environment_with_constant.rb b/railties/test/fixtures/environment_with_constant.rb deleted file mode 100644 index 23e1f7afd9..0000000000 --- a/railties/test/fixtures/environment_with_constant.rb +++ /dev/null @@ -1 +0,0 @@ -$initialize_test_set_from_env = 'success' diff --git a/railties/test/fixtures/plugins/alternate/a/generators/a_generator/a_generator.rb b/railties/test/fixtures/plugins/alternate/a/generators/a_generator/a_generator.rb deleted file mode 100644 index b33f2dad18..0000000000 --- a/railties/test/fixtures/plugins/alternate/a/generators/a_generator/a_generator.rb +++ /dev/null @@ -1,4 +0,0 @@ -class AGenerator < Rails::Generator::Base - def manifest - end -end diff --git a/railties/test/fixtures/plugins/alternate/a/lib/.gitignore b/railties/test/fixtures/plugins/alternate/a/lib/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/railties/test/fixtures/plugins/alternate/a/lib/.gitignore +++ /dev/null diff --git a/railties/test/fixtures/plugins/default/acts/acts_as_chunky_bacon/lib/.gitignore b/railties/test/fixtures/plugins/default/acts/acts_as_chunky_bacon/lib/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/railties/test/fixtures/plugins/default/acts/acts_as_chunky_bacon/lib/.gitignore +++ /dev/null diff --git a/railties/test/fixtures/plugins/default/empty/.gitignore b/railties/test/fixtures/plugins/default/empty/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/railties/test/fixtures/plugins/default/empty/.gitignore +++ /dev/null diff --git a/railties/test/fixtures/plugins/default/gemlike/init.rb b/railties/test/fixtures/plugins/default/gemlike/init.rb deleted file mode 100644 index 6a771b5b68..0000000000 --- a/railties/test/fixtures/plugins/default/gemlike/init.rb +++ /dev/null @@ -1 +0,0 @@ -raise 'This init.rb should not be evaluated because rails/init.rb exists' diff --git a/railties/test/fixtures/plugins/default/gemlike/lib/gemlike.rb b/railties/test/fixtures/plugins/default/gemlike/lib/gemlike.rb deleted file mode 100644 index 2088103e45..0000000000 --- a/railties/test/fixtures/plugins/default/gemlike/lib/gemlike.rb +++ /dev/null @@ -1,2 +0,0 @@ -module Gemlike -end
\ No newline at end of file diff --git a/railties/test/fixtures/plugins/default/gemlike/rails/init.rb b/railties/test/fixtures/plugins/default/gemlike/rails/init.rb deleted file mode 100644 index 171a293eb3..0000000000 --- a/railties/test/fixtures/plugins/default/gemlike/rails/init.rb +++ /dev/null @@ -1,7 +0,0 @@ -# I have access to my directory and the Rails config. -raise 'directory expected but undefined in init.rb' unless defined? directory -raise 'config expected but undefined in init.rb' unless defined? config - -# My lib/ dir must be in the load path. -require 'gemlike' -raise 'missing mixin from my lib/ dir' unless defined? Gemlike diff --git a/railties/test/fixtures/plugins/default/plugin_with_no_lib_dir/init.rb b/railties/test/fixtures/plugins/default/plugin_with_no_lib_dir/init.rb deleted file mode 100644 index e69de29bb2..0000000000 --- a/railties/test/fixtures/plugins/default/plugin_with_no_lib_dir/init.rb +++ /dev/null diff --git a/railties/test/fixtures/plugins/default/stubby/about.yml b/railties/test/fixtures/plugins/default/stubby/about.yml deleted file mode 100644 index d85a7cc0e3..0000000000 --- a/railties/test/fixtures/plugins/default/stubby/about.yml +++ /dev/null @@ -1,2 +0,0 @@ -author: Plugin Author -version: 1.0.0
\ No newline at end of file diff --git a/railties/test/fixtures/plugins/default/stubby/init.rb b/railties/test/fixtures/plugins/default/stubby/init.rb deleted file mode 100644 index 81beeb0d32..0000000000 --- a/railties/test/fixtures/plugins/default/stubby/init.rb +++ /dev/null @@ -1,7 +0,0 @@ -# I have access to my directory and the Rails config. -raise 'directory expected but undefined in init.rb' unless defined? directory -raise 'config expected but undefined in init.rb' unless defined? config - -# My lib/ dir must be in the load path. -require 'stubby_mixin' -raise 'missing mixin from my lib/ dir' unless defined? StubbyMixin diff --git a/railties/test/fixtures/plugins/default/stubby/lib/stubby_mixin.rb b/railties/test/fixtures/plugins/default/stubby/lib/stubby_mixin.rb deleted file mode 100644 index 2d569e5002..0000000000 --- a/railties/test/fixtures/plugins/default/stubby/lib/stubby_mixin.rb +++ /dev/null @@ -1,2 +0,0 @@ -module StubbyMixin -end diff --git a/railties/test/fixtures/plugins/engines/engine/app/controllers/engine_controller.rb b/railties/test/fixtures/plugins/engines/engine/app/controllers/engine_controller.rb deleted file mode 100644 index 323ee1c4dc..0000000000 --- a/railties/test/fixtures/plugins/engines/engine/app/controllers/engine_controller.rb +++ /dev/null @@ -1,2 +0,0 @@ -class EngineController -end
\ No newline at end of file diff --git a/railties/test/fixtures/plugins/engines/engine/app/metal/engine_metal.rb b/railties/test/fixtures/plugins/engines/engine/app/metal/engine_metal.rb deleted file mode 100644 index d67a127ca7..0000000000 --- a/railties/test/fixtures/plugins/engines/engine/app/metal/engine_metal.rb +++ /dev/null @@ -1,10 +0,0 @@ -class EngineMetal - def self.call(env) - if env["PATH_INFO"] =~ /^\/metal/ - [200, {"Content-Type" => "text/html"}, ["Engine metal"]] - else - [404, {"Content-Type" => "text/html"}, ["Not Found"]] - end - end -end - diff --git a/railties/test/fixtures/plugins/engines/engine/app/models/engine_model.rb b/railties/test/fixtures/plugins/engines/engine/app/models/engine_model.rb deleted file mode 100644 index e265712185..0000000000 --- a/railties/test/fixtures/plugins/engines/engine/app/models/engine_model.rb +++ /dev/null @@ -1,2 +0,0 @@ -class EngineModel -end
\ No newline at end of file diff --git a/railties/test/fixtures/plugins/engines/engine/config/locales/en.yml b/railties/test/fixtures/plugins/engines/engine/config/locales/en.yml deleted file mode 100644 index 641a7e035c..0000000000 --- a/railties/test/fixtures/plugins/engines/engine/config/locales/en.yml +++ /dev/null @@ -1,2 +0,0 @@ -en: - hello: "Hello from Engine" diff --git a/railties/test/fixtures/plugins/engines/engine/config/routes.rb b/railties/test/fixtures/plugins/engines/engine/config/routes.rb deleted file mode 100644 index da44595693..0000000000 --- a/railties/test/fixtures/plugins/engines/engine/config/routes.rb +++ /dev/null @@ -1,3 +0,0 @@ -ActionController::Routing::Routes.draw do |map| - match '/engine', :to => "engine" -end diff --git a/railties/test/fixtures/plugins/engines/engine/init.rb b/railties/test/fixtures/plugins/engines/engine/init.rb deleted file mode 100644 index 64e9ae6c30..0000000000 --- a/railties/test/fixtures/plugins/engines/engine/init.rb +++ /dev/null @@ -1,3 +0,0 @@ -# My app/models dir must be in the load path. -require 'engine_model' -raise LoadError, 'missing model from my app/models dir' unless defined?(EngineModel) diff --git a/railties/test/generators/generators_test_helper.rb b/railties/test/generators/generators_test_helper.rb index 3cd16a69f9..d17be5b964 100644 --- a/railties/test/generators/generators_test_helper.rb +++ b/railties/test/generators/generators_test_helper.rb @@ -9,7 +9,7 @@ Rails.application.config.root = Rails.root require 'rails/generators' require 'rails/generators/test_case' - +Rails::Generators.configure! require 'active_record' require 'action_dispatch' diff --git a/railties/test/generators/mailer_generator_test.rb b/railties/test/generators/mailer_generator_test.rb index dfc3130f77..e6fc1bbb5c 100644 --- a/railties/test/generators/mailer_generator_test.rb +++ b/railties/test/generators/mailer_generator_test.rb @@ -7,7 +7,18 @@ class MailerGeneratorTest < Rails::Generators::TestCase def test_mailer_skeleton_is_created run_generator - assert_file "app/mailers/notifier.rb", /class Notifier < ActionMailer::Base/ + assert_file "app/mailers/notifier.rb" do |mailer| + assert_match /class Notifier < ActionMailer::Base/, mailer + assert_match /default :from => "from@example.com"/, mailer + end + end + + def test_mailer_with_i18n_helper + run_generator + assert_file "app/mailers/notifier.rb" do |mailer| + assert_match /en\.actionmailer\.notifier\.foo\.subject/, mailer + assert_match /en\.actionmailer\.notifier\.bar\.subject/, mailer + end end def test_check_class_collision @@ -24,8 +35,15 @@ class MailerGeneratorTest < Rails::Generators::TestCase def test_invokes_default_template_engine run_generator - assert_file "app/views/notifier/foo.erb", /app\/views\/notifier\/foo/ - assert_file "app/views/notifier/bar.erb", /app\/views\/notifier\/bar/ + assert_file "app/views/notifier/foo.text.erb" do |view| + assert_match /app\/views\/notifier\/foo/, view + assert_match /<%= @greeting %>/, view + end + + assert_file "app/views/notifier/bar.text.erb" do |view| + assert_match /app\/views\/notifier\/bar/, view + assert_match /<%= @greeting %>/, view + end end def test_invokes_default_template_engine_even_with_no_action @@ -40,7 +58,18 @@ class MailerGeneratorTest < Rails::Generators::TestCase def test_actions_are_turned_into_methods run_generator - assert_file "app/mailers/notifier.rb", /def foo/ - assert_file "app/mailers/notifier.rb", /def bar/ + + assert_file "app/mailers/notifier.rb" do |mailer| + assert_instance_method :foo, mailer do |foo| + assert_match /mail :to => "to@example.org"/, foo + assert_match /@greeting = "Hi"/, foo + end + + assert_instance_method :bar, mailer do |bar| + assert_match /mail :to => "to@example.org"/, bar + assert_match /@greeting = "Hi"/, bar + end + end + end end diff --git a/railties/test/generators/named_base_test.rb b/railties/test/generators/named_base_test.rb index 99eb431a49..f327fb1282 100644 --- a/railties/test/generators/named_base_test.rb +++ b/railties/test/generators/named_base_test.rb @@ -16,28 +16,68 @@ class NamedBaseTest < Rails::Generators::TestCase tests Rails::Generators::ScaffoldControllerGenerator def test_named_generator_attributes - g = generator ["admin/foo"] - assert_equal 'admin/foo', g.name - assert_equal %w(admin), g.class_path - assert_equal 1, g.class_nesting_depth - assert_equal 'Admin::Foo', g.class_name - assert_equal 'foo', g.singular_name - assert_equal 'foos', g.plural_name - assert_equal g.singular_name, g.file_name - assert_equal "admin_#{g.plural_name}", g.table_name + g = generator ['admin/foo'] + assert_name g, 'admin/foo', :name + assert_name g, %w(admin), :class_path + assert_name g, 'Admin::Foo', :class_name + assert_name g, 'admin/foo', :file_path + assert_name g, 'foo', :file_name + assert_name g, 'foo', :singular_name + assert_name g, 'foos', :plural_name + assert_name g, 'admin.foo', :i18n_scope + assert_name g, 'admin_foos', :table_name + end + + def test_named_generator_attributes_as_ruby + g = generator ['Admin::Foo'] + assert_name g, 'Admin::Foo', :name + assert_name g, %w(admin), :class_path + assert_name g, 'Admin::Foo', :class_name + assert_name g, 'admin/foo', :file_path + assert_name g, 'foo', :file_name + assert_name g, 'foo', :singular_name + assert_name g, 'foos', :plural_name + assert_name g, 'admin.foo', :i18n_scope + assert_name g, 'admin_foos', :table_name end def test_named_generator_attributes_without_pluralized ActiveRecord::Base.pluralize_table_names = false - g = generator ["admin/foo"] - assert_equal "admin_#{g.singular_name}", g.table_name + g = generator ['admin/foo'] + assert_name g, 'admin_foo', :table_name end def test_scaffold_plural_names - g = generator ["ProductLine"] - assert_equal "ProductLines", g.controller_name - assert_equal "ProductLines", g.controller_class_name - assert_equal "product_lines", g.controller_file_name + g = generator ['admin/foo'] + assert_name g, 'admin/foos', :controller_name + assert_name g, %w(admin), :controller_class_path + assert_name g, 'Admin::Foos', :controller_class_name + assert_name g, 'admin/foos', :controller_file_path + assert_name g, 'foos', :controller_file_name + assert_name g, 'admin.foos', :controller_i18n_scope + end + + def test_scaffold_plural_names_as_ruby + g = generator ['Admin::Foo'] + assert_name g, 'Admin::Foos', :controller_name + assert_name g, %w(admin), :controller_class_path + assert_name g, 'Admin::Foos', :controller_class_name + assert_name g, 'admin/foos', :controller_file_path + assert_name g, 'foos', :controller_file_name + assert_name g, 'admin.foos', :controller_i18n_scope end + def test_application_name + g = generator ['Admin::Foo'] + Rails.stubs(:application).returns(Object.new) + assert_name g, "object", :application_name + Rails.stubs(:application).returns(nil) + assert_name g, "application", :application_name + end + + protected + + def assert_name(generator, value, method) + assert_equal value, generator.send(method) + end end diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb index 0a79e2cfb8..065dbe1423 100644 --- a/railties/test/generators/plugin_generator_test.rb +++ b/railties/test/generators/plugin_generator_test.rb @@ -48,7 +48,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase def test_creates_tasks_if_required run_generator ["plugin_fu", "--tasks"] - assert_file "vendor/plugins/plugin_fu/tasks/plugin_fu_tasks.rake" + assert_file "vendor/plugins/plugin_fu/lib/tasks/plugin_fu_tasks.rake" end def test_creates_generator_if_required diff --git a/railties/test/generators_test.rb b/railties/test/generators_test.rb index f37b684f73..33cc27bd84 100644 --- a/railties/test/generators_test.rb +++ b/railties/test/generators_test.rb @@ -99,6 +99,7 @@ class GeneratorsTest < Rails::Generators::TestCase assert_match /Rails:/, output assert_match /^ model$/, output assert_match /^ scaffold_controller$/, output + assert_no_match /^ app$/, output end def test_rails_generators_with_others_information diff --git a/railties/test/initializable_test.rb b/railties/test/initializable_test.rb index e308cbcb0e..0c7378cb64 100644 --- a/railties/test/initializable_test.rb +++ b/railties/test/initializable_test.rb @@ -10,14 +10,14 @@ module InitializableTests attr_accessor :foo, :bar end - initializer :omg, :global => true do + initializer :omg do @foo ||= 0 @foo += 1 end end class Bar < Foo - initializer :bar, :global => true do + initializer :bar do @bar ||= 0 @bar += 1 end @@ -26,7 +26,7 @@ module InitializableTests module Word include Rails::Initializable - initializer :word, :global => true do + initializer :word do $word = "bird" end end @@ -34,11 +34,11 @@ module InitializableTests class Parent include Rails::Initializable - initializer :one, :global => true do + initializer :one do $arr << 1 end - initializer :two, :global => true do + initializer :two do $arr << 2 end end @@ -46,17 +46,17 @@ module InitializableTests class Child < Parent include Rails::Initializable - initializer :three, :before => :one, :global => true do + initializer :three, :before => :one do $arr << 3 end - initializer :four, :after => :one, :global => true do + initializer :four, :after => :one do $arr << 4 end end class Parent - initializer :five, :before => :one, :global => true do + initializer :five, :before => :one do $arr << 5 end end @@ -72,11 +72,11 @@ module InitializableTests $arr << 2 end - initializer :three, :global => true do + initializer :three do $arr << 3 end - initializer :four, :global => true do + initializer :four do $arr << 4 end end @@ -181,13 +181,7 @@ module InitializableTests $arr = [] instance = Instance.new instance.run_initializers - assert_equal [1, 2], $arr - end - - test "running globals" do - $arr = [] - Instance.run_initializers - assert_equal [3, 4], $arr + assert_equal [1, 2, 3, 4], $arr end end diff --git a/railties/test/initializer/initialize_i18n_test.rb b/railties/test/initializer/initialize_i18n_test.rb deleted file mode 100644 index 472566378d..0000000000 --- a/railties/test/initializer/initialize_i18n_test.rb +++ /dev/null @@ -1,55 +0,0 @@ -require "isolation/abstract_unit" - -module InitializerTests - class InitializeI18nTest < Test::Unit::TestCase - include ActiveSupport::Testing::Isolation - - def setup - build_app - boot_rails - end - - # test_config_defaults_and_settings_should_be_added_to_i18n_defaults - test "i18n config defaults and settings should be added to i18n defaults" do - add_to_config <<-RUBY - config.root = "#{app_path}" - config.i18n.load_path << "my/other/locale.yml" - RUBY - require "#{app_path}/config/environment" - - #{RAILS_FRAMEWORK_ROOT}/railties/test/fixtures/plugins/engines/engine/config/locales/en.yml - assert_equal %W( - #{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/locale/en.yml - #{RAILS_FRAMEWORK_ROOT}/activemodel/lib/active_model/locale/en.yml - #{RAILS_FRAMEWORK_ROOT}/activerecord/lib/active_record/locale/en.yml - #{RAILS_FRAMEWORK_ROOT}/actionpack/lib/action_view/locale/en.yml - #{RAILS_FRAMEWORK_ROOT}/railties/tmp/app/config/locales/en.yml - my/other/locale.yml - ).map { |path| File.expand_path(path) }, I18n.load_path.map { |path| File.expand_path(path) } - end - - test "i18n finds locale files in engines" do - # app_file "vendor/plugins/engine/init.rb", "" - # app_file "vendor/plugins/engine/app/models/hellos.rb", "class Hello ; end" - # app_file "vendor/plugins/engine/lib/omg.rb", "puts 'omg'" - # app_file "vendor/plugins/engine/config/locales/en.yml", "hello:" - # - # Rails::Initializer.run do |c| - # c.root = app_path - # c.i18n.load_path << "my/other/locale.yml" - # end - # Rails.initialize! - # - # #{RAILS_FRAMEWORK_ROOT}/railties/test/fixtures/plugins/engines/engine/config/locales/en.yml - # assert_equal %W( - # #{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/locale/en.yml - # #{RAILS_FRAMEWORK_ROOT}/activemodel/lib/active_model/locale/en.yml - # #{RAILS_FRAMEWORK_ROOT}/activerecord/lib/active_record/locale/en.yml - # #{RAILS_FRAMEWORK_ROOT}/actionpack/lib/action_view/locale/en.yml - # #{app_path}/config/locales/en.yml - # my/other/locale.yml - # #{app_path}/vendor/plugins/engine/config/locales/en.yml - # ).map { |path| File.expand_path(path) }, I18n.load_path.map { |path| File.expand_path(path) } - end - end -end
\ No newline at end of file diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index dc5fddb19d..940585836c 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -100,6 +100,8 @@ module TestHelpers end class Bukkit + attr_reader :path + def initialize(path) @path = path end @@ -118,10 +120,29 @@ module TestHelpers def plugin(name, string = "") dir = "#{app_path}/vendor/plugins/#{name}" FileUtils.mkdir_p(dir) + File.open("#{dir}/init.rb", 'w') do |f| f.puts "::#{name.upcase} = 'loaded'" f.puts string end + + Bukkit.new(dir).tap do |bukkit| + yield bukkit if block_given? + end + end + + def engine(name) + dir = "#{app_path}/random/#{name}" + FileUtils.mkdir_p(dir) + + app = File.readlines("#{app_path}/config/application.rb") + app.insert(2, "$:.unshift(\"#{dir}/lib\")") + app.insert(3, "require #{name.inspect}") + + File.open("#{app_path}/config/application.rb", 'r+') do |f| + f.puts app + end + Bukkit.new(dir).tap do |bukkit| yield bukkit if block_given? end diff --git a/railties/test/mocks/routes.rb b/railties/test/mocks/routes.rb deleted file mode 100644 index ea12863683..0000000000 --- a/railties/test/mocks/routes.rb +++ /dev/null @@ -1,6 +0,0 @@ -module ActionController - module Routing - class Routes - end - end -end diff --git a/railties/test/paths_test.rb b/railties/test/paths_test.rb index d60d6177f6..92c7b2ba0e 100644 --- a/railties/test/paths_test.rb +++ b/railties/test/paths_test.rb @@ -3,22 +3,23 @@ require 'rails/paths' class PathsTest < ActiveSupport::TestCase def setup - @root = Rails::Application::Root.new("/foo/bar") + File.stubs(:exists?).returns(true) + @root = Rails::Paths::Root.new("/foo/bar") end test "the paths object is initialized with the root path" do - root = Rails::Application::Root.new("/fiz/baz") + root = Rails::Paths::Root.new("/fiz/baz") assert_equal "/fiz/baz", root.path end test "the paths object can be initialized with nil" do assert_nothing_raised do - Rails::Application::Root.new(nil) + Rails::Paths::Root.new(nil) end end test "a paths object initialized with nil can be updated" do - root = Rails::Application::Root.new(nil) + root = Rails::Paths::Root.new(nil) root.app = "app" root.path = "/root" assert_equal ["/root/app"], root.app.to_a @@ -30,7 +31,7 @@ class PathsTest < ActiveSupport::TestCase end test "raises exception if root path never set" do - root = Rails::Application::Root.new(nil) + root = Rails::Paths::Root.new(nil) root.app = "app" assert_raises RuntimeError do root.app.to_a @@ -110,7 +111,7 @@ class PathsTest < ActiveSupport::TestCase end test "the root can only have one physical path" do - assert_raise(RuntimeError) { Rails::Application::Root.new(["/fiz", "/biz"]) } + assert_raise(RuntimeError) { Rails::Paths::Root.new(["/fiz", "/biz"]) } assert_raise(RuntimeError) { @root.push "/biz" } assert_raise(RuntimeError) { @root.unshift "/biz" } assert_raise(RuntimeError) { @root.concat ["/biz"]} @@ -193,12 +194,7 @@ class PathsTest < ActiveSupport::TestCase assert_equal 2, @root.eager_load.size end - test "a path should have a glob that defaults to **/*.rb" do - @root.app = "/app" - assert_equal "**/*.rb", @root.app.glob - end - - test "it should be possible to override a path's default glob" do + test "it should be possible to add a path's default glob" do @root.app = "/app" @root.app.glob = "*.rb" assert_equal "*.rb", @root.app.glob @@ -227,4 +223,11 @@ class PathsTest < ActiveSupport::TestCase @root.app.eager_load! assert_equal ["/foo/bar/app"], @root.load_paths end + + test "adding a path to the load once paths also adds it to the load path" do + @root.app = "app" + @root.app.load_once! + assert_equal ["/foo/bar/app"], @root.load_paths + end + end diff --git a/railties/test/plugins/configuration_test.rb b/railties/test/plugins/configuration_test.rb deleted file mode 100644 index 09f8943af9..0000000000 --- a/railties/test/plugins/configuration_test.rb +++ /dev/null @@ -1,45 +0,0 @@ -require "isolation/abstract_unit" - -module PluginsTest - class ConfigurationTest < Test::Unit::TestCase - def setup - build_app - boot_rails - require "rails/all" - end - - test "config is available to plugins" do - class Foo < Rails::Railtie ; end - assert_nil Foo.config.action_controller.foo - end - - test "a config name is available for the plugin" do - class Foo < Rails::Railtie ; config.foo.greetings = "hello" ; end - assert_equal "hello", Foo.config.foo.greetings - end - - test "plugin configurations are available in the application" do - class Foo < Rails::Railtie ; config.foo.greetings = "hello" ; end - require "#{app_path}/config/application" - assert_equal "hello", AppTemplate::Application.config.foo.greetings - end - - test "plugin config merges are deep" do - class Foo < Rails::Railtie ; config.foo.greetings = 'hello' ; end - class MyApp < Rails::Application - config.foo.bar = "bar" - end - assert_equal "hello", MyApp.config.foo.greetings - assert_equal "bar", MyApp.config.foo.bar - end - - test "plugin can add subscribers" do - begin - class Foo < Rails::Railtie; subscriber(Rails::Subscriber.new); end - assert_kind_of Rails::Subscriber, Rails::Subscriber.subscribers[:foo] - ensure - Rails::Subscriber.subscribers.clear - end - end - end -end diff --git a/railties/test/plugins/framework_extension_test.rb b/railties/test/plugins/framework_extension_test.rb deleted file mode 100644 index d57fd4e635..0000000000 --- a/railties/test/plugins/framework_extension_test.rb +++ /dev/null @@ -1,68 +0,0 @@ -require "isolation/abstract_unit" - -module PluginsTest - class FrameworkExtensionTest < Test::Unit::TestCase - include ActiveSupport::Testing::Isolation - - def setup - build_app - boot_rails - FileUtils.rm_rf("#{app_path}/config/environments") - require "rails/all" - end - - test "rake_tasks block is executed when MyApp.load_tasks is called" do - $ran_block = false - - class MyTie < Rails::Railtie - rake_tasks do - $ran_block = true - end - end - - require "#{app_path}/config/environment" - - assert !$ran_block - require 'rake' - require 'rake/testtask' - require 'rake/rdoctask' - - AppTemplate::Application.load_tasks - assert $ran_block - end - - test "generators block is executed when MyApp.load_generators is called" do - $ran_block = false - - class MyTie < Rails::Railtie - generators do - $ran_block = true - end - end - - require "#{app_path}/config/environment" - - assert !$ran_block - AppTemplate::Application.load_generators - assert $ran_block - end - end - - class ActiveRecordExtensionTest < Test::Unit::TestCase - include ActiveSupport::Testing::Isolation - - def setup - build_app - boot_rails - FileUtils.rm_rf("#{app_path}/config/environments") - end - - test "active_record extensions are applied to ActiveRecord" do - add_to_config "config.active_record.table_name_prefix = 'tbl_'" - - require "#{app_path}/config/environment" - - assert_equal 'tbl_', ActiveRecord::Base.table_name_prefix - end - end -end
\ No newline at end of file diff --git a/railties/test/plugins/vendored_test.rb b/railties/test/plugins/vendored_test.rb deleted file mode 100644 index b3b85891b2..0000000000 --- a/railties/test/plugins/vendored_test.rb +++ /dev/null @@ -1,201 +0,0 @@ -require "isolation/abstract_unit" - -module PluginsTest - class VendoredTest < Test::Unit::TestCase - include ActiveSupport::Testing::Isolation - - def setup - build_app - - @plugin = plugin "bukkits", "::LEVEL = config.log_level" do |plugin| - plugin.write "lib/bukkits.rb", "class Bukkits; end" - end - end - - def boot_rails - super - require "#{app_path}/config/environment" - end - - test "it loads the plugin's init.rb file" do - boot_rails - assert_equal "loaded", BUKKITS - end - - test "the init.rb file has access to the config object" do - boot_rails - assert_equal :debug, LEVEL - end - - test "the plugin puts its lib directory on the load path" do - boot_rails - require "bukkits" - assert_equal "Bukkits", Bukkits.name - end - - test "plugin paths get added to the AS::Dependency list" do - boot_rails - assert_equal "Bukkits", Bukkits.name - end - - test "plugin constants do not get reloaded by default" do - boot_rails - assert_equal "Bukkits", Bukkits.name - ActiveSupport::Dependencies.clear - @plugin.delete("lib/bukkits.rb") - assert_nothing_raised { Bukkits } - end - - test "plugin constants get reloaded if config.reload_plugins is set" do - add_to_config <<-RUBY - config.reload_plugins = true - RUBY - - boot_rails - - assert_equal "Bukkits", Bukkits.name - ActiveSupport::Dependencies.clear - @plugin.delete("lib/bukkits.rb") - assert_raises(NameError) { Bukkits } - end - - test "plugin should work without init.rb" do - @plugin.delete("init.rb") - - boot_rails - - require "bukkits" - assert_nothing_raised { Bukkits } - end - - test "the plugin puts its models directory on the load path" do - @plugin.write "app/models/my_bukkit.rb", "class MyBukkit ; end" - - boot_rails - - assert_nothing_raised { MyBukkit } - end - - test "the plugin puts is controllers directory on the load path" do - @plugin.write "app/controllers/bukkit_controller.rb", "class BukkitController ; end" - - boot_rails - - assert_nothing_raised { BukkitController } - end - - test "the plugin adds its view to the load path" do - @plugin.write "app/controllers/bukkit_controller.rb", <<-RUBY - class BukkitController < ActionController::Base - def index - end - end - RUBY - - @plugin.write "app/views/bukkit/index.html.erb", "Hello bukkits" - - boot_rails - - require "action_controller" - require "rack/mock" - response = BukkitController.action(:index).call(Rack::MockRequest.env_for("/")) - assert_equal "Hello bukkits\n", response[2].body - end - - test "the plugin adds helpers to the controller's views" do - @plugin.write "app/controllers/bukkit_controller.rb", <<-RUBY - class BukkitController < ActionController::Base - def index - end - end - RUBY - - @plugin.write "app/helpers/bukkit_helper.rb", <<-RUBY - module BukkitHelper - def bukkits - "bukkits" - end - end - RUBY - - @plugin.write "app/views/bukkit/index.html.erb", "Hello <%= bukkits %>" - - boot_rails - - require "rack/mock" - response = BukkitController.action(:index).call(Rack::MockRequest.env_for("/")) - assert_equal "Hello bukkits\n", response[2].body - end - - test "routes.rb are added to the router" do - @plugin.write "config/routes.rb", <<-RUBY - class Sprokkit - def self.call(env) - [200, {'Content-Type' => 'text/html'}, ["I am a Sprokkit"]] - end - end - - ActionController::Routing::Routes.draw do - match "/sprokkit", :to => Sprokkit - end - RUBY - - boot_rails - require "rack/mock" - response = Rails.application.call(Rack::MockRequest.env_for("/sprokkit")) - assert_equal "I am a Sprokkit", response[2].join - end - end - - class VendoredOrderingTest < Test::Unit::TestCase - include ActiveSupport::Testing::Isolation - - def setup - build_app - $arr = [] - plugin "a_plugin", "$arr << :a" - plugin "b_plugin", "$arr << :b" - plugin "c_plugin", "$arr << :c" - end - - def boot_rails - super - require "#{app_path}/config/environment" - end - - test "plugins are loaded alphabetically by default" do - boot_rails - assert_equal [:a, :b, :c], $arr - end - - test "if specified, only those plugins are loaded" do - add_to_config "config.plugins = [:b_plugin]" - boot_rails - assert_equal [:b], $arr - end - - test "the plugins are initialized in the order they are specified" do - add_to_config "config.plugins = [:b_plugin, :a_plugin]" - boot_rails - assert_equal [:b, :a], $arr - end - - test "if :all is specified, the remaining plugins are loaded in alphabetical order" do - add_to_config "config.plugins = [:c_plugin, :all]" - boot_rails - assert_equal [:c, :a, :b], $arr - end - - test "if :all is at the beginning, it represents the plugins not otherwise specified" do - add_to_config "config.plugins = [:all, :b_plugin]" - boot_rails - assert_equal [:a, :c, :b], $arr - end - - test "plugin order array is strings" do - add_to_config "config.plugins = %w( c_plugin all )" - boot_rails - assert_equal [:c, :a, :b], $arr - end - end -end diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb new file mode 100644 index 0000000000..40ac11fa03 --- /dev/null +++ b/railties/test/railties/engine_test.rb @@ -0,0 +1,32 @@ +require "isolation/abstract_unit" +require "railties/shared_tests" + +module RailtiesTest + class EngineTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + include SharedTests + + def setup + build_app + + @plugin = engine "bukkits" do |plugin| + plugin.write "lib/bukkits.rb", <<-RUBY + class Bukkits + class Engine < ::Rails::Engine + end + end + RUBY + plugin.write "lib/another.rb", "class Another; end" + end + end + + def reload_config + :reload_engines + end + + test "Rails::Engine itself does not respond to config" do + boot_rails + assert !Rails::Engine.respond_to?(:config) + end + end +end diff --git a/railties/test/railties/plugin_ordering_test.rb b/railties/test/railties/plugin_ordering_test.rb new file mode 100644 index 0000000000..f6ca493fdf --- /dev/null +++ b/railties/test/railties/plugin_ordering_test.rb @@ -0,0 +1,72 @@ +require "isolation/abstract_unit" + +module RailtiesTest + class PluginOrderingTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + $arr = [] + plugin "a_plugin", "$arr << :a" + plugin "b_plugin", "$arr << :b" + plugin "c_plugin", "$arr << :c" + end + + def boot_rails + super + require "#{app_path}/config/environment" + end + + test "plugins are loaded alphabetically by default" do + boot_rails + assert_equal [:a, :b, :c], $arr + end + + test "if specified, only those plugins are loaded" do + add_to_config "config.plugins = [:b_plugin]" + boot_rails + assert_equal [:b], $arr + end + + test "the plugins are initialized in the order they are specified" do + add_to_config "config.plugins = [:b_plugin, :a_plugin]" + boot_rails + assert_equal [:b, :a], $arr + end + + test "if :all is specified, the remaining plugins are loaded in alphabetical order" do + add_to_config "config.plugins = [:c_plugin, :all]" + boot_rails + assert_equal [:c, :a, :b], $arr + end + + test "if :all is at the beginning, it represents the plugins not otherwise specified" do + add_to_config "config.plugins = [:all, :b_plugin]" + boot_rails + assert_equal [:a, :c, :b], $arr + end + + test "plugin order array is strings" do + add_to_config "config.plugins = %w( c_plugin all )" + boot_rails + assert_equal [:c, :a, :b], $arr + end + + test "can require lib file from a different plugin" do + plugin "foo", "require 'bar'" do |plugin| + plugin.write "lib/foo.rb", "$foo = true" + end + + plugin "bar", "require 'foo'" do |plugin| + plugin.write "lib/bar.rb", "$bar = true" + end + + add_to_config "config.plugins = [:foo, :bar]" + + boot_rails + + assert $foo + assert $bar + end + end +end
\ No newline at end of file diff --git a/railties/test/railties/plugin_test.rb b/railties/test/railties/plugin_test.rb new file mode 100644 index 0000000000..997b692e49 --- /dev/null +++ b/railties/test/railties/plugin_test.rb @@ -0,0 +1,115 @@ +require "isolation/abstract_unit" +require "railties/shared_tests" + +module RailtiesTest + class PluginTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + include SharedTests + + def setup + build_app + + @plugin = plugin "bukkits", "::LEVEL = config.log_level" do |plugin| + plugin.write "lib/bukkits.rb", "class Bukkits; end" + plugin.write "lib/another.rb", "class Another; end" + end + end + + def reload_config + :reload_plugins + end + + test "Rails::Plugin itself does not respond to config" do + boot_rails + assert !Rails::Plugin.respond_to?(:config) + end + + test "cannot inherit from Rails::Plugin" do + boot_rails + assert_raise RuntimeError do + class Foo < Rails::Plugin; end + end + end + + test "plugin can load the file with the same name in lib" do + boot_rails + require "bukkits" + assert_equal "Bukkits", Bukkits.name + end + + test "it loads the plugin's init.rb file" do + boot_rails + assert_equal "loaded", BUKKITS + end + + test "the init.rb file has access to the config object" do + boot_rails + assert_equal :debug, LEVEL + end + + test "plugin_init_is_ran_before_application_ones" do + plugin "foo", "$foo = true" do |plugin| + plugin.write "lib/foo.rb", "module Foo; end" + end + + app_file 'config/initializers/foo.rb', <<-RUBY + raise "no $foo" unless $foo + raise "no Foo" unless Foo + RUBY + + boot_rails + assert $foo + end + + test "plugin should work without init.rb" do + @plugin.delete("init.rb") + + boot_rails + + require "bukkits" + assert_nothing_raised { Bukkits } + end + + test "plugin cannot declare an engine for it" do + @plugin.write "lib/bukkits.rb", <<-RUBY + class Bukkits + class Engine < Rails::Engine + end + end + RUBY + + @plugin.write "init.rb", <<-RUBY + require "bukkits" + RUBY + + rescued = false + + begin + boot_rails + rescue Exception => e + rescued = true + assert_equal '"bukkits" is a Railtie/Engine and cannot be installed as plugin', e.message + end + + assert rescued, "Expected boot rails to fail" + end + + test "deprecated tasks are also loaded" do + $executed = false + @plugin.write "tasks/foo.rake", <<-RUBY + task :foo do + $executed = true + end + RUBY + + boot_rails + require 'rake' + require 'rake/rdoctask' + require 'rake/testtask' + Rails.application.load_tasks + Rake::Task[:foo].invoke + assert $executed + end + + end +end diff --git a/railties/test/railties/railtie_test.rb b/railties/test/railties/railtie_test.rb new file mode 100644 index 0000000000..b723e08281 --- /dev/null +++ b/railties/test/railties/railtie_test.rb @@ -0,0 +1,132 @@ +require "isolation/abstract_unit" + +module RailtiesTest + class RailtieTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + FileUtils.rm_rf("#{app_path}/config/environments") + require "rails/all" + end + + def app + @app ||= Rails.application + end + + test "Rails::Railtie itself does not respond to config" do + assert !Rails::Railtie.respond_to?(:config) + end + + test "cannot inherit from a railtie" do + class Foo < Rails::Railtie ; end + assert_raise RuntimeError do + class Bar < Foo; end + end + end + + test "config is available to railtie" do + class Foo < Rails::Railtie ; end + assert_nil Foo.config.action_controller.foo + end + + test "config name is available for the railtie" do + class Foo < Rails::Railtie ; config.foo.greetings = "hello" ; end + assert_equal "hello", Foo.config.foo.greetings + end + + test "railtie configurations are available in the application" do + class Foo < Rails::Railtie ; config.foo.greetings = "hello" ; end + require "#{app_path}/config/application" + assert_equal "hello", AppTemplate::Application.config.foo.greetings + end + + test "railtie config merges are deep" do + class Foo < Rails::Railtie ; config.foo.greetings = 'hello' ; end + class Bar < Rails::Railtie + config.foo.bar = "bar" + end + assert_equal "hello", Bar.config.foo.greetings + assert_equal "bar", Bar.config.foo.bar + end + + test "railtie can add subscribers" do + begin + class Foo < Rails::Railtie ; subscriber(Rails::Subscriber.new) ; end + assert_kind_of Rails::Subscriber, Rails::Subscriber.subscribers[:foo] + ensure + Rails::Subscriber.subscribers.clear + end + end + + test "railtie can add to_prepare callbacks" do + $to_prepare = false + class Foo < Rails::Railtie ; config.to_prepare { $to_prepare = true } ; end + assert !$to_prepare + require "#{app_path}/config/environment" + require "rack/test" + extend Rack::Test::Methods + get "/" + assert $to_prepare + end + + test "railtie can add after_initialize callbacks" do + $after_initialize = false + class Foo < Rails::Railtie ; config.after_initialize { $after_initialize = true } ; end + assert !$after_initialize + require "#{app_path}/config/environment" + assert $after_initialize + end + + test "rake_tasks block is executed when MyApp.load_tasks is called" do + $ran_block = false + + class MyTie < Rails::Railtie + rake_tasks do + $ran_block = true + end + end + + require "#{app_path}/config/environment" + + assert !$ran_block + require 'rake' + require 'rake/testtask' + require 'rake/rdoctask' + + AppTemplate::Application.load_tasks + assert $ran_block + end + + test "generators block is executed when MyApp.load_generators is called" do + $ran_block = false + + class MyTie < Rails::Railtie + generators do + $ran_block = true + end + end + + require "#{app_path}/config/environment" + + assert !$ran_block + AppTemplate::Application.load_generators + assert $ran_block + end + + test "railtie can add initializers" do + $ran_block = false + + class MyTie < Rails::Railtie + initializer :something_nice do + $ran_block = true + end + end + + assert !$ran_block + require "#{app_path}/config/environment" + assert $ran_block + end + end +end diff --git a/railties/test/railties/shared_tests.rb b/railties/test/railties/shared_tests.rb new file mode 100644 index 0000000000..d51a0d153c --- /dev/null +++ b/railties/test/railties/shared_tests.rb @@ -0,0 +1,315 @@ +module RailtiesTest + # Holds tests shared between plugin and engines + module SharedTests + def boot_rails + super + require "#{app_path}/config/environment" + end + + def app + @app ||= Rails.application + end + + def test_plugin_puts_its_lib_directory_on_load_path + boot_rails + require "another" + assert_equal "Another", Another.name + end + + def test_plugin_paths_get_added_to_as_dependency_list + boot_rails + assert_equal "Another", Another.name + end + + def test_plugins_constants_are_not_reloaded_by_default + boot_rails + assert_equal "Another", Another.name + ActiveSupport::Dependencies.clear + @plugin.delete("lib/another.rb") + assert_nothing_raised { Another } + end + + def test_plugin_constants_get_reloaded_if_config_reload_plugins + add_to_config <<-RUBY + config.#{reload_config} = true + RUBY + + boot_rails + + assert_equal "Another", Another.name + ActiveSupport::Dependencies.clear + @plugin.delete("lib/another.rb") + assert_raises(NameError) { Another } + end + + def test_plugin_puts_its_models_directory_on_load_path + @plugin.write "app/models/my_bukkit.rb", "class MyBukkit ; end" + boot_rails + assert_nothing_raised { MyBukkit } + end + + def test_plugin_puts_its_controllers_directory_on_the_load_path + @plugin.write "app/controllers/bukkit_controller.rb", "class BukkitController ; end" + boot_rails + assert_nothing_raised { BukkitController } + end + + def test_plugin_adds_its_views_to_view_paths + @plugin.write "app/controllers/bukkit_controller.rb", <<-RUBY + class BukkitController < ActionController::Base + def index + end + end + RUBY + + @plugin.write "app/views/bukkit/index.html.erb", "Hello bukkits" + + boot_rails + + require "action_controller" + require "rack/mock" + response = BukkitController.action(:index).call(Rack::MockRequest.env_for("/")) + assert_equal "Hello bukkits\n", response[2].body + end + + def test_plugin_adds_its_views_to_view_paths_with_lower_proriority + @plugin.write "app/controllers/bukkit_controller.rb", <<-RUBY + class BukkitController < ActionController::Base + def index + end + end + RUBY + + @plugin.write "app/views/bukkit/index.html.erb", "Hello bukkits" + app_file "app/views/bukkit/index.html.erb", "Hi bukkits" + + boot_rails + + require "action_controller" + require "rack/mock" + response = BukkitController.action(:index).call(Rack::MockRequest.env_for("/")) + assert_equal "Hi bukkits\n", response[2].body + end + + def test_plugin_adds_helpers_to_controller_views + @plugin.write "app/controllers/bukkit_controller.rb", <<-RUBY + class BukkitController < ActionController::Base + def index + end + end + RUBY + + @plugin.write "app/helpers/bukkit_helper.rb", <<-RUBY + module BukkitHelper + def bukkits + "bukkits" + end + end + RUBY + + @plugin.write "app/views/bukkit/index.html.erb", "Hello <%= bukkits %>" + + boot_rails + + require "rack/mock" + response = BukkitController.action(:index).call(Rack::MockRequest.env_for("/")) + assert_equal "Hello bukkits\n", response[2].body + end + + def test_plugin_eager_load_any_path_under_app + @plugin.write "app/anything/foo.rb", <<-RUBY + module Foo; end + RUBY + + boot_rails + assert Foo + end + + def test_routes_are_added_to_router + @plugin.write "config/routes.rb", <<-RUBY + class Sprokkit + def self.call(env) + [200, {'Content-Type' => 'text/html'}, ["I am a Sprokkit"]] + end + end + + ActionController::Routing::Routes.draw do + match "/sprokkit", :to => Sprokkit + end + RUBY + + boot_rails + require 'rack/test' + extend Rack::Test::Methods + + get "/sprokkit" + assert_equal "I am a Sprokkit", last_response.body + end + + def test_routes_in_plugins_have_lower_priority_than_application_ones + controller "foo", <<-RUBY + class FooController < ActionController::Base + def index + render :text => "foo" + end + end + RUBY + + app_file "config/routes.rb", <<-RUBY + AppTemplate::Application.routes.draw do |map| + match 'foo', :to => 'foo#index' + end + RUBY + + @plugin.write "app/controllers/bar_controller.rb", <<-RUBY + class BarController < ActionController::Base + def index + render :text => "bar" + end + end + RUBY + + @plugin.write "config/routes.rb", <<-RUBY + ActionController::Routing::Routes.draw do |map| + match 'foo', :to => 'bar#index' + match 'bar', :to => 'bar#index' + end + RUBY + + boot_rails + require 'rack/test' + extend Rack::Test::Methods + + get '/foo' + assert_equal 'foo', last_response.body + + get '/bar' + assert_equal 'bar', last_response.body + end + + def test_rake_tasks_lib_tasks_are_loaded + $executed = false + @plugin.write "lib/tasks/foo.rake", <<-RUBY + task :foo do + $executed = true + end + RUBY + + boot_rails + require 'rake' + require 'rake/rdoctask' + require 'rake/testtask' + Rails.application.load_tasks + Rake::Task[:foo].invoke + assert $executed + end + + def test_i18n_files_have_lower_priority_than_application_ones + add_to_config <<-RUBY + config.i18n.load_path << "#{app_path}/app/locales/en.yml" + RUBY + + app_file 'app/locales/en.yml', <<-YAML +en: + bar: "1" +YAML + + app_file 'config/locales/en.yml', <<-YAML +en: + foo: "2" + bar: "2" +YAML + + @plugin.write 'config/locales/en.yml', <<-YAML +en: + foo: "3" +YAML + + boot_rails + + assert_equal %W( + #{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/locale/en.yml + #{RAILS_FRAMEWORK_ROOT}/activemodel/lib/active_model/locale/en.yml + #{RAILS_FRAMEWORK_ROOT}/activerecord/lib/active_record/locale/en.yml + #{RAILS_FRAMEWORK_ROOT}/actionpack/lib/action_view/locale/en.yml + #{@plugin.path}/config/locales/en.yml + #{app_path}/config/locales/en.yml + #{app_path}/app/locales/en.yml + ).map { |path| File.expand_path(path) }, I18n.load_path.map { |path| File.expand_path(path) } + + assert_equal "2", I18n.t(:foo) + assert_equal "1", I18n.t(:bar) + end + + def test_plugin_metals_added_to_middleware_stack + @plugin.write 'app/metal/foo_metal.rb', <<-RUBY + class FooMetal + def self.call(env) + [200, { "Content-Type" => "text/html"}, ["FooMetal"]] + end + end + RUBY + + boot_rails + require 'rack/test' + extend Rack::Test::Methods + + get "/" + assert_equal 200, last_response.status + assert_equal "FooMetal", last_response.body + end + + def test_namespaced_controllers_with_namespaced_routes + @plugin.write "config/routes.rb", <<-RUBY + ActionController::Routing::Routes.draw do + namespace :admin do + match "index", :to => "admin/foo#index" + end + end + RUBY + + @plugin.write "app/controllers/admin/foo_controller.rb", <<-RUBY + class Admin::FooController < ApplicationController + def index + render :text => "Rendered from namespace" + end + end + RUBY + + boot_rails + require 'rack/test' + extend Rack::Test::Methods + + get "/admin/index" + assert_equal 200, last_response.status + assert_equal "Rendered from namespace", last_response.body + end + + def test_plugin_initializers + $plugin_initializer = false + @plugin.write "config/initializers/foo.rb", <<-RUBY + $plugin_initializer = true + RUBY + + boot_rails + assert $plugin_initializer + end + + def test_plugin_midleware_referenced_in_configuration + @plugin.write "lib/bukkits.rb", <<-RUBY + class Bukkits + def initialize(app) + @app = app + end + + def call(env) + @app.call(env) + end + end + RUBY + + add_to_config "config.middleware.use \"Bukkits\"" + boot_rails + end + end +end
\ No newline at end of file diff --git a/railties/test/vendor/gems/dummy-gem-a-0.4.0/.specification b/railties/test/vendor/gems/dummy-gem-a-0.4.0/.specification deleted file mode 100644 index 86dba2092c..0000000000 --- a/railties/test/vendor/gems/dummy-gem-a-0.4.0/.specification +++ /dev/null @@ -1,28 +0,0 @@ ---- !ruby/object:Gem::Specification -name: dummy-gem-a -version: !ruby/object:Gem::Version - version: 0.4.0 -platform: ruby -authors: -- "Nobody" -date: 2008-10-03 00:00:00 -04:00 -files: -- lib -- lib/dummy-gem-a.rb -require_paths: -- lib -required_ruby_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -required_rubygems_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -requirements: [] -specification_version: 2 -summary: Dummy Gem A diff --git a/railties/test/vendor/gems/dummy-gem-a-0.4.0/lib/dummy-gem-a.rb b/railties/test/vendor/gems/dummy-gem-a-0.4.0/lib/dummy-gem-a.rb deleted file mode 100644 index 0453b38ab8..0000000000 --- a/railties/test/vendor/gems/dummy-gem-a-0.4.0/lib/dummy-gem-a.rb +++ /dev/null @@ -1 +0,0 @@ -DUMMY_GEM_A_VERSION="0.4.0" diff --git a/railties/test/vendor/gems/dummy-gem-b-0.4.0/.specification b/railties/test/vendor/gems/dummy-gem-b-0.4.0/.specification deleted file mode 100644 index 5ea692d7a1..0000000000 --- a/railties/test/vendor/gems/dummy-gem-b-0.4.0/.specification +++ /dev/null @@ -1,28 +0,0 @@ ---- !ruby/object:Gem::Specification -name: dummy-gem-b -version: !ruby/object:Gem::Version - version: 0.4.0 -platform: ruby -authors: -- "Nobody" -date: 2008-10-03 00:00:00 -04:00 -files: -- lib -- lib/dummy-gem-b.rb -require_paths: -- lib -required_ruby_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -required_rubygems_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -requirements: [] -specification_version: 2 -summary: Dummy Gem B diff --git a/railties/test/vendor/gems/dummy-gem-b-0.4.0/lib/dummy-gem-b.rb b/railties/test/vendor/gems/dummy-gem-b-0.4.0/lib/dummy-gem-b.rb deleted file mode 100644 index 850b5dda83..0000000000 --- a/railties/test/vendor/gems/dummy-gem-b-0.4.0/lib/dummy-gem-b.rb +++ /dev/null @@ -1 +0,0 @@ -DUMMY_GEM_B_VERSION="0.4.0" diff --git a/railties/test/vendor/gems/dummy-gem-b-0.6.0/.specification b/railties/test/vendor/gems/dummy-gem-b-0.6.0/.specification deleted file mode 100644 index ab4707124a..0000000000 --- a/railties/test/vendor/gems/dummy-gem-b-0.6.0/.specification +++ /dev/null @@ -1,28 +0,0 @@ ---- !ruby/object:Gem::Specification -name: dummy-gem-b -version: !ruby/object:Gem::Version - version: 0.6.0 -platform: ruby -authors: -- "Nobody" -date: 2008-10-03 00:00:00 -04:00 -files: -- lib -- lib/dummy-gem-b.rb -require_paths: -- lib -required_ruby_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -required_rubygems_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -requirements: [] -specification_version: 2 -summary: Dummy Gem B diff --git a/railties/test/vendor/gems/dummy-gem-b-0.6.0/lib/dummy-gem-b.rb b/railties/test/vendor/gems/dummy-gem-b-0.6.0/lib/dummy-gem-b.rb deleted file mode 100644 index 7d6d01cd48..0000000000 --- a/railties/test/vendor/gems/dummy-gem-b-0.6.0/lib/dummy-gem-b.rb +++ /dev/null @@ -1 +0,0 @@ -DUMMY_GEM_B_VERSION="0.6.0" diff --git a/railties/test/vendor/gems/dummy-gem-c-0.4.0/.specification b/railties/test/vendor/gems/dummy-gem-c-0.4.0/.specification deleted file mode 100644 index f90f60424c..0000000000 --- a/railties/test/vendor/gems/dummy-gem-c-0.4.0/.specification +++ /dev/null @@ -1,28 +0,0 @@ ---- !ruby/object:Gem::Specification -name: dummy-gem-c -version: !ruby/object:Gem::Version - version: 0.4.0 -platform: ruby -authors: -- "Nobody" -date: 2008-10-03 00:00:00 -04:00 -files: -- lib -- lib/dummy-gem-c.rb -require_paths: -- lib -required_ruby_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -required_rubygems_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -requirements: [] -specification_version: 2 -summary: Dummy Gem C diff --git a/railties/test/vendor/gems/dummy-gem-c-0.4.0/lib/dummy-gem-c.rb b/railties/test/vendor/gems/dummy-gem-c-0.4.0/lib/dummy-gem-c.rb deleted file mode 100644 index 1a416bef82..0000000000 --- a/railties/test/vendor/gems/dummy-gem-c-0.4.0/lib/dummy-gem-c.rb +++ /dev/null @@ -1 +0,0 @@ -DUMMY_GEM_C_VERSION="0.4.0" diff --git a/railties/test/vendor/gems/dummy-gem-c-0.6.0/.specification b/railties/test/vendor/gems/dummy-gem-c-0.6.0/.specification deleted file mode 100644 index e75c0aa66a..0000000000 --- a/railties/test/vendor/gems/dummy-gem-c-0.6.0/.specification +++ /dev/null @@ -1,28 +0,0 @@ ---- !ruby/object:Gem::Specification -name: dummy-gem-c -version: !ruby/object:Gem::Version - version: 0.6.0 -platform: ruby -authors: -- "Nobody" -date: 2008-10-03 00:00:00 -04:00 -files: -- lib -- lib/dummy-gem-c.rb -require_paths: -- lib -required_ruby_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -required_rubygems_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -requirements: [] -specification_version: 2 -summary: Dummy Gem C diff --git a/railties/test/vendor/gems/dummy-gem-c-0.6.0/lib/dummy-gem-c.rb b/railties/test/vendor/gems/dummy-gem-c-0.6.0/lib/dummy-gem-c.rb deleted file mode 100644 index 9ba2ca8bb5..0000000000 --- a/railties/test/vendor/gems/dummy-gem-c-0.6.0/lib/dummy-gem-c.rb +++ /dev/null @@ -1 +0,0 @@ -DUMMY_GEM_C_VERSION="0.6.0" diff --git a/railties/test/vendor/gems/dummy-gem-d-1.0.0/lib/dummy-gem-d.rb b/railties/test/vendor/gems/dummy-gem-d-1.0.0/lib/dummy-gem-d.rb deleted file mode 100644 index e5cb007e5f..0000000000 --- a/railties/test/vendor/gems/dummy-gem-d-1.0.0/lib/dummy-gem-d.rb +++ /dev/null @@ -1 +0,0 @@ -DUMMY_GEM_D_VERSION="1.0.0" diff --git a/railties/test/vendor/gems/dummy-gem-e-1.0.0/.specification b/railties/test/vendor/gems/dummy-gem-e-1.0.0/.specification deleted file mode 100644 index ce4443c8be..0000000000 --- a/railties/test/vendor/gems/dummy-gem-e-1.0.0/.specification +++ /dev/null @@ -1,28 +0,0 @@ ---- !ruby/object:Gem::Specification -name: dummy-gem-e -version: !ruby/object:Gem::Version - version: 1.3.0 -platform: ruby -authors: -- "Nobody" -date: 2008-10-03 00:00:00 -04:00 -files: -- lib -- lib/dummy-gem-e.rb -require_paths: -- lib -required_ruby_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -required_rubygems_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -requirements: [] -specification_version: 2 -summary: Dummy Gem E diff --git a/railties/test/vendor/gems/dummy-gem-e-1.0.0/lib/dummy-gem-e.rb b/railties/test/vendor/gems/dummy-gem-e-1.0.0/lib/dummy-gem-e.rb deleted file mode 100644 index 48bf91a701..0000000000 --- a/railties/test/vendor/gems/dummy-gem-e-1.0.0/lib/dummy-gem-e.rb +++ /dev/null @@ -1 +0,0 @@ -DUMMY_GEM_E_VERSION="1.0.0" diff --git a/railties/test/vendor/gems/dummy-gem-f-1.0.0/.specification b/railties/test/vendor/gems/dummy-gem-f-1.0.0/.specification deleted file mode 100644 index 70a36b9a8c..0000000000 --- a/railties/test/vendor/gems/dummy-gem-f-1.0.0/.specification +++ /dev/null @@ -1,39 +0,0 @@ ---- !ruby/object:Gem::Specification -name: dummy-gem-f -version: !ruby/object:Gem::Version - version: 1.3.0 -platform: ruby -authors: -- "Nobody" -date: 2008-10-03 00:00:00 -04:00 -dependencies: -- !ruby/object:Gem::Dependency - name: absolutely-no-such-gem - type: :runtime - version_requirement: - version_requirements: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: 1.0.0 - version: -files: -- lib -- lib/dummy-gem-f.rb -require_paths: -- lib -required_ruby_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -required_rubygems_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -requirements: [] -specification_version: 2 -summary: Dummy Gem F diff --git a/railties/test/vendor/gems/dummy-gem-f-1.0.0/lib/dummy-gem-f.rb b/railties/test/vendor/gems/dummy-gem-f-1.0.0/lib/dummy-gem-f.rb deleted file mode 100644 index 0271c8c48a..0000000000 --- a/railties/test/vendor/gems/dummy-gem-f-1.0.0/lib/dummy-gem-f.rb +++ /dev/null @@ -1 +0,0 @@ -DUMMY_GEM_F_VERSION="1.0.0" diff --git a/railties/test/vendor/gems/dummy-gem-g-1.0.0/.specification b/railties/test/vendor/gems/dummy-gem-g-1.0.0/.specification deleted file mode 100644 index 27e29912a6..0000000000 --- a/railties/test/vendor/gems/dummy-gem-g-1.0.0/.specification +++ /dev/null @@ -1,39 +0,0 @@ ---- !ruby/object:Gem::Specification -name: dummy-gem-g -version: !ruby/object:Gem::Version - version: 1.3.0 -platform: ruby -authors: -- "Nobody" -date: 2008-10-03 00:00:00 -04:00 -dependencies: -- !ruby/object:Gem::Dependency - name: dummy-gem-f - type: :runtime - version_requirement: - version_requirements: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: 1.0.0 - version: -files: -- lib -- lib/dummy-gem-g.rb -require_paths: -- lib -required_ruby_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -required_rubygems_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -requirements: [] -specification_version: 2 -summary: Dummy Gem G diff --git a/railties/test/vendor/gems/dummy-gem-g-1.0.0/lib/dummy-gem-g.rb b/railties/test/vendor/gems/dummy-gem-g-1.0.0/lib/dummy-gem-g.rb deleted file mode 100644 index 8fc056586c..0000000000 --- a/railties/test/vendor/gems/dummy-gem-g-1.0.0/lib/dummy-gem-g.rb +++ /dev/null @@ -1 +0,0 @@ -DUMMY_GEM_G_VERSION="1.0.0" diff --git a/railties/test/vendor/gems/dummy-gem-h-1.0.0/.specification b/railties/test/vendor/gems/dummy-gem-h-1.0.0/.specification deleted file mode 100644 index b3f7930948..0000000000 --- a/railties/test/vendor/gems/dummy-gem-h-1.0.0/.specification +++ /dev/null @@ -1,29 +0,0 @@ ---- !ruby/object:Gem::Specification -name: dummy-gem-h -version: !ruby/object:Gem::Version - version: 1.3.0 -platform: ruby -authors: -- "Nobody" -date: 2008-10-03 00:00:00 -04:00 -dependencies: -files: -- lib -- lib/dummy-gem-h.rb -require_paths: -- lib -required_ruby_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -required_rubygems_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -requirements: [] -specification_version: 2 -summary: Dummy Gem H diff --git a/railties/test/vendor/gems/dummy-gem-h-1.0.0/lib/dummy-gem-h.rb b/railties/test/vendor/gems/dummy-gem-h-1.0.0/lib/dummy-gem-h.rb deleted file mode 100644 index 0f91234936..0000000000 --- a/railties/test/vendor/gems/dummy-gem-h-1.0.0/lib/dummy-gem-h.rb +++ /dev/null @@ -1 +0,0 @@ -DUMMY_GEM_H_VERSION="1.0.0" diff --git a/railties/test/vendor/gems/dummy-gem-i-1.0.0/.specification b/railties/test/vendor/gems/dummy-gem-i-1.0.0/.specification deleted file mode 100644 index 50b4969da5..0000000000 --- a/railties/test/vendor/gems/dummy-gem-i-1.0.0/.specification +++ /dev/null @@ -1,41 +0,0 @@ ---- !ruby/object:Gem::Specification -name: dummy-gem-i -version: !ruby/object:Gem::Version - version: 1.3.0 -platform: ruby -authors: -- "Nobody" -date: 2008-10-03 00:00:00 -04:00 -dependencies: -- !ruby/object:Gem::Dependency - name: dummy-gem-i - type: :runtime - version_requirement: - version_requirements: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: 1.0.0 - version: -extensions: -- ext/dummy-gem-i/extconf.rb -files: -- lib -- lib/dummy-gem-i.rb -require_paths: -- lib -required_ruby_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -required_rubygems_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -requirements: [] -specification_version: 2 -summary: Dummy Gem G diff --git a/railties/test/vendor/gems/dummy-gem-i-1.0.0/ext/dummy-gem-i/Makefile b/railties/test/vendor/gems/dummy-gem-i-1.0.0/ext/dummy-gem-i/Makefile deleted file mode 100644 index e69de29bb2..0000000000 --- a/railties/test/vendor/gems/dummy-gem-i-1.0.0/ext/dummy-gem-i/Makefile +++ /dev/null diff --git a/railties/test/vendor/gems/dummy-gem-i-1.0.0/lib/dummy-gem-i.rb b/railties/test/vendor/gems/dummy-gem-i-1.0.0/lib/dummy-gem-i.rb deleted file mode 100644 index 2f9a376c2c..0000000000 --- a/railties/test/vendor/gems/dummy-gem-i-1.0.0/lib/dummy-gem-i.rb +++ /dev/null @@ -1 +0,0 @@ -DUMMY_GEM_I_VERSION="1.0.0" diff --git a/railties/test/vendor/gems/dummy-gem-j-1.0.0/.specification b/railties/test/vendor/gems/dummy-gem-j-1.0.0/.specification deleted file mode 100644 index 2c456546fc..0000000000 --- a/railties/test/vendor/gems/dummy-gem-j-1.0.0/.specification +++ /dev/null @@ -1,41 +0,0 @@ ---- !ruby/object:Gem::Specification -name: dummy-gem-j -version: !ruby/object:Gem::Version - version: 1.3.0 -platform: ruby -authors: -- "Nobody" -date: 2008-10-03 00:00:00 -04:00 -dependencies: -- !ruby/object:Gem::Dependency - name: dummy-gem-j - type: :runtime - version_requirement: - version_requirements: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: 1.0.0 - version: -extensions: -- ext/dummy-gem-j/extconf.rb -files: -- lib -- lib/dummy-gem-j.rb -require_paths: -- lib -required_ruby_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -required_rubygems_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -requirements: [] -specification_version: 2 -summary: Dummy Gem G diff --git a/railties/test/vendor/gems/dummy-gem-j-1.0.0/lib/dummy-gem-j.rb b/railties/test/vendor/gems/dummy-gem-j-1.0.0/lib/dummy-gem-j.rb deleted file mode 100644 index 8ecd363ff8..0000000000 --- a/railties/test/vendor/gems/dummy-gem-j-1.0.0/lib/dummy-gem-j.rb +++ /dev/null @@ -1 +0,0 @@ -DUMMY_GEM_J_VERSION="1.0.0" diff --git a/railties/test/vendor/gems/dummy-gem-k-1.0.0/.specification b/railties/test/vendor/gems/dummy-gem-k-1.0.0/.specification deleted file mode 100644 index 20edd0f856..0000000000 --- a/railties/test/vendor/gems/dummy-gem-k-1.0.0/.specification +++ /dev/null @@ -1,49 +0,0 @@ ---- !ruby/object:Gem::Specification -name: dummy-gem-k -version: !ruby/object:Gem::Version - version: 1.3.0 -platform: ruby -authors: -- "Nobody" -date: 2008-10-03 00:00:00 -04:00 -dependencies: -- !ruby/object:Gem::Dependency - name: dummy-gem-k - type: :runtime - version_requirement: - version_requirements: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: 1.0.0 - version: -- !ruby/object:Gem::Dependency - name: dummy-gem-h - type: :development - version_requirement: - version_requirements: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: 1.0.0 - version: -files: -- lib -- lib/dummy-gem-k.rb -require_paths: -- lib -required_ruby_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -required_rubygems_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -requirements: [] -specification_version: 2 -summary: Dummy Gem I diff --git a/railties/test/vendor/gems/dummy-gem-k-1.0.0/lib/dummy-gem-k.rb b/railties/test/vendor/gems/dummy-gem-k-1.0.0/lib/dummy-gem-k.rb deleted file mode 100644 index 97fb1d69ce..0000000000 --- a/railties/test/vendor/gems/dummy-gem-k-1.0.0/lib/dummy-gem-k.rb +++ /dev/null @@ -1 +0,0 @@ -DUMMY_GEM_K_VERSION="1.0.0" |