aboutsummaryrefslogtreecommitdiffstats
path: root/railties
diff options
context:
space:
mode:
Diffstat (limited to 'railties')
-rw-r--r--railties/CHANGELOG4
-rw-r--r--railties/guides/source/action_view_overview.textile3
-rw-r--r--railties/guides/source/association_basics.textile2
-rw-r--r--railties/guides/source/command_line.textile2
-rw-r--r--railties/guides/source/debugging_rails_applications.textile4
-rw-r--r--railties/guides/source/generators.textile2
-rw-r--r--railties/guides/source/getting_started.textile4
-rw-r--r--railties/guides/source/index.html.erb4
-rw-r--r--railties/guides/source/initialization.textile2
-rw-r--r--railties/guides/source/layout.html.erb1
-rw-r--r--railties/guides/source/layouts_and_rendering.textile16
-rw-r--r--railties/guides/source/routing.textile2
-rw-r--r--railties/guides/source/ruby_on_rails_guides_guidelines.textile77
-rw-r--r--railties/lib/rails.rb2
-rw-r--r--railties/lib/rails/application.rb28
-rw-r--r--railties/lib/rails/application/bootstrap.rb2
-rw-r--r--railties/lib/rails/application/configuration.rb19
-rw-r--r--railties/lib/rails/application/finisher.rb2
-rw-r--r--railties/lib/rails/application/routes_reloader.rb45
-rw-r--r--railties/lib/rails/commands.rb19
-rw-r--r--railties/lib/rails/commands/plugin.rb2
-rw-r--r--railties/lib/rails/engine.rb217
-rw-r--r--railties/lib/rails/engine/configuration.rb71
-rw-r--r--railties/lib/rails/engine/railties.rb2
-rw-r--r--railties/lib/rails/generators/actions.rb4
-rw-r--r--railties/lib/rails/generators/rails/app/app_generator.rb25
-rw-r--r--railties/lib/rails/generators/rails/app/templates/Gemfile3
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml2
-rw-r--r--railties/lib/rails/paths.rb154
-rw-r--r--railties/lib/rails/plugin.rb6
-rw-r--r--railties/lib/rails/railtie.rb9
-rw-r--r--railties/lib/rails/railtie/configuration.rb33
-rw-r--r--railties/lib/rails/tasks/documentation.rake2
-rw-r--r--railties/lib/rails/tasks/railties.rake4
-rw-r--r--railties/lib/rails/test_unit/railtie.rb2
-rw-r--r--railties/lib/rails/test_unit/testing.rake7
-rw-r--r--railties/railties.gemspec2
-rw-r--r--railties/test/application/configuration_test.rb4
-rw-r--r--railties/test/application/console_test.rb5
-rw-r--r--railties/test/application/generators_test.rb2
-rw-r--r--railties/test/application/middleware/best_practices_test.rb26
-rw-r--r--railties/test/application/middleware/cache_test.rb12
-rw-r--r--railties/test/application/middleware/remote_ip_test.rb63
-rw-r--r--railties/test/application/middleware/sendfile_test.rb56
-rw-r--r--railties/test/application/middleware_test.rb137
-rw-r--r--railties/test/application/paths_test.rb28
-rw-r--r--railties/test/application/routing_test.rb61
-rw-r--r--railties/test/generators/app_generator_test.rb6
-rw-r--r--railties/test/generators/generated_attribute_test.rb2
-rw-r--r--railties/test/generators/mailer_generator_test.rb9
-rw-r--r--railties/test/generators/namespaced_generators_test.rb4
-rw-r--r--railties/test/isolation/abstract_unit.rb27
-rw-r--r--railties/test/paths_test.rb268
-rw-r--r--railties/test/railties/engine_test.rb147
-rw-r--r--railties/test/railties/mounted_engine_test.rb2
-rw-r--r--railties/test/railties/plugin_test.rb2
-rw-r--r--railties/test/railties/railtie_test.rb24
-rw-r--r--railties/test/railties/shared_tests.rb27
59 files changed, 1102 insertions, 597 deletions
diff --git a/railties/CHANGELOG b/railties/CHANGELOG
index d2a4add375..b38a9ce750 100644
--- a/railties/CHANGELOG
+++ b/railties/CHANGELOG
@@ -1,6 +1,8 @@
*Rails 3.1.0 (unreleased)*
-* Added Rack::Cache to the default middleware stack
+* Added Rack::Etag and Rack::ConditionalGet to the default middleware stack [José Valim]
+
+* Added Rack::Cache to the default middleware stack [Yehuda Katz and Carl Lerche]
* Engine is now rack application [Piotr Sarnacki]
diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile
index 843dfe530d..0e1a352ebd 100644
--- a/railties/guides/source/action_view_overview.textile
+++ b/railties/guides/source/action_view_overview.textile
@@ -253,9 +253,6 @@ javascript_include_tag :monkey # =>
<script type="text/javascript" src="/javascripts/tail.js"></script>
</ruby>
-h5. register_javascript_include_default
-
-Register one or more additional JavaScript files to be included when +javascript_include_tag :defaults+ is called. This method is typically intended to be called from plugin initialization to register additional +.js+ files that the plugin installed in +public/javascripts+.
h5. register_stylesheet_expansion
diff --git a/railties/guides/source/association_basics.textile b/railties/guides/source/association_basics.textile
index 6996dab8c5..f6d61373e1 100644
--- a/railties/guides/source/association_basics.textile
+++ b/railties/guides/source/association_basics.textile
@@ -550,7 +550,7 @@ build_customer
create_customer
</ruby>
-h6(#belongs_to-association). <tt>_association_(force_reload = false)</tt>
+h6(#belongs_to-association). <tt><em>association</em>(force_reload = false)</tt>
The <tt><em>association</em></tt> method returns the associated object, if any. If no associated object is found, it returns +nil+.
diff --git a/railties/guides/source/command_line.textile b/railties/guides/source/command_line.textile
index cbdfda9215..752b5926f7 100644
--- a/railties/guides/source/command_line.textile
+++ b/railties/guides/source/command_line.textile
@@ -145,7 +145,7 @@ $ rails generate controller Greetings hello
What all did this generate? It made sure a bunch of directories were in our application, and created a controller file, a functional test file, a helper for the view, and a view file.
-Check out the controller and modify it a little (in +app/controllers/greetings_controller.rb+):ma
+Check out the controller and modify it a little (in +app/controllers/greetings_controller.rb+):
<ruby>
class GreetingsController < ApplicationController
diff --git a/railties/guides/source/debugging_rails_applications.textile b/railties/guides/source/debugging_rails_applications.textile
index 35069f33ad..b9d45fb13a 100644
--- a/railties/guides/source/debugging_rails_applications.textile
+++ b/railties/guides/source/debugging_rails_applications.textile
@@ -250,7 +250,7 @@ Make sure you have started your web server with the option +--debugger+:
<shell>
~/PathTo/rails_project$ rails server --debugger
-=> Booting Mongrel (use 'rails server webrick' to force WEBrick)
+=> Booting WEBrick
=> Rails 3.0.0 application starting on http://0.0.0.0:3000
=> Debugger enabled
...
@@ -258,8 +258,6 @@ Make sure you have started your web server with the option +--debugger+:
TIP: In development mode, you can dynamically +require \'ruby-debug\'+ instead of restarting the server, if it was started without +--debugger+.
-In order to use Rails debugging you'll need to be running either *WEBrick* or *Mongrel*. For the moment, no alternative servers are supported.
-
h4. The Shell
As soon as your application calls the +debugger+ method, the debugger will be started in a debugger shell inside the terminal window where you launched your application server, and you will be placed at ruby-debug's prompt +(rdb:n)+. The _n_ is the thread number. The prompt will also show you the next line of code that is waiting to run.
diff --git a/railties/guides/source/generators.textile b/railties/guides/source/generators.textile
index b1f8ea29da..0f2cbb76dc 100644
--- a/railties/guides/source/generators.textile
+++ b/railties/guides/source/generators.textile
@@ -144,7 +144,7 @@ generators/initializer_generator.rb
If none is found you get an error message.
-INFO: The examples above put files under the application's +lib+ because said directoty belongs to +$LOAD_PATH+.
+INFO: The examples above put files under the application's +lib+ because said directory belongs to +$LOAD_PATH+.
h3. Customizing Your Workflow
diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile
index b2810188c2..3f433c9704 100644
--- a/railties/guides/source/getting_started.textile
+++ b/railties/guides/source/getting_started.textile
@@ -282,7 +282,7 @@ You actually have a functional Rails application already. To see it, you need to
$ rails server
</shell>
-This will fire up an instance of the Mongrel web server by default (Rails can also use several other web servers). To see your application in action, open a browser window and navigate to "http://localhost:3000":http://localhost:3000. You should see Rails' default information page:
+This will fire up an instance of the WEBrick web server by default (Rails can also use several other web servers). To see your application in action, open a browser window and navigate to "http://localhost:3000":http://localhost:3000. You should see Rails' default information page:
!images/rails_welcome.png(Welcome Aboard screenshot)!
@@ -559,7 +559,7 @@ The view is only part of the story of how HTML is displayed in your web browser.
<title>Blog</title>
<%= stylesheet_link_tag :all %>
<%= javascript_include_tag :defaults %>
- <%= csrf_meta_tag %>
+ <%= csrf_meta_tags %>
</head>
<body style="background: #EEEEEE;">
diff --git a/railties/guides/source/index.html.erb b/railties/guides/source/index.html.erb
index e6d327168a..6b897e3a6a 100644
--- a/railties/guides/source/index.html.erb
+++ b/railties/guides/source/index.html.erb
@@ -161,6 +161,10 @@ Ruby on Rails Guides
<%= guide('API Documentation Guidelines', 'api_documentation_guidelines.html') do %>
<p>This guide documents the Ruby on Rails API documentation guidelines.</p>
<% end %>
+
+ <%= guide('Ruby on Rails Guides Guidelines', 'ruby_on_rails_guides_guidelines.html') do %>
+ <p>This guide documents the Ruby on Rails guides guidelines.</p>
+ <% end %>
</dl>
<h3>Release Notes</h3>
diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile
index 599ddccdd6..3e02bc0158 100644
--- a/railties/guides/source/initialization.textile
+++ b/railties/guides/source/initialization.textile
@@ -3070,7 +3070,7 @@ The +Rails::Plugin::Configuration+ class may be a bit difficult to find at first
<ruby>
module Rails
- class Plugin < Railtie
+ class Plugin < Engine
...
end
end
diff --git a/railties/guides/source/layout.html.erb b/railties/guides/source/layout.html.erb
index 2039c76213..f0aa227c7e 100644
--- a/railties/guides/source/layout.html.erb
+++ b/railties/guides/source/layout.html.erb
@@ -81,6 +81,7 @@
<dt>Contributing to Rails</dt>
<dd><a href="contributing_to_rails.html">Contributing to Rails</a></dd>
<dd><a href="api_documentation_guidelines.html">API Documentation Guidelines</a></dd>
+ <dd><a href="ruby_on_rails_guides_guidelines.html">Ruby on Rails Guides Guidelines</a></dd>
<dt>Release Notes</dt>
<dd><a href="3_0_release_notes.html">Ruby on Rails 3.0 Release Notes</a></dd>
diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile
index 50c5986a64..088e1f817c 100644
--- a/railties/guides/source/layouts_and_rendering.textile
+++ b/railties/guides/source/layouts_and_rendering.textile
@@ -90,7 +90,7 @@ If we want to display the properties of all the books in our view, we can do so
<%= link_to 'New book', new_book_path %>
</ruby>
-NOTE: The actual rendering is done by subclasses of +ActionView::TemplateHandlers+. This guide does not dig into that process, but it's important to know that the file extension on your view controls the choice of template handler. In Rails 2, the standard extensions are +.erb+ for ERB (HTML with embedded Ruby), +.rjs+ for RJS (javascript with embedded ruby) and +.builder+ for Builder (XML generator).
+NOTE: The actual rendering is done by subclasses of +ActionView::TemplateHandlers+. This guide does not dig into that process, but it's important to know that the file extension on your view controls the choice of template handler. In Rails 2, the standard extensions are +.erb+ for ERB (HTML with embedded Ruby), +.rjs+ for RJS (JavaScript with embedded ruby) and +.builder+ for Builder (XML generator).
h4. Using +render+
@@ -252,7 +252,7 @@ render :inline =>
h5. Using +render+ with +:update+
-You can also render javascript-based page updates inline using the +:update+ option to +render+:
+You can also render JavaScript-based page updates inline using the +:update+ option to +render+:
<ruby>
render :update do |page|
@@ -260,7 +260,7 @@ render :update do |page|
end
</ruby>
-WARNING: Placing javascript updates in your controller may seem to streamline small updates, but it defeats the MVC orientation of Rails and will make it harder for other developers to follow the logic of your project. We recommend using a separate rjs template instead, no matter how small the update.
+WARNING: Placing JavaScript updates in your controller may seem to streamline small updates, but it defeats the MVC orientation of Rails and will make it harder for other developers to follow the logic of your project. We recommend using a separate RJS template instead, no matter how small the update.
h5. Rendering Text
@@ -276,7 +276,7 @@ NOTE: By default, if you use the +:text+ option, the text is rendered without us
h5. Rendering JSON
-JSON is a javascript data format used by many AJAX libraries. Rails has built-in support for converting objects to JSON and rendering that JSON back to the browser:
+JSON is a JavaScript data format used by many AJAX libraries. Rails has built-in support for converting objects to JSON and rendering that JSON back to the browser:
<ruby>
render :json => @product
@@ -655,7 +655,7 @@ I'll discuss each of these in turn.
h4. Asset Tags
-Asset tags provide methods for generating HTML that links views to assets like images, videos, audio, javascript, stylesheets, and feeds. There are six types of include tag:
+Asset tags provide methods for generating HTML that links views to assets like images, videos, audio, JavaScript, stylesheets, and feeds. There are six types of include tag:
* +auto_discovery_link_tag+
* +javascript_include_tag+
@@ -715,7 +715,7 @@ The +defaults+ option loads the Prototype and Scriptaculous libraries:
<%= javascript_include_tag :defaults %>
</erb>
-The +all+ option loads every javascript file in +public/javascripts+, starting with the Prototype and Scriptaculous libraries:
+The +all+ option loads every JavaScript file in +public/javascripts+, starting with the Prototype and Scriptaculous libraries:
<erb>
<%= javascript_include_tag :all %>
@@ -727,7 +727,7 @@ You can supply the +:recursive+ option to load files in subfolders of +public/ja
<%= javascript_include_tag :all, :recursive => true %>
</erb>
-If you're loading multiple javascript files, you can create a better user experience by combining multiple files into a single download. To make this happen in production, specify +:cache => true+ in your +javascript_include_tag+:
+If you're loading multiple JavaScript files, you can create a better user experience by combining multiple files into a single download. To make this happen in production, specify +:cache => true+ in your +javascript_include_tag+:
<erb>
<%= javascript_include_tag "main", "columns", :cache => true %>
@@ -962,7 +962,7 @@ The result of rendering this page into the supplied layout would be this HTML:
</html>
</erb>
-The +content_for+ method is very helpful when your layout contains distinct regions such as sidebars and footers that should get their own blocks of content inserted. It's also useful for inserting tags that load page-specific javascript or css files into the header of an otherwise generic layout.
+The +content_for+ method is very helpful when your layout contains distinct regions such as sidebars and footers that should get their own blocks of content inserted. It's also useful for inserting tags that load page-specific JavaScript or css files into the header of an otherwise generic layout.
h4. Using Partials
diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile
index 7d4fb69d3b..a8a8ee58ec 100644
--- a/railties/guides/source/routing.textile
+++ b/railties/guides/source/routing.textile
@@ -91,7 +91,7 @@ Creating a resourceful route will also expose a number of helpers to the control
* +photos_path+ returns +/photos+
* +new_photo_path+ returns +/photos/new+
-* +edit_photo_path+ returns +/photos/:id/edit+
+* +edit_photo_path(id)+ returns +/photos/:id/edit+ (for instance, +edit_photo_path(10)+ returns +/photos/10/edit+)
* +photo_path(id)+ returns +/photos/:id+ (for instance, +photo_path(10)+ returns +/photos/10+)
Each of these helpers has a corresponding +_url+ helper (such as +photos_url+) which returns the same path prefixed with the current host, port and path prefix.
diff --git a/railties/guides/source/ruby_on_rails_guides_guidelines.textile b/railties/guides/source/ruby_on_rails_guides_guidelines.textile
new file mode 100644
index 0000000000..0bc409cbda
--- /dev/null
+++ b/railties/guides/source/ruby_on_rails_guides_guidelines.textile
@@ -0,0 +1,77 @@
+h2. Ruby on Rails Guides Guidelines
+
+This guide documents guidelines for writing guides. This guide follows itself in a gracile loop.
+
+endprologue.
+
+h3. Textile
+
+Guides are written in "Textile":http://www.textism.com/tools/textile/. There's comprehensive documentation "here":http://redcloth.org/hobix.com/textile/ and a cheatsheet for markup "here":http://redcloth.org/hobix.com/textile/quick.html.
+
+h3. Prologue
+
+Each guide should start with motivational text at the top. That's the little introduction in the blue area. The prologue should tell the readers what's the guide about, and what will they learn. See for example the "Routing Guide":routing.html.
+
+h3. Titles
+
+The title of every guide uses +h2+, guide sections use +h3+, subsections +h4+, etc.
+
+Capitalize all words except for internal articles, prepositions, conjuctions, and forms of the verb to be:
+
+<plain>
+h5. Middleware Stack is an Array
+h5. When are Objects Saved?
+</plain>
+
+Use same typography as in regular text:
+
+<plain>
+h6. The +:content_type+ Option
+</plain>
+
+h3. API Documentation Guidelines
+
+The guides and the API should be coherent where appropriate. Please have a look at these particular sections of the "API Documentation Guidelines":api_documentation_guidelines.html:
+
+* "Wording":api_documentation_guidelines.html#wording
+* "Example Code":api_documentation_guidelines.html#example-code
+* "Filenames":api_documentation_guidelines.html#filenames
+* "Fonts":api_documentation_guidelines.html#fonts
+
+Those guidelines apply also to guides.
+
+h3. HTML Generation
+
+To generate all the guides just cd into the +railties+ directory and execute
+
+<plain>
+rake generate_guides
+</plain>
+
+You'll need the gems erubis, i18n, and RedCloth.
+
+To process +my_guide.textile+ and nothing else use the +ONLY+ environment variable:
+
+<plain>
+rake generate_guides ONLY=my_guide
+</plain>
+
+Although by default guides that have not been modified are not processed, so +ONLY+ is rarely needed in practice.
+
+To force process of al the guides pass +ALL=1+.
+
+It is also recommended that you work with +WARNINGS=1+, this detects duplicate IDs and warns about broken internal links.
+
+h3. HTML validation
+
+Please do validate the generated HTML with
+
+<plain>
+rake validate_guides
+</plain>
+
+Particularly, titles get an ID generated from their content and this often leads to duplicates. Please set +WARNINGS=1+ when generating guides to detect them. The warning messages suggest a way to fix them.
+
+h3. Changelog
+
+* October 5, 2010: ported from the docrails wiki and revised by "Xavier Noria":credits.html#fxn
diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb
index 3663910281..cca0891835 100644
--- a/railties/lib/rails.rb
+++ b/railties/lib/rails.rb
@@ -92,7 +92,7 @@ module Rails
end
def public_path
- application && application.paths.public.to_a.first
+ application && application.paths["public"].first
end
end
end
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index 0e85e6d1d5..d13356ab4d 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -39,6 +39,7 @@ module Rails
autoload :Configuration, 'rails/application/configuration'
autoload :Finisher, 'rails/application/finisher'
autoload :Railties, 'rails/application/railties'
+ autoload :RoutesReloader, 'rails/application/routes_reloader'
class << self
def inherited(base)
@@ -71,7 +72,7 @@ module Rails
end
def require_environment! #:nodoc:
- environment = paths.config.environment.to_a.first
+ environment = paths["config/environment"].existent.first
require environment if environment
end
@@ -80,18 +81,12 @@ module Rails
super
end
- def routes_reloader
- @routes_reloader ||= ActiveSupport::FileUpdateChecker.new([]){ reload_routes! }
+ def reload_routes!
+ routes_reloader.reload!
end
- def reload_routes!
- _routes = self.routes
- _routes.disable_clear_and_finalize = true
- _routes.clear!
- routes_reloader.paths.each { |path| load(path) }
- ActiveSupport.on_load(:action_controller) { _routes.finalize! }
- ensure
- _routes.disable_clear_and_finalize = false
+ def routes_reloader
+ @routes_reloader ||= RoutesReloader.new
end
def initialize!
@@ -133,10 +128,9 @@ module Rails
end
def initializers
- initializers = Bootstrap.initializers_for(self)
- initializers += super
- initializers += Finisher.initializers_for(self)
- initializers
+ Bootstrap.initializers_for(self) +
+ super +
+ Finisher.initializers_for(self)
end
def config
@@ -150,8 +144,8 @@ module Rails
rack_cache = config.action_controller.perform_caching && config.action_dispatch.rack_cache
require "action_dispatch/http/rack_cache" if rack_cache
+ middleware.use ::Rack::Cache, rack_cache if rack_cache
- middleware.use ::Rack::Cache, rack_cache if rack_cache
middleware.use ::ActionDispatch::Static, config.static_asset_paths if config.serve_static_assets
middleware.use ::Rack::Lock if !config.allow_concurrency
middleware.use ::Rack::Runtime
@@ -170,6 +164,8 @@ module Rails
middleware.use ::ActionDispatch::ParamsParser
middleware.use ::Rack::MethodOverride
middleware.use ::ActionDispatch::Head
+ middleware.use ::Rack::ConditionalGet
+ middleware.use ::Rack::ETag, "no-cache"
middleware.use ::ActionDispatch::BestStandardsSupport, config.action_dispatch.best_standards_support if config.action_dispatch.best_standards_support
end
end
diff --git a/railties/lib/rails/application/bootstrap.rb b/railties/lib/rails/application/bootstrap.rb
index e39b3bc705..213aa0768a 100644
--- a/railties/lib/rails/application/bootstrap.rb
+++ b/railties/lib/rails/application/bootstrap.rb
@@ -23,7 +23,7 @@ module Rails
# 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
+ path = config.paths["log"].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?
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index a0ecbc0fc8..3505388479 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -9,7 +9,7 @@ module Rails
:filter_parameters, :log_level, :logger,
:preload_frameworks, :reload_plugins,
:secret_token, :serve_static_assets, :session_options,
- :time_zone, :whiny_nils
+ :time_zone, :whiny_nils, :helpers_paths
def initialize(*)
super
@@ -17,6 +17,7 @@ module Rails
@allow_concurrency = false
@consider_all_requests_local = false
@filter_parameters = []
+ @helpers_paths = []
@dependency_loading = true
@serve_static_assets = true
@session_store = :cookie_store
@@ -24,6 +25,7 @@ module Rails
@time_zone = "UTC"
@middleware = app_middleware
@asset_path = '/'
+ @generators = app_generators
end
def asset_path=(value)
@@ -59,13 +61,12 @@ module Rails
def paths
@paths ||= begin
paths = super
- paths.config.database "config/database.yml"
- paths.config.environment "config/environment.rb"
- paths.lib.templates "lib/templates"
- paths.log "log/#{Rails.env}.log"
- paths.tmp "tmp"
- paths.tmp.cache "tmp/cache"
-
+ paths.add "config/database", :with => "config/database.yml"
+ paths.add "config/environment", :with => "config/environment.rb"
+ paths.add "lib/templates"
+ paths.add "log", :with => "log/#{Rails.env}.log"
+ paths.add "tmp"
+ paths.add "tmp/cache"
paths
end
end
@@ -87,7 +88,7 @@ module Rails
# YAML::load.
def database_configuration
require 'erb'
- YAML::load(ERB.new(IO.read(paths.config.database.to_a.first)).result)
+ YAML::load(ERB.new(IO.read(paths["config/database"].first)).result)
end
def cache_store
diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb
index b95df467c7..e3342be7ee 100644
--- a/railties/lib/rails/application/finisher.rb
+++ b/railties/lib/rails/application/finisher.rb
@@ -4,7 +4,7 @@ module Rails
include Initializable
initializer :add_generator_templates do
- config.generators.templates.unshift(*paths.lib.templates.to_a)
+ config.generators.templates.unshift(*paths["lib/templates"].existent)
end
initializer :ensure_autoload_once_paths_as_subset do
diff --git a/railties/lib/rails/application/routes_reloader.rb b/railties/lib/rails/application/routes_reloader.rb
new file mode 100644
index 0000000000..1d1f5e1b06
--- /dev/null
+++ b/railties/lib/rails/application/routes_reloader.rb
@@ -0,0 +1,45 @@
+module Rails
+ class Application
+ class RoutesReloader < ::ActiveSupport::FileUpdateChecker
+ attr_reader :route_sets
+
+ def initialize
+ super([]) { reload! }
+ @route_sets = []
+ end
+
+ def reload!
+ clear!
+ load_paths
+ finalize!
+ ensure
+ revert
+ end
+
+ protected
+
+ def clear!
+ route_sets.each do |routes|
+ routes.disable_clear_and_finalize = true
+ routes.clear!
+ end
+ end
+
+ def load_paths
+ paths.each { |path| load(path) }
+ end
+
+ def finalize!
+ route_sets.each do |routes|
+ ActiveSupport.on_load(:action_controller) { routes.finalize! }
+ end
+ end
+
+ def revert
+ route_sets.each do |routes|
+ routes.disable_clear_and_finalize = false
+ end
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb
index 60a93c9848..e3aa6d7c3e 100644
--- a/railties/lib/rails/commands.rb
+++ b/railties/lib/rails/commands.rb
@@ -11,7 +11,17 @@ command = ARGV.shift
command = aliases[command] || command
case command
-when 'generate', 'destroy', 'plugin', 'benchmarker', 'profiler'
+when 'generate', 'destroy', 'plugin'
+ require APP_PATH
+ Rails.application.require_environment!
+
+ if defined?(ENGINE_PATH)
+ engine = Rails.application.railties.engines.find { |r| r.root.to_s == ENGINE_PATH }
+ Rails.application = engine
+ end
+ require "rails/commands/#{command}"
+
+when 'benchmarker', 'profiler'
require APP_PATH
Rails.application.require_environment!
require "rails/commands/#{command}"
@@ -23,8 +33,15 @@ when 'console'
Rails::Console.start(Rails.application)
when 'server'
+ # Change to the application's path if there is no config.ru file in current dir.
+ # This allows us to run script/rails server from other directories, but still get
+ # the main config.ru and properly set the tmp directory.
+ Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exists?(File.expand_path("config.ru"))
+
require 'rails/commands/server'
Rails::Server.new.tap { |server|
+ # We need to require application after the server sets environment,
+ # otherwise the --environment option given to the server won't propagate.
require APP_PATH
Dir.chdir(Rails.application.root)
server.start
diff --git a/railties/lib/rails/commands/plugin.rb b/railties/lib/rails/commands/plugin.rb
index 7bb4a1c054..8b2cd1bdba 100644
--- a/railties/lib/rails/commands/plugin.rb
+++ b/railties/lib/rails/commands/plugin.rb
@@ -58,7 +58,7 @@ class RailsEnvironment
else
plugin = name_uri_or_plugin
end
- unless plugin.nil?
+ if plugin
plugin.install
else
puts "Plugin not found: #{name_uri_or_plugin}"
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index 0620b8608e..e9ce9610b8 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -17,7 +17,7 @@ module Rails
# In Rails versions before to 3.0, your gems automatically behaved as Engine, however
# this coupled Rails to Rubygems. Since Rails 3.0, if you want a gem to automatically
# behave as Engine, you have to specify an Engine for it somewhere inside your plugin
- # lib folder (similar with how we spceify a Railtie):
+ # lib folder (similar to how we specify a Railtie):
#
# # lib/my_engine.rb
# module MyEngine
@@ -47,6 +47,26 @@ module Rails
# end
# end
#
+ # == Generators
+ #
+ # You can set up generators for engine with config.generators method:
+ #
+ # class MyEngine < Rails::Engine
+ # config.generators do |g|
+ # g.orm :active_record
+ # g.template_engine :erb
+ # g.test_framework :test_unit
+ # end
+ # end
+ #
+ # You can also set generators for application by using config.app_generators:
+ #
+ # class MyEngine < Rails::Engine
+ # # note that you can also pass block to app_generators in the same way you
+ # # can pass it to generators method
+ # config.app_generators.orm :datamapper
+ # end
+ #
# == Paths
#
# Since Rails 3.0, both your Application and Engines do not have hardcoded paths.
@@ -57,30 +77,30 @@ module Rails
# you need to do is:
#
# class MyEngine < Rails::Engine
- # paths.app.controllers = "lib/controllers"
+ # paths["app/controllers"] = "lib/controllers"
# end
#
# You can also have your controllers being loaded from both "app/controllers" and
# "lib/controllers":
#
# class MyEngine < Rails::Engine
- # paths.app.controllers << "lib/controllers"
+ # paths["app/controllers"] << "lib/controllers"
# end
#
# The available paths in an Engine are:
#
# class MyEngine < Rails::Engine
- # paths.app = "app"
- # paths.app.controllers = "app/controllers"
- # paths.app.helpers = "app/helpers"
- # paths.app.models = "app/models"
- # paths.app.views = "app/views"
- # paths.lib = "lib"
- # paths.lib.tasks = "lib/tasks"
- # paths.config = "config"
- # paths.config.initializers = "config/initializers"
- # paths.config.locales = "config/locales"
- # paths.config.routes = "config/routes.rb"
+ # paths["app"] #=> ["app"]
+ # paths["app/controllers"] #=> ["app/controllers"]
+ # paths["app/helpers"] #=> ["app/helpers"]
+ # paths["app/models"] #=> ["app/models"]
+ # paths["app/views"] #=> ["app/views"]
+ # paths["lib"] #=> ["lib"]
+ # paths["lib/tasks"] #=> ["lib/tasks"]
+ # paths["config"] #=> ["config"]
+ # paths["config/initializers"] #=> ["config/initializers"]
+ # paths["config/locales"] #=> ["config/locales"]
+ # paths["config/routes"] #=> ["config/routes.rb"]
# end
#
# Your Application class adds a couple more paths to this set. And as in your Application,
@@ -165,19 +185,21 @@ module Rails
# == Serving static files
#
# By default, rails use ActionDispatch::Static to serve static files in development mode. This is ok
- # while you develop your application, but when you want to deploy it, assets from engine will not be served.
+ # while you develop your application, but when you want to deploy it, assets from engine will not be
+ # served by default. You should choose one of the two following strategies:
#
- # You can fix it in one of two ways:
# * enable serving static files by setting config.serve_static_assets to true
# * symlink engines' public directories in application's public directory by running
- # `rake railties:create_symlinks`
+ # `rake ENGINE_NAME:install:assets`, where ENGINE_NAME is usually my_engine for the
+ # examples above
#
# == Engine name
#
# There are some places where engine's name is used.
+ #
# * routes: when you mount engine with mount(MyEngine::Engine => '/my_engine'), it's used as default :as option
- # * migrations: when you copy engine's migrations, they will be decorated with suffix based on engine_name, for example:
- # 2010010203121314_create_users.my_engine.rb
+ #
+ # * rake tasks: engines have a few rake tasks. They are usually under my_engine namespace.
#
# Engine name is set by default based on class name. For MyEngine::Engine it will be my_engine_engine.
# You can change it manually it manually using engine_name method:
@@ -190,15 +212,17 @@ module Rails
#
# == Namespaced Engine
#
- # Normally, when you create controllers, helpers and models inside engine, they are treated
- # as they would be created inside application. One of the cosequences of that is including
- # application's helpers and url_helpers inside controller. Sometimes, especially when your
- # engine provides its own routes, you don't want that. To isolate engine's stuff from application
- # you can use namespace method:
+ # Normally when you create controllers, helpers and models inside engine, they are treated
+ # as they were created inside the application. This means all applications helpers and named routes
+ # will be available to your engine controllers.
+ #
+ # However, sometimes you want to isolate your engine from the application, specially if your engine
+ # have its own router. To do that, you simply need to call +isolate_namespace+. This method requires
+ # you to pass a module where all your controllers, helpers and models should be nested to:
#
# module MyEngine
# class Engine < Rails::Engine
- # namespace MyEngine
+ # isolate_namespace MyEngine
# end
# end
#
@@ -215,15 +239,21 @@ module Rails
# url_helpers from MyEngine::Engine.routes.
#
# The next thing that changes in isolated engine is routes behaviour. Normally, when you namespace
- # your controllers, you need to use scope or namespace method in routes. With isolated engine,
- # the namespace is applied by default, so you can ignore it in routes. Further more, you don't need
- # to use longer url helpers like "my_engine_articles_path". As the prefix is not set you can just use
- # articles_path as you would normally do.
+ # your controllers, you also need to do namespace all your routes. With isolated engine,
+ # the namespace is applied by default, so you can ignore it in routes:
+ #
+ # MyEngine::Engine.routes.draw do
+ # resources :articles
+ # end
+ #
+ # The routes above will automatically point to MyEngine::ApplicationContoller. Further more, you don't
+ # need to use longer url helpers like "my_engine_articles_path". Instead, you shuold simply use
+ # articles_path as you would do with your application.
#
# To make that behaviour consistent with other parts of framework, isolated engine has influence also on
# ActiveModel::Naming. When you use namespaced model, like MyEngine::Article, it will normally
- # use the prefix "my_engine". In isolated engine, the prefix will be ommited in most of the places,
- # like url helpers or form fields.
+ # use the prefix "my_engine". In isolated engine, the prefix will be ommited in url helpers and
+ # form fields for convenience.
#
# polymorphic_url(MyEngine::Article.new) #=> "articles_path"
#
@@ -231,16 +261,15 @@ module Rails
# text_field :title #=> <input type="text" name="article[title]" id="article_title" />
# end
#
- #
- # Additionaly namespaced engine will set its name according to namespace, so in that case:
- # MyEngine::Engine.engine_name #=> "my_engine" and it will set MyEngine.table_name_prefix
- # to "my_engine_".
+ # Additionaly isolated engine will set its name according to namespace, so
+ # MyEngine::Engine.engine_name #=> "my_engine". It will also set MyEngine.table_name_prefix
+ # to "my_engine_", changing MyEngine::Article model to use my_engine_article table.
#
# == Using Engine's routes outside Engine
#
- # Since you can mount engine inside application's routes now, you do not have direct access to engine's
- # url_helpers inside application. When you mount Engine in application's routes special helper is
- # created to allow doing that. Consider such scenario:
+ # Since now you can mount engine inside application's routes, you do not have direct access to engine's
+ # url_helpers inside application. When you mount Engine in application's routes, a special helper is
+ # created to allow you to do that. Consider such scenario:
#
# # APP/config/routes.rb
# MyApplication::Application.routes.draw do
@@ -248,7 +277,7 @@ module Rails
# match "/foo" => "foo#index"
# end
#
- # Now, you can use my_engine helper:
+ # Now, you can use my_engine helper inside your application:
#
# class FooController < ApplicationController
# def index
@@ -256,24 +285,27 @@ module Rails
# end
# end
#
- # There is also 'app' helper that gives you access to application's routes inside Engine:
+ # There is also 'main_app' helper that gives you access to application's routes inside Engine:
#
# module MyEngine
# class BarController
- # app.foo_path #=> /foo
+ # def index
+ # main_app.foo_path #=> /foo
+ # end
# end
# end
#
- # Note that :as option takes engine_name as default, so most of the time you can ommit it.
+ # Note that the :as option given to mount takes the engine_name as default, so most of the time
+ # you can simply ommit it.
#
- # If you want to generate url to engine's route using polymorphic_url, you can also use that helpers.
- #
- # Let's say that you want to create a form pointing to one of the engine's routes. All you need to do
- # is passing helper as the first element in array with attributes for url:
+ # Finally, if you want to generate url to engine's route using polymorphic_url, you also need
+ # to pass the engine helper. Let's say that you want to create a form pointing to one of the
+ # engine's routes. All you need to do is pass the helper as the first element in array with
+ # attributes for url:
#
# form_for([my_engine, @user])
#
- # This code will use my_engine.user_path(@user) to generate proper route.
+ # This code will use my_engine.user_path(@user) to generate the proper route.
#
# == Migrations & seed data
#
@@ -283,7 +315,7 @@ module Rails
# To use engine's migrations in application you can use rake task, which copies them to
# application's dir:
#
- # rake railties:copy_migrations
+ # rake ENGINE_NAME:install:migrations
#
# If your engine has migrations, you may also want to prepare data for the database in
# seeds.rb file. You can load that data using load_seed method, e.g.
@@ -295,7 +327,7 @@ module Rails
autoload :Configuration, "rails/engine/configuration"
class << self
- attr_accessor :called_from, :namespaced
+ attr_accessor :called_from, :isolated
alias :engine_name :railtie_name
def inherited(base)
@@ -330,37 +362,38 @@ module Rails
@endpoint
end
- def namespace(mod)
+ def isolate_namespace(mod)
engine_name(generate_railtie_name(mod))
- _railtie = self
name = engine_name
- mod.singleton_class.instance_eval do
- define_method(:_railtie) do
- _railtie
- end
-
- define_method(:table_name_prefix) do
- "#{name}_"
- end
- end
-
self.routes.default_scope = {:module => name}
-
- self.namespaced = true
+ self.isolated = true
+
+ unless mod.respond_to?(:_railtie)
+ _railtie = self
+ mod.singleton_class.instance_eval do
+ define_method(:_railtie) do
+ _railtie
+ end
+
+ define_method(:table_name_prefix) do
+ "#{name}_"
+ end
+ end
+ end
end
- def namespaced?
- !!namespaced
+ def isolated?
+ !!isolated
end
end
delegate :middleware, :root, :paths, :to => :config
- delegate :engine_name, :namespaced?, :to => "self.class"
+ delegate :engine_name, :isolated?, :to => "self.class"
def load_tasks
super
- config.paths.lib.tasks.to_a.sort.each { |ext| load(ext) }
+ paths["lib/tasks"].existent.sort.each { |ext| load(ext) }
end
def eager_load!
@@ -400,6 +433,8 @@ module Rails
def routes
@routes ||= ActionDispatch::Routing::RouteSet.new
+ @routes.append(&Proc.new) if block_given?
+ @routes
end
def initializers
@@ -418,7 +453,7 @@ module Rails
#
# Blog::Engine.load_seed
def load_seed
- seed_file = config.paths.db.seeds.to_a.first
+ seed_file = paths["db/seeds"].existent.first
load(seed_file) if File.exist?(seed_file)
end
@@ -446,19 +481,22 @@ module Rails
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)
+ paths = self.paths["config/routes"].existent
+
+ if routes? || paths.any?
+ app.routes_reloader.paths.unshift(*paths)
+ app.routes_reloader.route_sets << routes
end
end
# I18n load paths are a special case since the ones added
# later have higher priority.
initializer :add_locales do
- config.i18n.railties_load_path.concat(paths.config.locales.to_a)
+ config.i18n.railties_load_path.concat(paths["config/locales"].existent)
end
initializer :add_view_paths do
- views = paths.app.views.to_a
+ views = paths["app/views"].existent
unless views.empty?
ActiveSupport.on_load(:action_controller){ prepend_view_path(views) }
ActiveSupport.on_load(:action_mailer){ prepend_view_path(views) }
@@ -466,28 +504,27 @@ module Rails
end
initializer :load_environment_config, :before => :load_environment_hook do
- environment = config.paths.config.environments.to_a.first
+ environment = paths["config/environments"].existent.first
require environment if environment
end
initializer :append_asset_paths do
config.asset_path ||= "/#{engine_name}%s"
- public_path = config.paths.public.to_a.first
+ public_path = paths["public"].first
if config.compiled_asset_path && File.exist?(public_path)
config.static_asset_paths[config.compiled_asset_path] = public_path
end
end
- initializer :prepend_helpers_path do
- unless namespaced?
- config.helpers_paths = [] unless config.respond_to?(:helpers_paths)
- config.helpers_paths = config.paths.app.helpers.to_a + config.helpers_paths
+ initializer :prepend_helpers_path do |app|
+ if !isolated? || (app == self)
+ app.config.helpers_paths.unshift(*paths["app/helpers"].existent)
end
end
initializer :load_config_initializers do
- paths.config.initializers.to_a.sort.each do |initializer|
+ config.paths["config/initializers"].existent.sort.each do |initializer|
load(initializer)
end
end
@@ -497,7 +534,27 @@ module Rails
# consistently executed after all the initializers above across all engines.
end
+ rake_tasks do
+ next if self.is_a?(Rails::Application)
+
+ namespace railtie_name do
+ namespace :install do
+ # TODO Add assets copying to this list
+ # TODO Skip this if there is no paths["db/migrate"] for the engine
+ desc "Copy migrations from #{railtie_name} to application"
+ task :migrations do
+ ENV["FROM"] = railtie_name
+ Rake::Task["railties:install:migrations"].invoke
+ end
+ end
+ end
+ end
+
protected
+ def routes?
+ defined?(@routes)
+ end
+
def find_root_with_flag(flag, default=nil)
root_path = self.class.called_from
@@ -509,7 +566,7 @@ module Rails
root = File.exist?("#{root_path}/#{flag}") ? root_path : default
raise "Could not find root path for #{self}" unless root
- Config::CONFIG['host_os'] =~ /mswin|mingw/ ?
+ RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ?
Pathname.new(root).expand_path : Pathname.new(root).realpath
end
diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb
index d4d87be527..7a07dcad7d 100644
--- a/railties/lib/rails/engine/configuration.rb
+++ b/railties/lib/rails/engine/configuration.rb
@@ -4,40 +4,61 @@ module Rails
class Engine
class Configuration < ::Rails::Railtie::Configuration
attr_reader :root
- attr_writer :eager_load_paths, :autoload_once_paths, :autoload_paths
- attr_accessor :middleware, :plugins, :asset_path
+ attr_writer :middleware, :eager_load_paths, :autoload_once_paths, :autoload_paths
+ attr_accessor :plugins, :asset_path
def initialize(root=nil)
super()
@root = root
- @middleware = Rails::Configuration::MiddlewareStackProxy.new
- @helpers_paths = []
+ end
+
+ # Returns the middleware stack for the engine.
+ def middleware
+ @middleware ||= Rails::Configuration::MiddlewareStackProxy.new
+ 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 #:nodoc
+ @generators ||= Rails::Configuration::Generators.new
+ yield(@generators) if block_given?
+ @generators
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.mailers "app/mailers", :eager_load => true
- 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.config.environments "config/environments", :glob => "#{Rails.env}.rb"
- paths.public "public"
- paths.public.javascripts "public/javascripts"
- paths.public.stylesheets "public/stylesheets"
- paths.vendor "vendor", :load_path => true
- paths.vendor.plugins "vendor/plugins"
- paths.db "db"
- paths.db.migrate "db/migrate"
- paths.db.seeds "db/seeds.rb"
+ paths.add "app", :eager_load => true, :glob => "*"
+ paths.add "app/controllers", :eager_load => true
+ paths.add "app/helpers", :eager_load => true
+ paths.add "app/models", :eager_load => true
+ paths.add "app/mailers", :eager_load => true
+ paths.add "app/views"
+ paths.add "lib", :load_path => true
+ paths.add "lib/tasks", :glob => "**/*.rake"
+ paths.add "config"
+ paths.add "config/environments", :glob => "#{Rails.env}.rb"
+ paths.add "config/initializers", :glob => "**/*.rb"
+ paths.add "config/locales", :glob => "*.{rb,yml}"
+ paths.add "config/routes", :with => "config/routes.rb"
+ paths.add "db"
+ paths.add "db/migrate"
+ paths.add "db/seeds", :with => "db/seeds.rb"
+ paths.add "public"
+ paths.add "public/javascripts"
+ paths.add "public/stylesheets"
+ paths.add "vendor", :load_path => true
+ paths.add "vendor/plugins"
paths
end
end
diff --git a/railties/lib/rails/engine/railties.rb b/railties/lib/rails/engine/railties.rb
index 389a7602c6..e91bdbf1e5 100644
--- a/railties/lib/rails/engine/railties.rb
+++ b/railties/lib/rails/engine/railties.rb
@@ -15,7 +15,7 @@ module Rails
def plugins
@plugins ||= begin
plugin_names = (@config.plugins || [:all]).map { |p| p.to_sym }
- Plugin.all(plugin_names, @config.paths.vendor.plugins)
+ Plugin.all(plugin_names, @config.paths["vendor/plugins"].existent)
end
end
end
diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb
index 8f0d5ffff4..378c07cb0e 100644
--- a/railties/lib/rails/generators/actions.rb
+++ b/railties/lib/rails/generators/actions.rb
@@ -187,8 +187,8 @@ module Rails
# initializer("globals.rb") do
# data = ""
#
- # ['MY_WORK', 'ADMINS', 'BEST_COMPANY_EVAR'].each do
- # data << "#{const} = :entp"
+ # ['MY_WORK', 'ADMINS', 'BEST_COMPANY_EVAR'].each do |const|
+ # data << "#{const} = :entp\n"
# end
#
# data
diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb
index 2715483914..7907191c74 100644
--- a/railties/lib/rails/generators/rails/app/app_generator.rb
+++ b/railties/lib/rails/generators/rails/app/app_generator.rb
@@ -14,23 +14,20 @@ module Rails
@options = generator.options
end
- private
- %w(template copy_file directory empty_directory inside
- empty_directory_with_gitkeep create_file chmod shebang).each do |method|
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def #{method}(*args, &block)
- @generator.send(:#{method}, *args, &block)
- end
- RUBY
- end
+ private
- # TODO: Remove once this is fully in place
- def method_missing(meth, *args, &block)
- STDERR.puts "Calling #{meth} with #{args.inspect} with #{block}"
- @generator.send(meth, *args, &block)
- end
+ def method_missing(meth, *args, &block)
+ @generator.send(meth, *args, &block)
+ end
end
+ # The application builder allows you to override elements of the application
+ # generator without being forced to reverse the operations of the default
+ # generator.
+ #
+ # This allows you to override entire operations, like the creation of the
+ # Gemfile, README, or javascript files, without needing to know exactly
+ # what those operations do so you can create another template action.
class AppBuilder
def rakefile
template "Rakefile"
diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile
index 1dbf27d978..40213b1261 100644
--- a/railties/lib/rails/generators/rails/app/templates/Gemfile
+++ b/railties/lib/rails/generators/rails/app/templates/Gemfile
@@ -3,15 +3,18 @@ source 'http://rubygems.org'
<%- if options.dev? -%>
gem 'rails', :path => '<%= Rails::Generators::RAILS_DEV_PATH %>'
gem 'arel', :git => 'git://github.com/rails/arel.git'
+gem "rack", :git => "git://github.com/rack/rack.git"
<%- elsif options.edge? -%>
gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'arel', :git => 'git://github.com/rails/arel.git'
+gem "rack", :git => "git://github.com/rack/rack.git"
<%- else -%>
gem 'rails', '<%= Rails::VERSION::STRING %>'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
# gem 'arel', :git => 'git://github.com/rails/arel.git'
+# gem "rack", :git => "git://github.com/rack/rack.git"
<%- end -%>
<% unless options[:skip_active_record] -%>
diff --git a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt
index 1dd112b4a6..1de78eecae 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt
@@ -4,7 +4,7 @@
<title><%= app_const_base %></title>
<%%= stylesheet_link_tag :all %>
<%%= javascript_include_tag :defaults %>
- <%%= csrf_meta_tag %>
+ <%%= csrf_meta_tags %>
</head>
<body>
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml
index fddf8b8144..b661a60389 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml
@@ -10,7 +10,7 @@
#
# By default prefetch_rows (OCI_ATTR_PREFETCH_ROWS) is set to 100. And
# until true bind variables are supported, cursor_sharing is set by default
-# to 'similar'. Both can be changed in the configation below; the defaults
+# to 'similar'. Both can be changed in the configuration below; the defaults
# are equivalent to specifying:
#
# prefetch_rows: 100
diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb
index d303212f52..8570fc7b3f 100644
--- a/railties/lib/rails/paths.rb
+++ b/railties/lib/rails/paths.rb
@@ -2,15 +2,17 @@ require 'set'
module Rails
module Paths
- module PathParent
- attr_reader :children
-
+ module PathParent #:nodoc:
def method_missing(id, *args)
- name = id.to_s
+ match = id.to_s.match(/^(.*)=$/)
+ full = [@current, $1 || id].compact.join("/")
+
+ ActiveSupport::Deprecation.warn 'config.paths.app.controller API is deprecated in ' <<
+ 'favor of config.paths["app/controller"] API.'
- if name =~ /^(.*)=$/ || args.any?
- @children[$1 || name] = Path.new(@root, *args)
- elsif path = @children[name]
+ if match || args.any?
+ @root[full] = Path.new(@root, full, *args)
+ elsif path = @root[full]
path
else
super
@@ -18,22 +20,72 @@ module Rails
end
end
- class Root
+ # This object is an extended hash that behaves as root of the Rails::Paths system.
+ # It allows you to collect information about how you want to structure your application
+ # paths by a Hash like API. It requires you to give a physical path on initialization.
+ #
+ # root = Root.new
+ # root.add "app/controllers", :eager_load => true
+ #
+ # The command above creates a new root object and add "app/controllers" as a path.
+ # This means we can get a Path object back like below:
+ #
+ # path = root["app/controllers"]
+ # path.eager_load? #=> true
+ # path.is_a?(Rails::Paths::Path) #=> true
+ #
+ # The Path object is simply an array and allows you to easily add extra paths:
+ #
+ # path.is_a?(Array) #=> true
+ # path.inspect #=> ["app/controllers"]
+ #
+ # path << "lib/controllers"
+ # path.inspect #=> ["app/controllers", "lib/controllers"]
+ #
+ # Notice that when you add a path using #add, the path object created already
+ # contains the path with the same path value given to #add. In some situations,
+ # you may not want this behavior, so you can give :with as option.
+ #
+ # root.add "config/routes", :with => "config/routes.rb"
+ # root["config/routes"].inspect #=> ["config/routes.rb"]
+ #
+ # #add also accepts the following options as argument: eager_load, autoload,
+ # autoload_once and glob.
+ #
+ # Finally, the Path object also provides a few helpers:
+ #
+ # root = Root.new
+ # root.path = "/rails"
+ # root.add "app/controllers"
+ #
+ # root["app/controllers"].expanded #=> ["/rails/app/controllers"]
+ # root["app/controllers"].existent #=> ["/rails/app/controllers"]
+ #
+ # Check the Path documentation for more information.
+ class Root < ::Hash
include PathParent
-
attr_accessor :path
def initialize(path)
raise if path.is_a?(Array)
- @children = {}
+ @current = nil
@path = path
@root = self
- @all_paths = []
+ super()
+ end
+
+ def []=(path, value)
+ value = Path.new(self, path, value) unless value.is_a?(Path)
+ super(path, value)
+ end
+
+ def add(path, options={})
+ with = options[:with] || path
+ self[path] = Path.new(self, path, with, options)
end
def all_paths
- @all_paths.uniq!
- @all_paths
+ values.tap { |v| v.uniq! }
end
def autoload_once
@@ -52,68 +104,54 @@ module Rails
filter_by(:load_path?)
end
- def push(*)
- raise "Application root can only have one physical path"
- end
-
- alias unshift push
- alias << push
- alias concat push
-
protected
def filter_by(constraint)
all = []
all_paths.each do |path|
if path.send(constraint)
- paths = path.paths
- paths -= path.children.values.map { |p| p.send(constraint) ? [] : p.paths }.flatten
+ paths = path.existent
+ paths -= path.children.map { |p| p.send(constraint) ? [] : p.existent }.flatten
all.concat(paths)
end
end
all.uniq!
- all.reject! { |p| !File.exists?(p) }
all
end
end
- class Path
- include PathParent, Enumerable
+ class Path < Array
+ include PathParent
attr_reader :path
attr_accessor :glob
- def initialize(root, *paths)
- options = paths.last.is_a?(::Hash) ? paths.pop : {}
- @children = {}
+ def initialize(root, current, *paths)
+ options = paths.last.is_a?(::Hash) ? paths.pop : {}
+ super(paths.flatten)
+
+ @current = current
@root = root
- @paths = paths.flatten
@glob = options[:glob]
autoload_once! if options[:autoload_once]
eager_load! if options[:eager_load]
autoload! if options[:autoload]
load_path! if options[:load_path]
-
- @root.all_paths << self
- end
-
- def each
- to_a.each { |p| yield p }
end
- def push(path)
- @paths.push path
+ def children
+ keys = @root.keys.select { |k| k.include?(@current) }
+ keys.delete(@current)
+ @root.values_at(*keys.sort)
end
- alias << push
-
- def unshift(path)
- @paths.unshift path
+ def first
+ expanded.first
end
- def concat(paths)
- @paths.concat paths
+ def last
+ expanded.last
end
%w(autoload_once eager_load autoload load_path).each do |m|
@@ -132,20 +170,36 @@ module Rails
RUBY
end
- def paths
+ # Expands all paths against the root and return all unique values.
+ def expanded
raise "You need to set a path root" unless @root.path
+ result = []
- result = @paths.map do |p|
+ each do |p|
path = File.expand_path(p, @root.path)
- @glob ? Dir[File.join(path, @glob)] : path
+
+ if @glob
+ result.concat Dir[File.join(path, @glob)]
+ else
+ result << path
+ end
end
- result.flatten!
result.uniq!
result
end
- alias to_a paths
+ # Returns all expanded paths but only if they exist in the filesystem.
+ def existent
+ expanded.select { |f| File.exists?(f) }
+ end
+
+ def paths
+ ActiveSupport::Deprecation.warn "paths is deprecated. Please call expand instead."
+ expanded
+ end
+
+ alias to_a expanded
end
end
-end \ No newline at end of file
+end
diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb
index 5614624673..ceddd25eaa 100644
--- a/railties/lib/rails/plugin.rb
+++ b/railties/lib/rails/plugin.rb
@@ -62,13 +62,13 @@ module Rails
end
initializer :handle_lib_autoload, :before => :set_load_path do |app|
- paths = if app.config.reload_plugins
+ autoload = if app.config.reload_plugins
config.autoload_paths
else
config.autoload_once_paths
end
- paths.concat config.paths.lib.to_a
+ autoload.concat paths["lib"].existent
end
initializer :load_init_rb, :before => :load_config_initializers do |app|
@@ -83,7 +83,7 @@ module Rails
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"
+ raise "\"#{name}\" is a Railtie/Engine and cannot be installed as a plugin"
end
end
end
diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb
index 09650789ac..c76bc83377 100644
--- a/railties/lib/rails/railtie.rb
+++ b/railties/lib/rails/railtie.rb
@@ -83,7 +83,7 @@ module Rails
#
# class MyRailtie < Rails::Railtie
# # Customize the ORM
- # config.generators.orm :my_railtie_orm
+ # config.app_generators.orm :my_railtie_orm
#
# # Add a to_prepare block which is executed once in production
# # and before each request in development
@@ -191,6 +191,13 @@ module Rails
def load_tasks
self.class.rake_tasks.each(&:call)
+
+ # load also tasks from all superclasses
+ klass = self.class.superclass
+ while klass.respond_to?(:rake_tasks)
+ klass.rake_tasks.each { |t| self.instance_exec(&t) }
+ klass = klass.superclass
+ end
end
def load_generators
diff --git a/railties/lib/rails/railtie/configuration.rb b/railties/lib/rails/railtie/configuration.rb
index f09e3940cc..afeceafb67 100644
--- a/railties/lib/rails/railtie/configuration.rb
+++ b/railties/lib/rails/railtie/configuration.rb
@@ -5,7 +5,6 @@ module Rails
class Configuration
def initialize
@@options ||= {}
- @@static_asset_paths = ActiveSupport::OrderedHash.new
end
# This allows you to modify the application's middlewares from Engines.
@@ -17,25 +16,19 @@ module Rails
@@app_middleware ||= Rails::Configuration::MiddlewareStackProxy.new
end
- # Holds generators configuration:
+ # This allows you to modify application's generators from Railties.
#
- # 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
+ # Values set on app_generators will become defaults for applicaiton, unless
+ # application overwrites them.
+ def app_generators
+ @@app_generators ||= Rails::Configuration::Generators.new
+ yield(@@app_generators) if block_given?
+ @@app_generators
+ end
+
+ def generators(&block) #:nodoc
+ ActiveSupport::Deprecation.warn "config.generators in Rails::Railtie is deprecated. Please use config.app_generators instead."
+ app_generators(&block)
end
def before_configuration(&block)
@@ -70,7 +63,7 @@ module Rails
# with associated public folders, like:
# { "/" => "/app/public", "/my_engine" => "app/engines/my_engine/public" }
def static_asset_paths
- @@static_asset_paths
+ @@static_asset_paths ||= ActiveSupport::OrderedHash.new
end
private
diff --git a/railties/lib/rails/tasks/documentation.rake b/railties/lib/rails/tasks/documentation.rake
index 7aefbb49b0..edd716d7d0 100644
--- a/railties/lib/rails/tasks/documentation.rake
+++ b/railties/lib/rails/tasks/documentation.rake
@@ -47,7 +47,7 @@ namespace :doc do
rdoc.rdoc_files.include('app/**/*.rb')
rdoc.rdoc_files.include('lib/**/*.rb')
}
- Rake::Task['doc:app'].comment = "Generate docs for the app -- also availble doc:rails, doc:guides, doc:plugins (options: TEMPLATE=/rdoc-template.rb, TITLE=\"Custom Title\")"
+ Rake::Task['doc:app'].comment = "Generate docs for the app -- also available doc:rails, doc:guides, doc:plugins (options: TEMPLATE=/rdoc-template.rb, TITLE=\"Custom Title\")"
# desc 'Generate documentation for the Rails framework.'
RDocTaskWithoutDescriptions.new("rails") { |rdoc|
diff --git a/railties/lib/rails/tasks/railties.rake b/railties/lib/rails/tasks/railties.rake
index 7cf31f84a0..e08bd9687d 100644
--- a/railties/lib/rails/tasks/railties.rake
+++ b/railties/lib/rails/tasks/railties.rake
@@ -1,8 +1,8 @@
namespace :railties do
- desc "Create symlinks to railties public directories in application's public directory."
+ # desc "Create symlinks to railties public directories in application's public directory."
task :create_symlinks => :environment do
paths = Rails.application.config.static_asset_paths.dup
- app_public_path = Rails.application.config.paths.public.to_a.first
+ app_public_path = Rails.application.paths["public"].first
paths.each do |mount_path, path|
symlink_path = File.join(app_public_path, mount_path)
diff --git a/railties/lib/rails/test_unit/railtie.rb b/railties/lib/rails/test_unit/railtie.rb
index e3fafc4b9d..2b6170ebfb 100644
--- a/railties/lib/rails/test_unit/railtie.rb
+++ b/railties/lib/rails/test_unit/railtie.rb
@@ -1,6 +1,6 @@
module Rails
class TestUnitRailtie < Rails::Railtie
- config.generators do |c|
+ config.app_generators do |c|
c.test_framework :test_unit, :fixture => true,
:fixture_replacement => nil
diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake
index 713833f884..28dc40379b 100644
--- a/railties/lib/rails/test_unit/testing.rake
+++ b/railties/lib/rails/test_unit/testing.rake
@@ -73,7 +73,8 @@ end
desc 'Runs test:units, test:functionals, test:integration together (also available: test:benchmark, test:profile, test:plugins)'
task :test do
- errors = %w(test:units test:functionals test:integration).collect do |task|
+ tests_to_run = ENV['TEST'] ? ["test:single"] : %w(test:units test:functionals test:integration)
+ errors = tests_to_run.collect do |task|
begin
Rake::Task[task].invoke
nil
@@ -123,6 +124,10 @@ namespace :test do
end
Rake::Task['test:uncommitted'].comment = "Test changes since last checkin (only Subversion and Git)"
+ Rake::TestTask.new(:single => "test:prepare") do |t|
+ t.libs << "test"
+ end
+
TestTaskWithoutDescription.new(:units => "test:prepare") do |t|
t.libs << "test"
t.pattern = 'test/unit/**/*_test.rb'
diff --git a/railties/railties.gemspec b/railties/railties.gemspec
index 73acb73dec..d26c1bcdbc 100644
--- a/railties/railties.gemspec
+++ b/railties/railties.gemspec
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
s.has_rdoc = false
s.add_dependency('rake', '>= 0.8.7')
- s.add_dependency('thor', '~> 0.14.2')
+ s.add_dependency('thor', '~> 0.14.3')
s.add_dependency('activesupport', version)
s.add_dependency('actionpack', version)
end
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index 7403d16cf4..b8d0854286 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -42,7 +42,7 @@ module ApplicationTests
test "Rails::Application responds to paths" do
require "#{app_path}/config/environment"
assert_respond_to AppTemplate::Application, :paths
- assert_equal AppTemplate::Application.paths.app.views.to_a, ["#{app_path}/app/views"]
+ assert_equal AppTemplate::Application.paths["app/views"].expanded, ["#{app_path}/app/views"]
end
test "the application root is set correctly" do
@@ -180,7 +180,7 @@ module ApplicationTests
test "config.paths.public sets Rails.public_path" do
add_to_config <<-RUBY
- config.paths.public = "somewhere"
+ config.paths["public"] = "somewhere"
RUBY
require "#{app_path}/config/application"
diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb
index 25b4a21902..d4159dd0fd 100644
--- a/railties/test/application/console_test.rb
+++ b/railties/test/application/console_test.rb
@@ -1,7 +1,7 @@
require 'isolation/abstract_unit'
class ConsoleTest < Test::Unit::TestCase
- include ActiveSupport::Testing::Isolation
+ include ActiveSupport::Testing::Isolation
def setup
build_app
@@ -14,16 +14,15 @@ class ConsoleTest < Test::Unit::TestCase
end
def test_app_method_should_return_integration_session
+ TestHelpers::Rack.send :remove_method, :app
load_environment
console_session = app
- assert_not_nil console_session
assert_instance_of ActionDispatch::Integration::Session, console_session
end
def test_new_session_should_return_integration_session
load_environment
session = new_session
- assert_not_nil session
assert_instance_of ActionDispatch::Integration::Session, session
end
diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb
index d258625f42..551e966c85 100644
--- a/railties/test/application/generators_test.rb
+++ b/railties/test/application/generators_test.rb
@@ -69,7 +69,7 @@ module ApplicationTests
assert_equal :rspec, Rails::Generators.options[:rails][:test_framework]
assert_equal "-w", Rails::Generators.aliases[:rails][:test_framework]
assert_equal Hash[:shoulda => :test_unit], Rails::Generators.fallbacks
- assert_equal ["#{app_path}/lib/templates", "some/where"], Rails::Generators.templates_path
+ assert_equal ["some/where"], Rails::Generators.templates_path
end
test "generators no color on initialization" do
diff --git a/railties/test/application/middleware/best_practices_test.rb b/railties/test/application/middleware/best_practices_test.rb
new file mode 100644
index 0000000000..5b722e7510
--- /dev/null
+++ b/railties/test/application/middleware/best_practices_test.rb
@@ -0,0 +1,26 @@
+require 'isolation/abstract_unit'
+
+module ApplicationTests
+ class BestPracticesTest < Test::Unit::TestCase
+ include ActiveSupport::Testing::Isolation
+
+ def setup
+ build_app
+ boot_rails
+ require 'rack/test'
+ extend Rack::Test::Methods
+ simple_controller
+ end
+
+ test "simple controller in production mode returns best standards" do
+ get '/foo'
+ assert_equal "IE=Edge,chrome=1", last_response.headers["X-UA-Compatible"]
+ end
+
+ test "simple controller in development mode leaves out Chrome" do
+ app("development")
+ get "/foo"
+ assert_equal "IE=Edge", last_response.headers["X-UA-Compatible"]
+ end
+ end
+end
diff --git a/railties/test/application/middleware/cache_test.rb b/railties/test/application/middleware/cache_test.rb
index 5675cebfd9..f582ed0e42 100644
--- a/railties/test/application/middleware/cache_test.rb
+++ b/railties/test/application/middleware/cache_test.rb
@@ -11,18 +11,6 @@ module ApplicationTests
extend Rack::Test::Methods
end
- def app(env = "production")
- old_env = ENV["RAILS_ENV"]
-
- @app ||= begin
- ENV["RAILS_ENV"] = env
- require "#{app_path}/config/environment"
- Rails.application
- end
- ensure
- ENV["RAILS_ENV"] = old_env
- end
-
def simple_controller
controller :expires, <<-RUBY
class ExpiresController < ApplicationController
diff --git a/railties/test/application/middleware/remote_ip_test.rb b/railties/test/application/middleware/remote_ip_test.rb
new file mode 100644
index 0000000000..f28302d70a
--- /dev/null
+++ b/railties/test/application/middleware/remote_ip_test.rb
@@ -0,0 +1,63 @@
+require 'isolation/abstract_unit'
+
+module ApplicationTests
+ class RemoteIpTest < Test::Unit::TestCase
+ include ActiveSupport::Testing::Isolation
+
+ def setup
+ build_app
+ boot_rails
+ FileUtils.rm_rf "#{app_path}/config/environments"
+ end
+
+ def app
+ @app ||= Rails.application
+ end
+
+ def remote_ip(env = {})
+ remote_ip = nil
+ env = Rack::MockRequest.env_for("/").merge(env).merge!(
+ 'action_dispatch.show_exceptions' => false,
+ 'action_dispatch.secret_token' => 'b3c631c314c0bbca50c1b2843150fe33'
+ )
+
+ endpoint = Proc.new do |e|
+ remote_ip = ActionDispatch::Request.new(e).remote_ip
+ [200, {}, ["Hello"]]
+ end
+
+ Rails.application.middleware.build(endpoint).call(env)
+ remote_ip
+ end
+
+ test "remote_ip works" do
+ make_basic_app
+ assert_equal "1.1.1.1", remote_ip("REMOTE_ADDR" => "1.1.1.1")
+ end
+
+ test "checks IP spoofing by default" do
+ make_basic_app
+ assert_raises(ActionDispatch::RemoteIp::IpSpoofAttackError) do
+ remote_ip("HTTP_X_FORWARDED_FOR" => "1.1.1.1", "HTTP_CLIENT_IP" => "1.1.1.2")
+ end
+ end
+
+ test "can disable IP spoofing check" do
+ make_basic_app do |app|
+ app.config.action_dispatch.ip_spoofing_check = false
+ end
+
+ assert_nothing_raised(ActionDispatch::RemoteIp::IpSpoofAttackError) do
+ assert_equal "1.1.1.2", remote_ip("HTTP_X_FORWARDED_FOR" => "1.1.1.1", "HTTP_CLIENT_IP" => "1.1.1.2")
+ end
+ end
+
+ test "the user can set trusted proxies" do
+ make_basic_app do |app|
+ app.config.action_dispatch.trusted_proxies = /^4\.2\.42\.42$/
+ end
+
+ assert_equal "1.1.1.1", remote_ip("REMOTE_ADDR" => "4.2.42.42,1.1.1.1")
+ end
+ end
+end
diff --git a/railties/test/application/middleware/sendfile_test.rb b/railties/test/application/middleware/sendfile_test.rb
new file mode 100644
index 0000000000..0128261cd4
--- /dev/null
+++ b/railties/test/application/middleware/sendfile_test.rb
@@ -0,0 +1,56 @@
+require 'isolation/abstract_unit'
+
+module ApplicationTests
+ class SendfileTest < Test::Unit::TestCase
+ include ActiveSupport::Testing::Isolation
+
+ def setup
+ build_app
+ boot_rails
+ FileUtils.rm_rf "#{app_path}/config/environments"
+ end
+
+ def app
+ @app ||= Rails.application
+ end
+
+ define_method :simple_controller do
+ class ::OmgController < ActionController::Base
+ def index
+ send_file __FILE__
+ end
+ end
+ end
+
+ # x_sendfile_header middleware
+ test "config.action_dispatch.x_sendfile_header defaults to ''" do
+ make_basic_app
+ simple_controller
+
+ get "/"
+ assert_equal File.read(__FILE__), last_response.body
+ end
+
+ test "config.action_dispatch.x_sendfile_header can be set" do
+ make_basic_app do |app|
+ app.config.action_dispatch.x_sendfile_header = "X-Sendfile"
+ end
+
+ simple_controller
+
+ get "/"
+ assert_equal File.expand_path(__FILE__), last_response.headers["X-Sendfile"]
+ end
+
+ test "config.action_dispatch.x_sendfile_header is sent to Rack::Sendfile" do
+ make_basic_app do |app|
+ app.config.action_dispatch.x_sendfile_header = 'X-Lighttpd-Send-File'
+ end
+
+ simple_controller
+
+ get "/"
+ assert_equal File.expand_path(__FILE__), last_response.headers["X-Lighttpd-Send-File"]
+ end
+ end
+end
diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb
index f9b594eb33..173ac40b12 100644
--- a/railties/test/application/middleware_test.rb
+++ b/railties/test/application/middleware_test.rb
@@ -36,6 +36,8 @@ module ApplicationTests
"ActionDispatch::ParamsParser",
"Rack::MethodOverride",
"ActionDispatch::Head",
+ "Rack::ConditionalGet",
+ "Rack::ETag",
"ActionDispatch::BestStandardsSupport"
], middleware
end
@@ -45,27 +47,7 @@ module ApplicationTests
boot!
- assert_equal [
- "Rack::Cache",
- "ActionDispatch::Static",
- "Rack::Lock",
- "ActiveSupport::Cache::Strategy::LocalCache",
- "Rack::Runtime",
- "Rails::Rack::Logger",
- "ActionDispatch::ShowExceptions",
- "ActionDispatch::RemoteIp",
- "Rack::Sendfile",
- "ActionDispatch::Callbacks",
- "ActiveRecord::ConnectionAdapters::ConnectionManagement",
- "ActiveRecord::QueryCache",
- "ActionDispatch::Cookies",
- "ActionDispatch::Session::CookieStore",
- "ActionDispatch::Flash",
- "ActionDispatch::ParamsParser",
- "Rack::MethodOverride",
- "ActionDispatch::Head",
- "ActionDispatch::BestStandardsSupport"
- ], middleware
+ assert_equal "Rack::Cache", middleware.first
end
test "removing Active Record omits its middleware" do
@@ -129,81 +111,46 @@ module ApplicationTests
assert_equal "Rack::Config", middleware.first
end
- # x_sendfile_header middleware
- test "config.action_dispatch.x_sendfile_header defaults to ''" do
+ # ConditionalGet + Etag
+ test "conditional get + etag middlewares handle http caching based on body" do
make_basic_app
class ::OmgController < ActionController::Base
def index
- send_file __FILE__
- end
- end
-
- get "/"
- assert_equal File.read(__FILE__), last_response.body
- end
-
- test "config.action_dispatch.x_sendfile_header can be set" do
- make_basic_app do |app|
- app.config.action_dispatch.x_sendfile_header = "X-Sendfile"
- end
-
- class ::OmgController < ActionController::Base
- def index
- send_file __FILE__
+ if params[:nothing]
+ render :text => ""
+ else
+ render :text => "OMG"
+ end
end
end
- get "/"
- assert_equal File.expand_path(__FILE__), last_response.headers["X-Sendfile"]
- end
-
- test "config.action_dispatch.x_sendfile_header is sent to Rack::Sendfile" do
- make_basic_app do |app|
- app.config.action_dispatch.x_sendfile_header = 'X-Lighttpd-Send-File'
- end
-
- class ::OmgController < ActionController::Base
- def index
- send_file __FILE__
- end
- end
+ etag = "5af83e3196bf99f440f31f2e1a6c9afe".inspect
get "/"
- assert_equal File.expand_path(__FILE__), last_response.headers["X-Lighttpd-Send-File"]
- end
-
- # remote_ip tests
- test "remote_ip works" do
- make_basic_app
- assert_equal "1.1.1.1", remote_ip("REMOTE_ADDR" => "1.1.1.1")
- end
-
- test "checks IP spoofing by default" do
- make_basic_app
- assert_raises(ActionDispatch::RemoteIp::IpSpoofAttackError) do
- remote_ip("HTTP_X_FORWARDED_FOR" => "1.1.1.1", "HTTP_CLIENT_IP" => "1.1.1.2")
- end
- end
-
- test "can disable IP spoofing check" do
- make_basic_app do |app|
- app.config.action_dispatch.ip_spoofing_check = false
- end
-
- assert_nothing_raised(ActionDispatch::RemoteIp::IpSpoofAttackError) do
- assert_equal "1.1.1.2", remote_ip("HTTP_X_FORWARDED_FOR" => "1.1.1.1", "HTTP_CLIENT_IP" => "1.1.1.2")
- end
- end
-
- test "the user can set trusted proxies" do
- make_basic_app do |app|
- app.config.action_dispatch.trusted_proxies = /^4\.2\.42\.42$/
- end
-
- assert_equal "1.1.1.1", remote_ip("REMOTE_ADDR" => "4.2.42.42,1.1.1.1")
- end
-
+ assert_equal 200, last_response.status
+ assert_equal "OMG", last_response.body
+ assert_equal "text/html; charset=utf-8", last_response.headers["Content-Type"]
+ assert_equal "max-age=0, private, must-revalidate", last_response.headers["Cache-Control"]
+ assert_equal etag, last_response.headers["Etag"]
+
+ get "/", {}, "HTTP_IF_NONE_MATCH" => etag
+ assert_equal 304, last_response.status
+ assert_equal "", last_response.body
+ assert_equal nil, last_response.headers["Content-Type"]
+ assert_equal "max-age=0, private, must-revalidate", last_response.headers["Cache-Control"]
+ assert_equal etag, last_response.headers["Etag"]
+
+ get "/?nothing=true"
+ puts last_response.body
+ assert_equal 200, last_response.status
+ assert_equal "", last_response.body
+ assert_equal "text/html; charset=utf-8", last_response.headers["Content-Type"]
+ assert_equal "no-cache", last_response.headers["Cache-Control"]
+ assert_equal nil, last_response.headers["Etag"]
+ end
+
+ # Show exceptions middleware
test "show exceptions middleware filter backtrace before logging" do
my_middleware = Struct.new(:app) do
def call(env)
@@ -232,21 +179,5 @@ module ApplicationTests
def middleware
AppTemplate::Application.middleware.map(&:klass).map(&:name)
end
-
- def remote_ip(env = {})
- remote_ip = nil
- env = Rack::MockRequest.env_for("/").merge(env).merge!(
- 'action_dispatch.show_exceptions' => false,
- 'action_dispatch.secret_token' => 'b3c631c314c0bbca50c1b2843150fe33'
- )
-
- endpoint = Proc.new do |e|
- remote_ip = ActionDispatch::Request.new(e).remote_ip
- [200, {}, ["Hello"]]
- end
-
- Rails.application.middleware.build(endpoint).call(env)
- remote_ip
- end
end
end
diff --git a/railties/test/application/paths_test.rb b/railties/test/application/paths_test.rb
index c98b11556b..b1ff6e9cb1 100644
--- a/railties/test/application/paths_test.rb
+++ b/railties/test/application/paths_test.rb
@@ -25,7 +25,7 @@ module ApplicationTests
end
def assert_path(paths, *dir)
- assert_equal [root(*dir)], paths.paths
+ assert_equal [root(*dir)], paths.expanded
end
def assert_in_load_path(*path)
@@ -37,20 +37,20 @@ module ApplicationTests
end
test "booting up Rails yields a valid paths object" do
- assert_path @paths.app.models, "app", "models"
- assert_path @paths.app.helpers, "app", "helpers"
- 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", "en.yml"
- assert_path @paths.config.environment, "config", "environment.rb"
- assert_path @paths.config.environments, "config", "environments", "development.rb"
+ assert_path @paths["app/models"], "app/models"
+ assert_path @paths["app/helpers"], "app/helpers"
+ 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/en.yml"
+ assert_path @paths["config/environment"], "config/environment.rb"
+ assert_path @paths["config/environments"], "config/environments/development.rb"
- assert_equal root("app", "controllers"), @paths.app.controllers.to_a.first
+ assert_equal root("app", "controllers"), @paths["app/controllers"].expanded.first
end
test "booting up Rails yields a list of paths that are eager" do
diff --git a/railties/test/application/routing_test.rb b/railties/test/application/routing_test.rb
index 416a5de5b0..62589c998d 100644
--- a/railties/test/application/routing_test.rb
+++ b/railties/test/application/routing_test.rb
@@ -11,34 +11,6 @@ module ApplicationTests
extend Rack::Test::Methods
end
- def app(env = "production")
- old_env = ENV["RAILS_ENV"]
-
- @app ||= begin
- ENV["RAILS_ENV"] = env
- require "#{app_path}/config/environment"
- Rails.application
- end
- ensure
- ENV["RAILS_ENV"] = old_env
- end
-
- def simple_controller
- controller :foo, <<-RUBY
- class FooController < ApplicationController
- def index
- render :text => "foo"
- end
- end
- RUBY
-
- app_file 'config/routes.rb', <<-RUBY
- AppTemplate::Application.routes.draw do
- match ':controller(/:action)'
- end
- RUBY
- end
-
test "rails/info/properties in development" do
app("development")
get "/rails/info/properties"
@@ -58,21 +30,6 @@ module ApplicationTests
assert_equal 'foo', last_response.body
end
- test "simple controller in production mode returns best standards" do
- simple_controller
-
- get '/foo'
- assert_equal "IE=Edge,chrome=1", last_response.headers["X-UA-Compatible"]
- end
-
- test "simple controller in development mode leaves out Chrome" do
- simple_controller
- app("development")
-
- get "/foo"
- assert_equal "IE=Edge", last_response.headers["X-UA-Compatible"]
- end
-
test "simple controller with helper" do
controller :foo, <<-RUBY
class FooController < ApplicationController
@@ -177,7 +134,7 @@ module ApplicationTests
assert_equal 'admin::foo', last_response.body
end
- def test_reloads_appended_route_blocks
+ test "routes appending blocks" do
app_file 'config/routes.rb', <<-RUBY
AppTemplate::Application.routes.draw do
match ':controller#:action'
@@ -246,9 +203,12 @@ module ApplicationTests
test 'routes are loaded just after initialization' do
require "#{app_path}/config/application"
- app_file 'config/routes.rb', <<-RUBY
- InitializeRackApp = lambda { |env| [200, {}, ["InitializeRackApp"]] }
+ # Create the rack app just inside after initialize callback
+ ActiveSupport.on_load(:after_initialize) do
+ ::InitializeRackApp = lambda { |env| [200, {}, ["InitializeRackApp"]] }
+ end
+ app_file 'config/routes.rb', <<-RUBY
AppTemplate::Application.routes.draw do
match 'foo', :to => ::InitializeRackApp
end
@@ -258,7 +218,14 @@ module ApplicationTests
assert_equal "InitializeRackApp", last_response.body
end
- test 'resource routing with irrigular inflection' do
+ test 'reload_routes! is part of Rails.application API' do
+ app("development")
+ assert_nothing_raised do
+ Rails.application.reload_routes!
+ end
+ end
+
+ test 'resource routing with irregular inflection' do
app_file 'config/initializers/inflection.rb', <<-RUBY
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'yazi', 'yazilar'
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index 3653b067c8..51277b805b 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -165,9 +165,13 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_file "Gemfile", /^gem\s+["']mysql2["']$/
end
- def test_config_database_is_not_added_if_skip_active_record_is_given
+ def test_generator_if_skip_active_record_is_given
run_generator [destination_root, "--skip-active-record"]
assert_no_file "config/database.yml"
+ assert_file "test/test_helper.rb" do |helper_content|
+ assert_no_match /fixtures :all/, helper_content
+ end
+ assert_file "test/performance/browsing_test.rb"
end
def test_active_record_is_removed_from_frameworks_if_skip_active_record_is_given
diff --git a/railties/test/generators/generated_attribute_test.rb b/railties/test/generators/generated_attribute_test.rb
index 272e179fe3..064546a3f3 100644
--- a/railties/test/generators/generated_attribute_test.rb
+++ b/railties/test/generators/generated_attribute_test.rb
@@ -117,7 +117,7 @@ class GeneratedAttributeTest < Rails::Generators::TestCase
def test_missing_type_raises_exception
assert_raise Thor::Error do
- create_generated_attribute(:'', 'title')
+ create_generated_attribute('', 'title')
end
end
end
diff --git a/railties/test/generators/mailer_generator_test.rb b/railties/test/generators/mailer_generator_test.rb
index 450dec7716..f4fdc46328 100644
--- a/railties/test/generators/mailer_generator_test.rb
+++ b/railties/test/generators/mailer_generator_test.rb
@@ -59,6 +59,15 @@ class MailerGeneratorTest < Rails::Generators::TestCase
assert_match /haml \[not found\]/, content
end
+ def test_mailer_with_namedspaced_mailer
+ run_generator ["Farm::Animal", "moos"]
+ assert_file "app/mailers/farm/animal.rb" do |mailer|
+ assert_match /class Farm::Animal < ActionMailer::Base/, mailer
+ assert_match /en\.farm\.animal\.moos\.subject/, mailer
+ end
+ assert_file "app/views/farm/animal/moos.text.erb"
+ end
+
def test_actions_are_turned_into_methods
run_generator
diff --git a/railties/test/generators/namespaced_generators_test.rb b/railties/test/generators/namespaced_generators_test.rb
index 38b95a49ac..d1190fd17d 100644
--- a/railties/test/generators/namespaced_generators_test.rb
+++ b/railties/test/generators/namespaced_generators_test.rb
@@ -6,14 +6,14 @@ require 'rails/generators/mailer/mailer_generator'
class NamespacedGeneratorTestCase < Rails::Generators::TestCase
def setup
- TestApp::Application.namespace(TestApp)
+ TestApp::Application.isolate_namespace(TestApp)
end
def teardown
if TestApp.respond_to?(:_railtie)
TestApp.singleton_class.send(:undef_method, :_railtie)
TestApp.singleton_class.send(:undef_method, :table_name_prefix)
- TestApp::Application.namespaced = false
+ TestApp::Application.isolated = false
end
end
end
diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb
index 79c7735019..3b03e4eb3d 100644
--- a/railties/test/isolation/abstract_unit.rb
+++ b/railties/test/isolation/abstract_unit.rb
@@ -45,6 +45,17 @@ module TestHelpers
end
module Rack
+ def app(env = "production")
+ old_env = ENV["RAILS_ENV"]
+ @app ||= begin
+ ENV["RAILS_ENV"] = env
+ require "#{app_path}/config/environment"
+ Rails.application
+ end
+ ensure
+ ENV["RAILS_ENV"] = old_env
+ end
+
def extract_body(response)
"".tap do |body|
response[2].each {|chunk| body << chunk }
@@ -124,6 +135,22 @@ module TestHelpers
extend ::Rack::Test::Methods
end
+ def simple_controller
+ controller :foo, <<-RUBY
+ class FooController < ApplicationController
+ def index
+ render :text => "foo"
+ end
+ end
+ RUBY
+
+ app_file 'config/routes.rb', <<-RUBY
+ AppTemplate::Application.routes.draw do
+ match ':controller(/:action)'
+ end
+ RUBY
+ end
+
class Bukkit
attr_reader :path
diff --git a/railties/test/paths_test.rb b/railties/test/paths_test.rb
index 80fae8c543..6e4e3446b3 100644
--- a/railties/test/paths_test.rb
+++ b/railties/test/paths_test.rb
@@ -20,234 +20,264 @@ class PathsTest < ActiveSupport::TestCase
test "a paths object initialized with nil can be updated" do
root = Rails::Paths::Root.new(nil)
- root.app = "app"
+ root.add "app"
root.path = "/root"
- assert_equal ["/root/app"], root.app.to_a
+ assert_equal ["app"], root["app"]
+ assert_equal ["/root/app"], root["app"].to_a
end
test "creating a root level path" do
- @root.app = "/foo/bar"
- assert_equal ["/foo/bar"], @root.app.to_a
+ @root.add "app"
+ assert_equal ["/foo/bar/app"], @root["app"].to_a
+ end
+
+ test "creating a root level path with options" do
+ @root.add "app", :with => "/foo/bar"
+ assert_equal ["/foo/bar"], @root["app"].to_a
end
test "raises exception if root path never set" do
root = Rails::Paths::Root.new(nil)
- root.app = "app"
+ root.add "app"
assert_raises RuntimeError do
- root.app.to_a
+ root["app"].to_a
end
end
- test "creating a root level path without assignment" do
- @root.app "/foo/bar"
- assert_equal ["/foo/bar"], @root.app.to_a
- end
-
- test "trying to access a path that does not exist raises NoMethodError" do
- assert_raises(NoMethodError) { @root.app }
- end
-
- test "relative paths are relative to the paths root" do
- @root.app = "app"
- assert_equal ["/foo/bar/app"], @root.app.to_a
- end
-
- test "relative paths are relative to the paths root without assignment" do
- @root.app "app"
- assert_equal ["/foo/bar/app"], @root.app.to_a
- end
-
test "creating a child level path" do
- @root.app = "/foo/bar"
- @root.app.models = "/foo/bar/baz"
- assert_equal ["/foo/bar/baz"], @root.app.models.to_a
+ @root.add "app"
+ @root.add "app/models"
+ assert_equal ["/foo/bar/app/models"], @root["app/models"].to_a
end
- test "creating a child level path without assignment" do
- @root.app = "/foo/bar"
- @root.app.models "/foo/bar/baz"
- assert_equal ["/foo/bar/baz"], @root.app.models.to_a
+ test "creating a child level path with option" do
+ @root.add "app"
+ @root.add "app/models", :with => "/foo/bar/baz"
+ assert_equal ["/foo/bar/baz"], @root["app/models"].to_a
end
test "child level paths are relative from the root" do
- @root.app = "/app"
- @root.app.models = "baz"
-
- assert_equal ["/foo/bar/baz"], @root.app.models.to_a
+ @root.add "app"
+ @root.add "app/models", :with => "baz"
+ assert_equal ["/foo/bar/baz"], @root["app/models"].to_a
end
test "adding multiple physical paths as an array" do
- @root.app = ["/app", "/app2"]
- assert_equal ["/app", "/app2"], @root.app.to_a
- end
-
- test "adding multiple physical paths as an array without assignment" do
- @root.app "/app", "/app2"
- assert_equal ["/app", "/app2"], @root.app.to_a
+ @root.add "app", :with => ["/app", "/app2"]
+ assert_equal ["/app", "/app2"], @root["app"].to_a
end
test "adding multiple physical paths using #push" do
- @root.app = "/app"
- @root.app.push "/app2"
- assert_equal ["/app", "/app2"], @root.app.to_a
+ @root.add "app"
+ @root["app"].push "app2"
+ assert_equal ["/foo/bar/app", "/foo/bar/app2"], @root["app"].to_a
end
test "adding multiple physical paths using <<" do
- @root.app = "/app"
- @root.app << "/app2"
- assert_equal ["/app", "/app2"], @root.app.to_a
+ @root.add "app"
+ @root["app"] << "app2"
+ assert_equal ["/foo/bar/app", "/foo/bar/app2"], @root["app"].to_a
end
test "adding multiple physical paths using concat" do
- @root.app = "/app"
- @root.app.concat ["/app2", "/app3"]
- assert_equal ["/app", "/app2", "/app3"], @root.app.to_a
+ @root.add "app"
+ @root["app"].concat ["app2", "/app3"]
+ assert_equal ["/foo/bar/app", "/foo/bar/app2", "/app3"], @root["app"].to_a
end
test "adding multiple physical paths using #unshift" do
- @root.app = "/app"
- @root.app.unshift "/app2"
- assert_equal ["/app2", "/app"], @root.app.to_a
+ @root.add "app"
+ @root["app"].unshift "app2"
+ assert_equal ["/foo/bar/app2", "/foo/bar/app"], @root["app"].to_a
end
test "the root can only have one physical path" do
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"]}
- assert_raise(RuntimeError) { @root << "/biz" }
end
test "it is possible to add a path that should be autoloaded only once" do
- @root.app = "/app"
- @root.app.autoload_once!
- assert @root.app.autoload_once?
- assert @root.autoload_once.include?(@root.app.paths.first)
+ @root.add "app", :with => "/app"
+ @root["app"].autoload_once!
+ assert @root["app"].autoload_once?
+ assert @root.autoload_once.include?(@root["app"].expanded.first)
end
test "it is possible to remove a path that should be autoloaded only once" do
- @root.app = "/app"
- @root.app.autoload_once!
- assert @root.app.autoload_once?
+ @root["app"] = "/app"
+ @root["app"].autoload_once!
+ assert @root["app"].autoload_once?
- @root.app.skip_autoload_once!
- assert !@root.app.autoload_once?
- assert !@root.autoload_once.include?(@root.app.paths.first)
+ @root["app"].skip_autoload_once!
+ assert !@root["app"].autoload_once?
+ assert !@root.autoload_once.include?(@root["app"].expanded.first)
end
test "it is possible to add a path without assignment and specify it should be loaded only once" do
- @root.app "/app", :autoload_once => true
- assert @root.app.autoload_once?
+ @root.add "app", :with => "/app", :autoload_once => true
+ assert @root["app"].autoload_once?
assert @root.autoload_once.include?("/app")
end
test "it is possible to add multiple paths without assignment and specify it should be loaded only once" do
- @root.app "/app", "/app2", :autoload_once => true
- assert @root.app.autoload_once?
+ @root.add "app", :with => ["/app", "/app2"], :autoload_once => true
+ assert @root["app"].autoload_once?
assert @root.autoload_once.include?("/app")
assert @root.autoload_once.include?("/app2")
end
test "making a path autoload_once more than once only includes it once in @root.load_once" do
- @root.app = "/app"
- @root.app.autoload_once!
- @root.app.autoload_once!
- assert_equal 1, @root.autoload_once.select {|p| p == @root.app.paths.first }.size
+ @root["app"] = "/app"
+ @root["app"].autoload_once!
+ @root["app"].autoload_once!
+ assert_equal 1, @root.autoload_once.select {|p| p == @root["app"].expanded.first }.size
end
test "paths added to a load_once path should be added to the autoload_once collection" do
- @root.app = "/app"
- @root.app.autoload_once!
- @root.app << "/app2"
+ @root["app"] = "/app"
+ @root["app"].autoload_once!
+ @root["app"] << "/app2"
assert_equal 2, @root.autoload_once.size
end
test "it is possible to mark a path as eager loaded" do
- @root.app = "/app"
- @root.app.eager_load!
- assert @root.app.eager_load?
- assert @root.eager_load.include?(@root.app.paths.first)
+ @root["app"] = "/app"
+ @root["app"].eager_load!
+ assert @root["app"].eager_load?
+ assert @root.eager_load.include?(@root["app"].to_a.first)
end
test "it is possible to skip a path from eager loading" do
- @root.app = "/app"
- @root.app.eager_load!
- assert @root.app.eager_load?
+ @root["app"] = "/app"
+ @root["app"].eager_load!
+ assert @root["app"].eager_load?
- @root.app.skip_eager_load!
- assert !@root.app.eager_load?
- assert !@root.eager_load.include?(@root.app.paths.first)
+ @root["app"].skip_eager_load!
+ assert !@root["app"].eager_load?
+ assert !@root.eager_load.include?(@root["app"].to_a.first)
end
test "it is possible to add a path without assignment and mark it as eager" do
- @root.app "/app", :eager_load => true
- assert @root.app.eager_load?
+ @root.add "app", :with => "/app", :eager_load => true
+ assert @root["app"].eager_load?
assert @root.eager_load.include?("/app")
end
test "it is possible to add multiple paths without assignment and mark them as eager" do
- @root.app "/app", "/app2", :eager_load => true
- assert @root.app.eager_load?
+ @root.add "app", :with => ["/app", "/app2"], :eager_load => true
+ assert @root["app"].eager_load?
assert @root.eager_load.include?("/app")
assert @root.eager_load.include?("/app2")
end
test "it is possible to create a path without assignment and mark it both as eager and load once" do
- @root.app "/app", :eager_load => true, :autoload_once => true
- assert @root.app.eager_load?
- assert @root.app.autoload_once?
+ @root.add "app", :with => "/app", :eager_load => true, :autoload_once => true
+ assert @root["app"].eager_load?
+ assert @root["app"].autoload_once?
assert @root.eager_load.include?("/app")
assert @root.autoload_once.include?("/app")
end
test "making a path eager more than once only includes it once in @root.eager_paths" do
- @root.app = "/app"
- @root.app.eager_load!
- @root.app.eager_load!
- assert_equal 1, @root.eager_load.select {|p| p == @root.app.paths.first }.size
+ @root["app"] = "/app"
+ @root["app"].eager_load!
+ @root["app"].eager_load!
+ assert_equal 1, @root.eager_load.select {|p| p == @root["app"].expanded.first }.size
end
test "paths added to a eager_load path should be added to the eager_load collection" do
- @root.app = "/app"
- @root.app.eager_load!
- @root.app << "/app2"
+ @root["app"] = "/app"
+ @root["app"].eager_load!
+ @root["app"] << "/app2"
assert_equal 2, @root.eager_load.size
end
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
+ @root["app"] = "/app"
+ @root["app"].glob = "*.rb"
+ assert_equal "*.rb", @root["app"].glob
end
test "it should be possible to override a path's default glob without assignment" do
- @root.app "/app", :glob => "*.rb"
- assert_equal "*.rb", @root.app.glob
+ @root.add "app", :with => "/app", :glob => "*.rb"
+ assert_equal "*.rb", @root["app"].glob
end
test "a path can be added to the load path" do
- @root.app = "app"
- @root.app.load_path!
- @root.app.models = "app/models"
+ @root["app"] = "app"
+ @root["app"].load_path!
+ @root["app/models"] = "app/models"
assert_equal ["/foo/bar/app"], @root.load_paths
end
test "a path can be added to the load path on creation" do
- @root.app "/app", :load_path => true
- assert @root.app.load_path?
+ @root.add "app", :with => "/app", :load_path => true
+ assert @root["app"].load_path?
assert_equal ["/app"], @root.load_paths
end
test "a path can be marked as autoload path" do
- @root.app = "app"
- @root.app.autoload!
- @root.app.models = "app/models"
+ @root["app"] = "app"
+ @root["app"].autoload!
+ @root["app/models"] = "app/models"
assert_equal ["/foo/bar/app"], @root.autoload_paths
end
test "a path can be marked as autoload on creation" do
- @root.app "/app", :autoload => true
- assert @root.app.autoload?
+ @root.add "app", :with => "/app", :autoload => true
+ assert @root["app"].autoload?
assert_equal ["/app"], @root.autoload_paths
end
+
+ # Deprecated API tests
+
+ test "reading a root level path with assignment" do
+ @root.add "app"
+ assert_deprecated do
+ assert_equal ["/foo/bar/app"], @root.app.to_a
+ end
+ end
+
+ test "creating a root level path with assignment" do
+ assert_deprecated do
+ @root.app = "/foo/bar"
+ end
+ assert_equal ["/foo/bar"], @root["app"].to_a
+ end
+
+ test "creating a root level path without assignment" do
+ assert_deprecated do
+ @root.app "/foo/bar"
+ end
+ assert_equal ["/foo/bar"], @root["app"].to_a
+ end
+
+ test "reading a nested level path with assignment" do
+ @root.add "app"
+ @root.add "app/model"
+ assert_deprecated do
+ assert_equal ["/foo/bar/app/model"], @root.app.model.to_a
+ end
+ end
+
+ test "creating a nested level path with assignment" do
+ @root.add "app"
+ assert_deprecated do
+ @root.app.model = "/foo/bar"
+ end
+ assert_equal ["/foo/bar"], @root["app/model"].to_a
+ end
+
+ test "creating a nested level path without assignment" do
+ @root.add "app"
+ assert_deprecated do
+ @root.app.model "/foo/bar"
+ end
+ assert_equal ["/foo/bar"], @root["app/model"].to_a
+ end
+
+ test "trying to access a path that does not exist raises NoMethodError" do
+ assert_deprecated do
+ assert_raises(NoMethodError) { @root.app }
+ end
+ end
end
diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb
index a9dd7d4c1b..db74e41472 100644
--- a/railties/test/railties/engine_test.rb
+++ b/railties/test/railties/engine_test.rb
@@ -62,17 +62,18 @@ module RailtiesTest
def call(env)
response = @app.call(env)
- response[2].upcase!
+ response[2].each { |b| b.upcase! }
response
end
end
test "engine is a rack app and can have his own middleware stack" do
+ add_to_config("config.action_dispatch.show_exceptions = false")
+
@plugin.write "lib/bukkits.rb", <<-RUBY
class Bukkits
class Engine < ::Rails::Engine
- endpoint lambda { |env| [200, {'Content-Type' => 'text/html'}, 'Hello World'] }
-
+ endpoint lambda { |env| [200, {'Content-Type' => 'text/html'}, ['Hello World']] }
config.middleware.use ::RailtiesTest::EngineTest::Upcaser
end
end
@@ -89,7 +90,7 @@ module RailtiesTest
env = Rack::MockRequest.env_for("/bukkits")
response = Rails.application.call(env)
- assert_equal "HELLO WORLD", response[2]
+ assert_equal ["HELLO WORLD"], response[2]
end
test "it provides routes as default endpoint" do
@@ -102,7 +103,7 @@ module RailtiesTest
@plugin.write "config/routes.rb", <<-RUBY
Bukkits::Engine.routes.draw do
- match "/foo" => lambda { |env| [200, {'Content-Type' => 'text/html'}, 'foo'] }
+ match "/foo" => lambda { |env| [200, {'Content-Type' => 'text/html'}, ['foo']] }
end
RUBY
@@ -116,8 +117,7 @@ module RailtiesTest
env = Rack::MockRequest.env_for("/bukkits/foo")
response = Rails.application.call(env)
-
- assert_equal "foo", response[2]
+ assert_equal ["foo"], response[2]
end
test "engine can load its own plugins" do
@@ -379,22 +379,22 @@ module RailtiesTest
env = Rack::MockRequest.env_for("/foo")
response = Rails.application.call(env)
- assert_equal "Something... Something... Something...", response[2].body
+ assert_equal ["Something... Something... Something..."], response[2]
env = Rack::MockRequest.env_for("/foo/show")
response = Rails.application.call(env)
- assert_equal "/foo", response[2].body
+ assert_equal ["/foo"], response[2]
env = Rack::MockRequest.env_for("/foo/bar")
response = Rails.application.call(env)
- assert_equal "It's a bar.", response[2].body
+ assert_equal ["It's a bar."], response[2]
end
test "isolated engine should include only its own routes and helpers" do
@plugin.write "lib/bukkits.rb", <<-RUBY
module Bukkits
class Engine < ::Rails::Engine
- namespace Bukkits
+ isolate_namespace Bukkits
end
end
RUBY
@@ -488,30 +488,30 @@ module RailtiesTest
env = Rack::MockRequest.env_for("/bukkits/from_app")
response = AppTemplate::Application.call(env)
- assert_equal "false", response[2].body
+ assert_equal ["false"], response[2]
env = Rack::MockRequest.env_for("/bukkits/foo/show")
response = AppTemplate::Application.call(env)
- assert_equal "/bukkits/foo", response[2].body
+ assert_equal ["/bukkits/foo"], response[2]
env = Rack::MockRequest.env_for("/bukkits/foo")
response = AppTemplate::Application.call(env)
- assert_equal "Helped.", response[2].body
+ assert_equal ["Helped."], response[2]
env = Rack::MockRequest.env_for("/bukkits/routes_helpers_in_view")
response = AppTemplate::Application.call(env)
- assert_equal "/bukkits/foo, /bar", response[2].body
+ assert_equal ["/bukkits/foo, /bar"], response[2]
env = Rack::MockRequest.env_for("/bukkits/polymorphic_path_without_namespace")
response = AppTemplate::Application.call(env)
- assert_equal "/bukkits/posts/1", response[2].body
+ assert_equal ["/bukkits/posts/1"], response[2]
end
test "isolated engine should avoid namespace in names if that's possible" do
@plugin.write "lib/bukkits.rb", <<-RUBY
module Bukkits
class Engine < ::Rails::Engine
- namespace Bukkits
+ isolate_namespace Bukkits
end
end
RUBY
@@ -553,11 +553,11 @@ module RailtiesTest
end
RUBY
- @plugin.write "app/views/bukkits/posts/new.html.erb", <<-RUBY
+ @plugin.write "app/views/bukkits/posts/new.html.erb", <<-ERB
<%= form_for(Bukkits::Post.new) do |f| %>
<%= f.text_field :title %>
<% end %>
- RUBY
+ ERB
add_to_config("config.action_dispatch.show_exceptions = false")
@@ -572,7 +572,7 @@ module RailtiesTest
@plugin.write "lib/bukkits.rb", <<-RUBY
module Bukkits
class Engine < ::Rails::Engine
- namespace(Bukkits)
+ isolate_namespace(Bukkits)
end
end
RUBY
@@ -593,8 +593,8 @@ module RailtiesTest
@plugin.write "lib/bukkits.rb", <<-RUBY
module Bukkits
class Engine < ::Rails::Engine
- namespace(Bukkits)
- config.paths.public = "#{File.join(@plugin.path, "alternate_public")}"
+ isolate_namespace(Bukkits)
+ paths["public"] = "#{File.join(@plugin.path, "alternate_public")}"
end
end
RUBY
@@ -611,8 +611,8 @@ module RailtiesTest
@plugin.write "lib/bukkits.rb", <<-RUBY
module Bukkits
class Engine < ::Rails::Engine
- namespace(Bukkits)
- config.paths.public = "#{File.join(@plugin.path, "not_existing")}"
+ isolate_namespace(Bukkits)
+ paths["public"] = "#{File.join(@plugin.path, "not_existing")}"
end
end
RUBY
@@ -643,5 +643,104 @@ module RailtiesTest
Bukkits::Engine.load_seed
assert Bukkits::Engine.config.bukkits_seeds_loaded
end
+
+ test "using namespace more than once on one module should not overwrite _railtie method" do
+ @plugin.write "lib/bukkits.rb", <<-RUBY
+ module AppTemplate
+ class Engine < ::Rails::Engine
+ isolate_namespace(AppTemplate)
+ end
+ end
+ RUBY
+
+ add_to_config "isolate_namespace AppTemplate"
+
+ app_file "config/routes.rb", <<-RUBY
+ AppTemplate::Application.routes.draw do end
+ RUBY
+
+ boot_rails
+
+ assert_equal AppTemplate._railtie, AppTemplate::Engine
+ end
+
+ test "properly reload routes" do
+ # when routes are inside application class definition
+ # they should not be reloaded when engine's routes
+ # file has changed
+ add_to_config <<-RUBY
+ routes do
+ mount lambda{|env| [200, {}, ["foo"]]} => "/foo"
+ mount Bukkits::Engine => "/bukkits"
+ end
+ RUBY
+
+ FileUtils.rm(File.join(app_path, "config/routes.rb"))
+
+ @plugin.write "config/routes.rb", <<-RUBY
+ Bukkits::Engine.routes.draw do
+ mount lambda{|env| [200, {}, ["bar"]]} => "/bar"
+ end
+ RUBY
+
+ @plugin.write "lib/bukkits.rb", <<-RUBY
+ module Bukkits
+ class Engine < ::Rails::Engine
+ isolate_namespace(Bukkits)
+ end
+ end
+ RUBY
+
+ require 'rack/test'
+ extend Rack::Test::Methods
+
+ boot_rails
+
+ require "#{rails_root}/config/environment"
+ get "/foo"
+ assert_equal "foo", last_response.body
+
+ get "/bukkits/bar"
+ assert_equal "bar", last_response.body
+ end
+
+ test "setting generators for engine and overriding app generator's" do
+ @plugin.write "lib/bukkits.rb", <<-RUBY
+ module Bukkits
+ class Engine < ::Rails::Engine
+ config.generators do |g|
+ g.orm :datamapper
+ g.template_engine :haml
+ g.test_framework :rspec
+ end
+
+ config.app_generators do |g|
+ g.orm :mongoid
+ g.template_engine :liquid
+ g.test_framework :shoulda
+ end
+ end
+ end
+ RUBY
+
+ add_to_config <<-RUBY
+ config.generators do |g|
+ g.test_framework :test_unit
+ end
+ RUBY
+
+ boot_rails
+ require "#{rails_root}/config/environment"
+
+ app_generators = Rails.application.config.generators.options[:rails]
+ assert_equal :mongoid , app_generators[:orm]
+ assert_equal :liquid , app_generators[:template_engine]
+ assert_equal :test_unit, app_generators[:test_framework]
+
+ generators = Bukkits::Engine.config.generators.options[:rails]
+ assert_equal :datamapper, generators[:orm]
+ assert_equal :haml , generators[:template_engine]
+ assert_equal :rspec , generators[:test_framework]
+ end
end
end
diff --git a/railties/test/railties/mounted_engine_test.rb b/railties/test/railties/mounted_engine_test.rb
index b52ced92ec..47a4753e78 100644
--- a/railties/test/railties/mounted_engine_test.rb
+++ b/railties/test/railties/mounted_engine_test.rb
@@ -49,7 +49,7 @@ module ApplicationTests
@plugin.write "lib/blog.rb", <<-RUBY
module Blog
class Engine < ::Rails::Engine
- namespace(Blog)
+ isolate_namespace(Blog)
end
end
RUBY
diff --git a/railties/test/railties/plugin_test.rb b/railties/test/railties/plugin_test.rb
index bae05d6978..c15ac05103 100644
--- a/railties/test/railties/plugin_test.rb
+++ b/railties/test/railties/plugin_test.rb
@@ -110,7 +110,7 @@ module RailtiesTest
boot_rails
rescue Exception => e
rescued = true
- assert_equal '"bukkits" is a Railtie/Engine and cannot be installed as plugin', e.message
+ assert_equal '"bukkits" is a Railtie/Engine and cannot be installed as a plugin', e.message
end
assert rescued, "Expected boot rails to fail"
diff --git a/railties/test/railties/railtie_test.rb b/railties/test/railties/railtie_test.rb
index 406d5d764f..6d194eecba 100644
--- a/railties/test/railties/railtie_test.rb
+++ b/railties/test/railties/railtie_test.rb
@@ -103,6 +103,30 @@ module RailtiesTest
assert $ran_block
end
+ test "rake_tasks block defined in superclass of railtie is also executed" do
+ $ran_block = []
+
+ class Rails::Railtie
+ rake_tasks do
+ $ran_block << railtie_name
+ end
+ end
+
+ class MyTie < Rails::Railtie
+ railtie_name "my_tie"
+ end
+
+ require "#{app_path}/config/environment"
+
+ assert_equal [], $ran_block
+ require 'rake'
+ require 'rake/testtask'
+ require 'rake/rdoctask'
+
+ AppTemplate::Application.load_tasks
+ assert $ran_block.include?("my_tie")
+ end
+
test "generators block is executed when MyApp.load_generators is called" do
$ran_block = false
diff --git a/railties/test/railties/shared_tests.rb b/railties/test/railties/shared_tests.rb
index 9b62f88fd7..b1d7580dff 100644
--- a/railties/test/railties/shared_tests.rb
+++ b/railties/test/railties/shared_tests.rb
@@ -21,6 +21,11 @@ module RailtiesTest
end
RUBY
+ @plugin.write "db/migrate/3_create_sessions.rb", <<-RUBY
+ class CreateSessions < ActiveRecord::Migration
+ end
+ RUBY
+
app_file "db/migrate/1_create_sessions.rb", <<-RUBY
class CreateSessions < ActiveRecord::Migration
end
@@ -38,24 +43,26 @@ module RailtiesTest
add_to_config "ActiveRecord::Base.timestamped_migrations = false"
Dir.chdir(app_path) do
- output = `rake railties:copy_migrations FROM=bukkits`
+ output = `rake bukkits:install:migrations 2>&1`
- assert File.exists?("#{app_path}/db/migrate/2_create_users.bukkits.rb")
- assert File.exists?("#{app_path}/db/migrate/3_add_last_name_to_users.bukkits.rb")
- assert_match /2_create_users/, output
- assert_match /3_add_last_name_to_users/, output
+ assert File.exists?("#{app_path}/db/migrate/2_create_users.rb")
+ assert File.exists?("#{app_path}/db/migrate/3_add_last_name_to_users.rb")
+ assert_match /Copied migration 2_create_users.rb from bukkits/, output
+ assert_match /Copied migration 3_add_last_name_to_users.rb from bukkits/, output
+ assert_match /WARNING: Migration 3_create_sessions.rb from bukkits has been skipped/, output
assert_equal 3, Dir["#{app_path}/db/migrate/*.rb"].length
- output = `rake railties:copy_migrations`
+ output = `rake railties:install:migrations 2>&1`
- assert File.exists?("#{app_path}/db/migrate/4_create_yaffles.acts_as_yaffle.rb")
- assert_match /4_create_yaffles/, output
+ assert File.exists?("#{app_path}/db/migrate/4_create_yaffles.rb")
+ assert_match /WARNING: Migration 3_create_sessions.rb from bukkits has been skipped/, output
+ assert_match /Copied migration 4_create_yaffles.rb from acts_as_yaffle/, output
+ assert_no_match /2_create_users/, output
migrations_count = Dir["#{app_path}/db/migrate/*.rb"].length
- output = `rake railties:copy_migrations`
+ output = `rake railties:install:migrations 2>&1`
assert_equal migrations_count, Dir["#{app_path}/db/migrate/*.rb"].length
- assert_match /No migrations were copied/, output
end
end