aboutsummaryrefslogtreecommitdiffstats
path: root/railties
diff options
context:
space:
mode:
authorPratik Naik <pratiknaik@gmail.com>2010-01-28 19:46:17 +0000
committerPratik Naik <pratiknaik@gmail.com>2010-01-28 19:46:17 +0000
commit285361d1589002fcdd1584c07e6eb295f13c9f37 (patch)
tree2d50a69b3b59b6fb3cb7577b990fe3b1aaf58f4f /railties
parentdfa19408651ecc82e2aeba95d93db871ba8a6e41 (diff)
parentd58398c2b5e98aad18dc72790230f338c10d145c (diff)
downloadrails-285361d1589002fcdd1584c07e6eb295f13c9f37.tar.gz
rails-285361d1589002fcdd1584c07e6eb295f13c9f37.tar.bz2
rails-285361d1589002fcdd1584c07e6eb295f13c9f37.zip
Merge remote branch 'mainstream/master'
Conflicts: railties/lib/rails/railtie.rb
Diffstat (limited to 'railties')
-rw-r--r--railties/lib/generators/erb/mailer/mailer_generator.rb2
-rw-r--r--railties/lib/generators/erb/mailer/templates/view.erb3
-rw-r--r--railties/lib/generators/erb/mailer/templates/view.text.erb3
-rwxr-xr-xrailties/lib/generators/rails/app/templates/Rakefile2
-rw-r--r--railties/lib/generators/rails/app/templates/config/boot.rb6
-rw-r--r--railties/lib/generators/rails/app/templates/public/javascripts/jquery-1.4.1.min.js152
-rw-r--r--railties/lib/generators/rails/app/templates/public/javascripts/jquery.rails.js239
-rw-r--r--railties/lib/generators/rails/app/templates/public/javascripts/prototype.rails.js324
-rwxr-xr-xrailties/lib/generators/rails/app/templates/script/console.tt2
-rwxr-xr-xrailties/lib/generators/rails/app/templates/script/dbconsole.tt2
-rw-r--r--railties/lib/generators/rails/mailer/templates/mailer.rb18
-rw-r--r--railties/lib/generators/rails/metal/templates/metal.rb2
-rw-r--r--railties/lib/generators/rails/plugin/plugin_generator.rb2
-rw-r--r--railties/lib/generators/rails/plugin/templates/lib/tasks/%file_name%_tasks.rake.tt (renamed from railties/lib/generators/rails/plugin/templates/tasks/%file_name%_tasks.rake.tt)0
-rw-r--r--railties/lib/generators/rails/resource/resource_generator.rb4
-rw-r--r--railties/lib/generators/rails/scaffold_controller/scaffold_controller_generator.rb6
-rw-r--r--railties/lib/generators/test_unit/mailer/templates/fixture2
-rw-r--r--railties/lib/generators/test_unit/mailer/templates/functional_test.rb8
-rw-r--r--railties/lib/rails.rb10
-rw-r--r--railties/lib/rails/all.rb2
-rw-r--r--railties/lib/rails/application.rb182
-rw-r--r--railties/lib/rails/application/bootstrap.rb85
-rw-r--r--railties/lib/rails/application/configurable.rb19
-rw-r--r--railties/lib/rails/application/configuration.rb84
-rw-r--r--railties/lib/rails/application/finisher.rb49
-rw-r--r--railties/lib/rails/application/metal_loader.rb50
-rw-r--r--railties/lib/rails/application/railties.rb31
-rw-r--r--railties/lib/rails/application/routes_reloader.rb46
-rw-r--r--railties/lib/rails/bootstrap.rb161
-rw-r--r--railties/lib/rails/commands/console.rb8
-rw-r--r--railties/lib/rails/configuration.rb399
-rw-r--r--railties/lib/rails/console/app.rb (renamed from railties/lib/rails/console_app.rb)11
-rw-r--r--railties/lib/rails/console/helpers.rb (renamed from railties/lib/rails/console_with_helpers.rb)0
-rw-r--r--railties/lib/rails/console/sandbox.rb (renamed from railties/lib/rails/console_sandbox.rb)0
-rw-r--r--railties/lib/rails/engine.rb130
-rw-r--r--railties/lib/rails/engine/configurable.rb25
-rw-r--r--railties/lib/rails/engine/configuration.rb49
-rw-r--r--railties/lib/rails/generators.rb21
-rw-r--r--railties/lib/rails/generators/named_base.rb79
-rw-r--r--railties/lib/rails/generators/resource_helpers.rb43
-rw-r--r--railties/lib/rails/initializable.rb26
-rw-r--r--railties/lib/rails/paths.rb44
-rw-r--r--railties/lib/rails/plugin.rb65
-rw-r--r--railties/lib/rails/rack.rb1
-rw-r--r--railties/lib/rails/rack/logger.rb18
-rw-r--r--railties/lib/rails/rack/metal.rb26
-rw-r--r--railties/lib/rails/railtie.rb83
-rw-r--r--railties/lib/rails/railtie/configurable.rb23
-rw-r--r--railties/lib/rails/railtie/configuration.rb9
-rw-r--r--railties/lib/rails/tasks.rb1
-rw-r--r--railties/lib/rails/tasks/documentation.rake54
-rw-r--r--railties/lib/rails/tasks/middleware.rake2
-rw-r--r--railties/lib/rails/tasks/routes.rake1
-rw-r--r--railties/lib/rails/test_unit/railtie.rb17
-rw-r--r--railties/test/application/configuration_test.rb64
-rw-r--r--railties/test/application/console_test.rb4
-rw-r--r--railties/test/application/generators_test.rb25
-rw-r--r--railties/test/application/initializer_test.rb185
-rw-r--r--railties/test/application/initializers/boot_test.rb (renamed from railties/test/initializer/boot_test.rb)2
-rw-r--r--railties/test/application/initializers/check_ruby_version_test.rb (renamed from railties/test/initializer/check_ruby_version_test.rb)2
-rw-r--r--railties/test/application/initializers/frameworks_test.rb86
-rw-r--r--railties/test/application/initializers/i18n_test.rb55
-rw-r--r--railties/test/application/initializers/initializers_test.rb55
-rw-r--r--railties/test/application/initializers/load_path_test.rb74
-rw-r--r--railties/test/application/initializers/notifications_test.rb (renamed from railties/test/application/notifications_test.rb)27
-rw-r--r--railties/test/application/middleware_test.rb7
-rw-r--r--railties/test/application/paths_test.rb (renamed from railties/test/initializer/path_test.rb)28
-rw-r--r--railties/test/application/rackup_test.rb (renamed from railties/test/application/load_test.rb)2
-rw-r--r--railties/test/application/routing_test.rb78
-rw-r--r--railties/test/fixtures/eager/zoo.rb3
-rw-r--r--railties/test/fixtures/eager/zoo/reptile_house.rb2
-rw-r--r--railties/test/fixtures/environment_with_constant.rb1
-rw-r--r--railties/test/fixtures/plugins/alternate/a/generators/a_generator/a_generator.rb4
-rw-r--r--railties/test/fixtures/plugins/alternate/a/lib/.gitignore0
-rw-r--r--railties/test/fixtures/plugins/default/acts/acts_as_chunky_bacon/lib/.gitignore0
-rw-r--r--railties/test/fixtures/plugins/default/empty/.gitignore0
-rw-r--r--railties/test/fixtures/plugins/default/gemlike/init.rb1
-rw-r--r--railties/test/fixtures/plugins/default/gemlike/lib/gemlike.rb2
-rw-r--r--railties/test/fixtures/plugins/default/gemlike/rails/init.rb7
-rw-r--r--railties/test/fixtures/plugins/default/plugin_with_no_lib_dir/init.rb0
-rw-r--r--railties/test/fixtures/plugins/default/stubby/about.yml2
-rw-r--r--railties/test/fixtures/plugins/default/stubby/init.rb7
-rw-r--r--railties/test/fixtures/plugins/default/stubby/lib/stubby_mixin.rb2
-rw-r--r--railties/test/fixtures/plugins/engines/engine/app/controllers/engine_controller.rb2
-rw-r--r--railties/test/fixtures/plugins/engines/engine/app/metal/engine_metal.rb10
-rw-r--r--railties/test/fixtures/plugins/engines/engine/app/models/engine_model.rb2
-rw-r--r--railties/test/fixtures/plugins/engines/engine/config/locales/en.yml2
-rw-r--r--railties/test/fixtures/plugins/engines/engine/config/routes.rb3
-rw-r--r--railties/test/fixtures/plugins/engines/engine/init.rb3
-rw-r--r--railties/test/generators/generators_test_helper.rb2
-rw-r--r--railties/test/generators/mailer_generator_test.rb39
-rw-r--r--railties/test/generators/named_base_test.rb70
-rw-r--r--railties/test/generators/plugin_generator_test.rb2
-rw-r--r--railties/test/generators_test.rb1
-rw-r--r--railties/test/initializable_test.rb28
-rw-r--r--railties/test/initializer/initialize_i18n_test.rb55
-rw-r--r--railties/test/isolation/abstract_unit.rb21
-rw-r--r--railties/test/mocks/routes.rb6
-rw-r--r--railties/test/paths_test.rb27
-rw-r--r--railties/test/plugins/configuration_test.rb45
-rw-r--r--railties/test/plugins/framework_extension_test.rb68
-rw-r--r--railties/test/plugins/vendored_test.rb201
-rw-r--r--railties/test/railties/engine_test.rb32
-rw-r--r--railties/test/railties/plugin_ordering_test.rb72
-rw-r--r--railties/test/railties/plugin_test.rb115
-rw-r--r--railties/test/railties/railtie_test.rb132
-rw-r--r--railties/test/railties/shared_tests.rb315
-rw-r--r--railties/test/vendor/gems/dummy-gem-a-0.4.0/.specification28
-rw-r--r--railties/test/vendor/gems/dummy-gem-a-0.4.0/lib/dummy-gem-a.rb1
-rw-r--r--railties/test/vendor/gems/dummy-gem-b-0.4.0/.specification28
-rw-r--r--railties/test/vendor/gems/dummy-gem-b-0.4.0/lib/dummy-gem-b.rb1
-rw-r--r--railties/test/vendor/gems/dummy-gem-b-0.6.0/.specification28
-rw-r--r--railties/test/vendor/gems/dummy-gem-b-0.6.0/lib/dummy-gem-b.rb1
-rw-r--r--railties/test/vendor/gems/dummy-gem-c-0.4.0/.specification28
-rw-r--r--railties/test/vendor/gems/dummy-gem-c-0.4.0/lib/dummy-gem-c.rb1
-rw-r--r--railties/test/vendor/gems/dummy-gem-c-0.6.0/.specification28
-rw-r--r--railties/test/vendor/gems/dummy-gem-c-0.6.0/lib/dummy-gem-c.rb1
-rw-r--r--railties/test/vendor/gems/dummy-gem-d-1.0.0/lib/dummy-gem-d.rb1
-rw-r--r--railties/test/vendor/gems/dummy-gem-e-1.0.0/.specification28
-rw-r--r--railties/test/vendor/gems/dummy-gem-e-1.0.0/lib/dummy-gem-e.rb1
-rw-r--r--railties/test/vendor/gems/dummy-gem-f-1.0.0/.specification39
-rw-r--r--railties/test/vendor/gems/dummy-gem-f-1.0.0/lib/dummy-gem-f.rb1
-rw-r--r--railties/test/vendor/gems/dummy-gem-g-1.0.0/.specification39
-rw-r--r--railties/test/vendor/gems/dummy-gem-g-1.0.0/lib/dummy-gem-g.rb1
-rw-r--r--railties/test/vendor/gems/dummy-gem-h-1.0.0/.specification29
-rw-r--r--railties/test/vendor/gems/dummy-gem-h-1.0.0/lib/dummy-gem-h.rb1
-rw-r--r--railties/test/vendor/gems/dummy-gem-i-1.0.0/.specification41
-rw-r--r--railties/test/vendor/gems/dummy-gem-i-1.0.0/ext/dummy-gem-i/Makefile0
-rw-r--r--railties/test/vendor/gems/dummy-gem-i-1.0.0/lib/dummy-gem-i.rb1
-rw-r--r--railties/test/vendor/gems/dummy-gem-j-1.0.0/.specification41
-rw-r--r--railties/test/vendor/gems/dummy-gem-j-1.0.0/lib/dummy-gem-j.rb1
-rw-r--r--railties/test/vendor/gems/dummy-gem-k-1.0.0/.specification49
-rw-r--r--railties/test/vendor/gems/dummy-gem-k-1.0.0/lib/dummy-gem-k.rb1
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"