Navigation Menu

Skip to content

Commit

Permalink
Removing Metal from Rails 3.
Browse files Browse the repository at this point in the history
If you have existing Metals, you have a few options:
* if your metal behaves like a middleware, add it to the
  middleware stack via config.middleware.use. You can use
  methods on the middleware stack to control exactly where
  it should go
* if it behaves like a Rack endpoint, you can link to it
  in the router. This will result in more optimal routing
  time, and allows you to remove code in your endpoint
  that matches specific URLs in favor of the more powerful
  handling in the router itself.

For the future, you can use ActionController::Metal to get
a very fast controller with the ability to opt-in to specific
controller features without paying the penalty of the full
controller stack.

Since Rails 3 is closer to Rack, the Metal abstraction is
no longer needed.
  • Loading branch information
wycats committed May 29, 2010
1 parent 564ab47 commit 45e6028
Show file tree
Hide file tree
Showing 20 changed files with 9 additions and 319 deletions.
1 change: 0 additions & 1 deletion actionpack/lib/action_dispatch.rb
Expand Up @@ -43,7 +43,6 @@ module ActionDispatch

autoload_under 'middleware' do
autoload :Callbacks
autoload :Cascade
autoload :Cookies
autoload :Flash
autoload :Head
Expand Down
29 changes: 0 additions & 29 deletions actionpack/lib/action_dispatch/middleware/cascade.rb

This file was deleted.

2 changes: 0 additions & 2 deletions railties/guides/source/configuring.textile
Expand Up @@ -63,8 +63,6 @@ h4. Rails General Configuration

* +config.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Controller. Set to nil to disable logging.

* +config.metals+ accepts an array used as the metals to load. If this is set to nil, all metals will be loaded in alphabetical order. If this is set to [], no metals will be loaded. Otherwise metals will be loaded in the order specified

* +config.plugin_loader+ overrides the class that handles loading each plugin. Defaults to +Rails::Plugin::Loader+.

* +config.plugin_locators+ overrides the class that handle finding the desired plugins that you‘d like to load for your application. By default it is the +Rails::Plugin::FileSystemLocator+.
Expand Down
6 changes: 1 addition & 5 deletions railties/guides/source/initialization.textile
Expand Up @@ -668,7 +668,6 @@ This file requires _rails/railtie.rb_ which defines +Rails::Railtie+.
* add_routing_namespaces
* add_locales
* add_view_paths
* add_metals
* add_generator_templates
* load_application_initializers
* load_application_classes
Expand Down Expand Up @@ -726,7 +725,6 @@ This file is used to set up the +Rails::Paths+ module which is used to set up he
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.metals "app/metal", :eager_load => true
paths.app.views "app/views", :eager_load => true
paths.lib "lib", :load_path => true
paths.lib.tasks "lib/tasks", :glob => "**/*.rake"
Expand Down Expand Up @@ -3154,7 +3152,6 @@ This method is defined like this:
middleware.use('ActionDispatch::Cookies')
middleware.use(lambda { ActionController::Base.session_store }, lambda { ActionController::Base.session_options })
middleware.use('ActionDispatch::Flash', :if => lambda { ActionController::Base.session_store })
middleware.use(lambda { Rails::Rack::Metal.new(Rails.application.config.paths.app.metals.to_a, Rails.application.config.metals) })
middleware.use('ActionDispatch::ParamsParser')
middleware.use('::Rack::MethodOverride')
middleware.use('::ActionDispatch::Head')
Expand Down Expand Up @@ -3288,7 +3285,7 @@ Finally, a +Rails::Application::Configuration+ object will be returned. On this
<ruby>
attr_accessor :after_initialize_blocks, :cache_classes, :colorize_logging,
:consider_all_requests_local, :dependency_loading,
:load_once_paths, :logger, :metals, :plugins,
:load_once_paths, :logger, :plugins,
:preload_frameworks, :reload_plugins, :serve_static_assets,
:time_zone, :whiny_nils

Expand Down Expand Up @@ -3574,7 +3571,6 @@ The +super+ method it references comes from +Rails::Engine::Configuration+ which
paths.app.controllers "app/controllers", :eager_load => true
paths.app.helpers "app/helpers", :eager_load => true
paths.app.models "app/models", :eager_load => true
paths.app.metals "app/metal"
paths.app.views "app/views"
paths.lib "lib", :load_path => true
paths.lib.tasks "lib/tasks", :glob => "**/*.rake"
Expand Down
51 changes: 0 additions & 51 deletions railties/guides/source/rails_on_rack.textile
Expand Up @@ -222,57 +222,6 @@ use MyOwnStackFromStratch
run ActionController::Dispatcher.new
</ruby>

h3. Rails Metal Applications

This comment has been minimized.

Copy link
@fxn

fxn May 29, 2010

Member

Big applause for patching the guide :).


Rails Metal applications are minimal Rack applications specially designed for integrating with a typical Rails application. As Rails Metal Applications skip all of the Action Controller stack, serving a request has no overhead from the Rails framework itself. This is especially useful for infrequent cases where the performance of the full stack Rails framework is an issue.

Ryan Bates' "Railscast on Rails Metal":http://railscasts.com/episodes/150-rails-metal provides a nice walkthrough generating and using Rails Metal.

h4. Generating a Metal Application

Rails provides a generator called +metal+ for creating a new Metal application:

<shell>
$ rails generate metal poller
</shell>

This generates +poller.rb+ in the +app/metal+ directory:

<ruby>
# Allow the metal piece to run in isolation
require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails)

class Poller
def self.call(env)
if env["PATH_INFO"] =~ /^\/poller/
[200, {"Content-Type" => "text/html"}, ["Hello, World!"]]
else
[404, {"Content-Type" => "text/html", "X-Cascade" => "pass"}, ["Not Found"]]
end
end
end
</ruby>

Metal applications within +app/metal+ folders in plugins will also be discovered and added to the list.

Metal applications are an optimization. You should make sure to "understand the related performance implications":http://weblog.rubyonrails.org/2008/12/20/performance-of-rails-metal before using it.

WARNING: To continue the Metal chain execution, return an +X-Cascade+ HTTP header with a value of +pass+.

h4. Execution Order

All Metal Applications are executed in alphabetical order of their filenames, so +aaa.rb+ will come before +bbb.rb+ in the metal chain.

You can override the default ordering in your environment. Simply add a line like the following to +config/application.rb+

It is, however, possible to override the default ordering in your environment. Simply add a line like the following to +config/environment.rb+

<ruby>
config.metals = ["Bbb", "Aaa"]
</ruby>

Each string in the array should be the name of your metal class. If you do this then be warned that any metal applications not listed will not be loaded.

h3. Resources

h4. Learning Rack
Expand Down
10 changes: 4 additions & 6 deletions railties/lib/rails/application.rb
Expand Up @@ -27,7 +27,7 @@ module Rails
# Besides providing the same configuration as Rails::Engine and Rails::Railtie,
# the application object has several specific configurations, for example
# "allow_concurrency", "cache_classes", "consider_all_requests_local", "filter_parameters",
# "logger", "metals", "reload_engines", "reload_plugins" and so forth.
# "logger", "reload_engines", "reload_plugins" and so forth.
#
# Check Rails::Application::Configuration to see them all.
#
Expand All @@ -36,17 +36,15 @@ module Rails
# The application object is also responsible for holding the routes and reloading routes
# whenever the files change in development.
#
# == Middlewares and metals
# == Middlewares
#
# The Application is also responsible for building the middleware stack and setting up
# both application and engines metals.
# The Application is also responsible for building the middleware stack.
#
class Application < Engine
autoload :Bootstrap, 'rails/application/bootstrap'
autoload :Configurable, 'rails/application/configurable'
autoload :Configuration, 'rails/application/configuration'
autoload :Finisher, 'rails/application/finisher'
autoload :MetalLoader, 'rails/application/metal_loader'
autoload :Railties, 'rails/application/railties'
autoload :RoutesReloader, 'rails/application/routes_reloader'

Expand Down Expand Up @@ -83,7 +81,7 @@ def method_missing(*args, &block)
end
end

delegate :middleware, :metal_loader, :to => :config
delegate :middleware, :to => :config

def require_environment!
environment = paths.config.environment.to_a.first
Expand Down
7 changes: 1 addition & 6 deletions railties/lib/rails/application/configuration.rb
Expand Up @@ -9,7 +9,7 @@ class Configuration < ::Rails::Engine::Configuration

attr_accessor :allow_concurrency, :cache_classes, :cache_store,
:encoding, :consider_all_requests_local, :dependency_loading,
:filter_parameters, :log_level, :logger, :metals,
:filter_parameters, :log_level, :logger,
:plugins, :preload_frameworks, :reload_engines, :reload_plugins,
:secret_token, :serve_static_assets, :session_options,
:time_zone, :whiny_nils
Expand Down Expand Up @@ -45,10 +45,6 @@ def middleware
@middleware ||= app_middleware.merge_into(default_middleware_stack)
end

def metal_loader
@metal_loader ||= Rails::Application::MetalLoader.new
end

def paths
@paths ||= begin
paths = super
Expand Down Expand Up @@ -157,7 +153,6 @@ def default_middleware_stack
middleware.use('::ActionDispatch::ParamsParser')
middleware.use('::Rack::MethodOverride')
middleware.use('::ActionDispatch::Head')
middleware.use(lambda { metal_loader.build_middleware(metals) }, :if => lambda { metal_loader.metals.any? })
end
end
end
Expand Down
50 changes: 0 additions & 50 deletions railties/lib/rails/application/metal_loader.rb

This file was deleted.

7 changes: 1 addition & 6 deletions railties/lib/rails/engine.rb
Expand Up @@ -25,7 +25,7 @@ module Rails
# end
#
# Then ensure that this file is loaded at the top of your config/application.rb (or in
# your Gemfile) and it will automatically load models, controllers, helpers and metals
# your Gemfile) and it will automatically load models, controllers and helpers
# inside app, load routes at "config/routes.rb", load locales at "config/locales/*",
# load tasks at "lib/tasks/*".
#
Expand Down Expand Up @@ -73,7 +73,6 @@ module Rails
# paths.app.controllers = "app/controllers"
# paths.app.helpers = "app/helpers"
# paths.app.models = "app/models"
# paths.app.metals = "app/metal"
# paths.app.views = "app/views"
# paths.lib = "lib"
# paths.lib.tasks = "lib/tasks"
Expand Down Expand Up @@ -202,10 +201,6 @@ def eager_load!
end
end

initializer :add_metals do |app|
app.metal_loader.paths.unshift(*paths.app.metals.to_a)
end

initializer :load_config_initializers do
paths.config.initializers.to_a.sort.each do |initializer|
load(initializer)
Expand Down
1 change: 0 additions & 1 deletion railties/lib/rails/engine/configuration.rb
Expand Up @@ -19,7 +19,6 @@ def paths
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.metals "app/metal", :eager_load => true
paths.app.views "app/views"
paths.lib "lib", :load_path => true
paths.lib.tasks "lib/tasks", :glob => "**/*.rake"
Expand Down
2 changes: 1 addition & 1 deletion railties/lib/rails/generators/base.rb
Expand Up @@ -288,7 +288,7 @@ def self.base_name
end

# Removes the namespaces and get the generator name. For example,
# Rails::Generators::MetalGenerator will return "metal" as generator name.
# Rails::Generators::ModelGenerator will return "model" as generator name.
#
def self.generator_name
@generator_name ||= begin
Expand Down
8 changes: 0 additions & 8 deletions railties/lib/rails/generators/rails/metal/USAGE

This file was deleted.

11 changes: 0 additions & 11 deletions railties/lib/rails/generators/rails/metal/metal_generator.rb

This file was deleted.

12 changes: 0 additions & 12 deletions railties/lib/rails/generators/rails/metal/templates/metal.rb

This file was deleted.

2 changes: 1 addition & 1 deletion railties/lib/rails/tasks/framework.rake
Expand Up @@ -37,7 +37,7 @@ namespace :rails do
project_templates = "#{Rails.root}/lib/templates"

default_templates = { "erb" => %w{controller mailer scaffold},
"rails" => %w{controller helper metal scaffold_controller stylesheets} }
"rails" => %w{controller helper scaffold_controller stylesheets} }

default_templates.each do |type, names|
local_template_type_dir = File.join(project_templates, type)
Expand Down

2 comments on commit 45e6028

@dpickett
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't kill the metal, the metal will live on!

http://www.youtube.com/watch?v=vJ3emd3phLY

@joshk
Copy link
Contributor

@joshk joshk commented on 45e6028 May 29, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The metal is gone ?!? Oh metal, I will miss you :-(

Please sign in to comment.