From 6db930cb5bbff9ad824590b5844e04768de240b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 14 Mar 2012 22:30:01 +0100 Subject: [PATCH] Remove --http. --- actionpack/CHANGELOG.md | 2 - actionpack/lib/action_controller.rb | 1 - actionpack/lib/action_controller/http.rb | 134 --------- actionpack/test/abstract_unit.rb | 4 - .../controller/http/action_methods_test.rb | 19 -- .../controller/http/conditional_get_test.rb | 55 ---- .../controller/http/data_streaming_test.rb | 27 -- .../test/controller/http/force_ssl_test.rb | 20 -- .../test/controller/http/redirect_to_test.rb | 19 -- .../test/controller/http/renderers_test.rb | 37 --- .../test/controller/http/url_for_test.rb | 20 -- railties/guides/source/api_app.textile | 271 ------------------ railties/lib/rails/configuration.rb | 20 -- railties/lib/rails/generators.rb | 23 +- .../generators/rails/app/app_generator.rb | 8 - .../controllers/application_controller.rb.tt | 6 +- .../rails/app/templates/config/application.rb | 9 - .../rails/resource/resource_generator.rb | 1 - .../scaffold_controller_generator.rb | 3 +- .../templates/http_controller.rb | 60 ---- .../test_unit/scaffold/scaffold_generator.rb | 6 +- .../templates/http_functional_test.rb | 50 ---- railties/test/application/generators_test.rb | 28 -- .../initializers/frameworks_test.rb | 27 -- railties/test/application/middleware_test.rb | 30 -- railties/test/application/rake_test.rb | 20 -- .../test/generators/app_generator_test.rb | 33 --- .../generators/resource_generator_test.rb | 6 - .../scaffold_controller_generator_test.rb | 37 --- railties/test/generators_test.rb | 51 ---- 30 files changed, 7 insertions(+), 1020 deletions(-) delete mode 100644 actionpack/lib/action_controller/http.rb delete mode 100644 actionpack/test/controller/http/action_methods_test.rb delete mode 100644 actionpack/test/controller/http/conditional_get_test.rb delete mode 100644 actionpack/test/controller/http/data_streaming_test.rb delete mode 100644 actionpack/test/controller/http/force_ssl_test.rb delete mode 100644 actionpack/test/controller/http/redirect_to_test.rb delete mode 100644 actionpack/test/controller/http/renderers_test.rb delete mode 100644 actionpack/test/controller/http/url_for_test.rb delete mode 100644 railties/guides/source/api_app.textile delete mode 100644 railties/lib/rails/generators/rails/scaffold_controller/templates/http_controller.rb delete mode 100644 railties/lib/rails/generators/test_unit/scaffold/templates/http_functional_test.rb diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 97215b90d62..20b6820065e 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,7 +1,5 @@ ## Rails 4.0.0 (unreleased) ## -* Support API apps http://edgeguides.rubyonrails.org/api_app.html *Santiago Pastorino and Carlos Antonio da Silva* - * Add `include_hidden` option to select tag. With `:include_hidden => false` select with `multiple` attribute doesn't generate hidden input with blank value. *Vasiliy Ermolovich* * Removed default `size` option from the `text_field`, `search_field`, `telephone_field`, `url_field`, `email_field` helpers. *Philip Arndt* diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index b8624fd1bab..7c10fcbb8a1 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -6,7 +6,6 @@ module ActionController autoload :Base autoload :Caching - autoload :HTTP autoload :Metal autoload :Middleware diff --git a/actionpack/lib/action_controller/http.rb b/actionpack/lib/action_controller/http.rb deleted file mode 100644 index 252a652cd96..00000000000 --- a/actionpack/lib/action_controller/http.rb +++ /dev/null @@ -1,134 +0,0 @@ -require "action_controller/log_subscriber" - -module ActionController - # HTTP Controller is a lightweight version of ActionController::Base, - # created for applications that don't require all functionality that a complete - # \Rails controller provides, allowing you to create faster controllers. The - # main scenario where HTTP Controllers could be used is API only applications. - # - # An HTTP Controller is different from a normal controller in the sense that - # by default it doesn't include a number of features that are usually required - # by browser access only: layouts and templates rendering, cookies, sessions, - # flash, assets, and so on. This makes the entire controller stack thinner and - # faster, suitable for API applications. It doesn't mean you won't have such - # features if you need them: they're all available for you to include in - # your application, they're just not part of the default HTTP Controller stack. - # - # By default, only the ApplicationController in a \Rails application inherits - # from ActionController::HTTP. All other controllers in turn inherit - # from ApplicationController. - # - # A sample controller could look like this: - # - # class PostsController < ApplicationController - # def index - # @posts = Post.all - # render json: @posts - # end - # end - # - # Request, response and parameters objects all work the exact same way as - # ActionController::Base. - # - # == Renders - # - # The default HTTP Controller stack includes all renderers, which means you - # can use render :json and brothers freely in your controllers. Keep - # in mind that templates are not going to be rendered, so you need to ensure - # your controller is calling either render or redirect in - # all actions. - # - # def show - # @post = Post.find(params[:id]) - # render json: @post - # end - # - # == Redirects - # - # Redirects are used to move from one action to another. You can use the - # redirect method in your controllers in the same way as - # ActionController::Base. For example: - # - # def create - # redirect_to root_url and return if not_authorized? - # # do stuff here - # end - # - # == Adding new behavior - # - # In some scenarios you may want to add back some functionality provided by - # ActionController::Base that is not present by default in - # ActionController::HTTP, for instance MimeResponds. This - # module gives you the respond_to and respond_with methods. - # Adding it is quite simple, you just need to include the module in a specific - # controller or in ApplicationController in case you want it - # available to your entire app: - # - # class ApplicationController < ActionController::HTTP - # include ActionController::MimeResponds - # end - # - # class PostsController < ApplicationController - # respond_to :json, :xml - # - # def index - # @posts = Post.all - # respond_with @posts - # end - # end - # - # Quite straightforward. Make sure to check ActionController::Base - # available modules if you want to include any other functionality that is - # not provided by ActionController::HTTP out of the box. - class HTTP < Metal - abstract! - - # Shortcut helper that returns all the ActionController::HTTP modules except the ones passed in the argument: - # - # class MetalController - # ActionController::HTTP.without_modules(:ParamsWrapper, :Streaming).each do |left| - # include left - # end - # end - # - # This gives better control over what you want to exclude and makes it easier - # to create a bare controller class, instead of listing the modules required manually. - def self.without_modules(*modules) - modules = modules.map do |m| - m.is_a?(Symbol) ? ActionController.const_get(m) : m - end - - MODULES - modules - end - - MODULES = [ - HideActions, - UrlFor, - Redirecting, - Rendering, - Renderers::All, - ConditionalGet, - RackDelegation, - - ForceSSL, - DataStreaming, - - # Before callbacks should also be executed the earliest as possible, so - # also include them at the bottom. - AbstractController::Callbacks, - - # Append rescue at the bottom to wrap as much as possible. - Rescue, - - # Add instrumentations hooks at the bottom, to ensure they instrument - # all the methods properly. - Instrumentation - ] - - MODULES.each do |mod| - include mod - end - - ActiveSupport.run_load_hooks(:action_controller, self) - end -end diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index a05a816b712..b1a5356ddd8 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -293,10 +293,6 @@ module ActionController end end - class HTTP - include SharedTestRoutes.url_helpers - end - class TestCase include ActionDispatch::TestProcess diff --git a/actionpack/test/controller/http/action_methods_test.rb b/actionpack/test/controller/http/action_methods_test.rb deleted file mode 100644 index 20bb53aca26..00000000000 --- a/actionpack/test/controller/http/action_methods_test.rb +++ /dev/null @@ -1,19 +0,0 @@ -require 'abstract_unit' - -class ActionMethodsHTTPController < ActionController::HTTP - def one; end - def two; end - hide_action :two -end - -class ActionMethodsHTTPTest < ActiveSupport::TestCase - def setup - @controller = ActionMethodsHTTPController.new - end - - def test_action_methods - assert_equal Set.new(%w(one)), - @controller.class.action_methods, - "#{@controller.controller_path} should not be empty!" - end -end diff --git a/actionpack/test/controller/http/conditional_get_test.rb b/actionpack/test/controller/http/conditional_get_test.rb deleted file mode 100644 index 70d5ef296fc..00000000000 --- a/actionpack/test/controller/http/conditional_get_test.rb +++ /dev/null @@ -1,55 +0,0 @@ -require 'abstract_unit' - -class ConditionalGetHTTPController < ActionController::HTTP - before_filter :handle_last_modified_and_etags, :only => :two - - def one - if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123]) - render :text => "Hi!" - end - end - - def two - render :text => "Hi!" - end - - private - - def handle_last_modified_and_etags - fresh_when(:last_modified => Time.now.utc.beginning_of_day, :etag => [ :foo, 123 ]) - end -end - -class ConditionalGetHTTPTest < ActionController::TestCase - tests ConditionalGetHTTPController - - def setup - @last_modified = Time.now.utc.beginning_of_day.httpdate - end - - def test_request_with_bang_gets_last_modified - get :two - assert_equal @last_modified, @response.headers['Last-Modified'] - assert_response :success - end - - def test_request_with_bang_obeys_last_modified - @request.if_modified_since = @last_modified - get :two - assert_response :not_modified - end - - def test_last_modified_works_with_less_than_too - @request.if_modified_since = 5.years.ago.httpdate - get :two - assert_response :success - end - - def test_request_not_modified - @request.if_modified_since = @last_modified - get :one - assert_equal 304, @response.status.to_i - assert_blank @response.body - assert_equal @last_modified, @response.headers['Last-Modified'] - end -end diff --git a/actionpack/test/controller/http/data_streaming_test.rb b/actionpack/test/controller/http/data_streaming_test.rb deleted file mode 100644 index 67457b25b01..00000000000 --- a/actionpack/test/controller/http/data_streaming_test.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'abstract_unit' - -module TestHTTPFileUtils - def file_name() File.basename(__FILE__) end - def file_path() File.expand_path(__FILE__) end - def file_data() @data ||= File.open(file_path, 'rb') { |f| f.read } end -end - -class DataStreamingHTTPController < ActionController::HTTP - include TestHTTPFileUtils - - def one; end - def two - send_data(file_data, {}) - end -end - -class DataStreamingHTTPTest < ActionController::TestCase - include TestHTTPFileUtils - tests DataStreamingHTTPController - - def test_data - response = process('two') - assert_kind_of String, response.body - assert_equal file_data, response.body - end -end diff --git a/actionpack/test/controller/http/force_ssl_test.rb b/actionpack/test/controller/http/force_ssl_test.rb deleted file mode 100644 index 479ede6b78a..00000000000 --- a/actionpack/test/controller/http/force_ssl_test.rb +++ /dev/null @@ -1,20 +0,0 @@ -require 'abstract_unit' - -class ForceSSLHTTPController < ActionController::HTTP - force_ssl - - def one; end - def two - head :ok - end -end - -class ForceSSLHTTPTest < ActionController::TestCase - tests ForceSSLHTTPController - - def test_banana_redirects_to_https - get :two - assert_response 301 - assert_equal "https://test.host/force_sslhttp/two", redirect_to_url - end -end diff --git a/actionpack/test/controller/http/redirect_to_test.rb b/actionpack/test/controller/http/redirect_to_test.rb deleted file mode 100644 index c410910baeb..00000000000 --- a/actionpack/test/controller/http/redirect_to_test.rb +++ /dev/null @@ -1,19 +0,0 @@ -require 'abstract_unit' - -class RedirectToHTTPController < ActionController::HTTP - def one - redirect_to :action => "two" - end - - def two; end -end - -class RedirectToHTTPTest < ActionController::TestCase - tests RedirectToHTTPController - - def test_redirect_to - get :one - assert_response :redirect - assert_equal "http://test.host/redirect_to_http/two", redirect_to_url - end -end diff --git a/actionpack/test/controller/http/renderers_test.rb b/actionpack/test/controller/http/renderers_test.rb deleted file mode 100644 index a28f226a944..00000000000 --- a/actionpack/test/controller/http/renderers_test.rb +++ /dev/null @@ -1,37 +0,0 @@ -require 'abstract_unit' - -class Model - def to_json(options = {}) - { :a => 'b' }.to_json(options) - end - - def to_xml(options = {}) - { :a => 'b' }.to_xml(options) - end -end - -class RenderersHTTPController < ActionController::HTTP - def one - render :json => Model.new - end - - def two - render :xml => Model.new - end -end - -class RenderersHTTPTest < ActionController::TestCase - tests RenderersHTTPController - - def test_render_json - get :one - assert_response :success - assert_equal({ :a => 'b' }.to_json, @response.body) - end - - def test_render_xml - get :two - assert_response :success - assert_equal({ :a => 'b' }.to_xml, @response.body) - end -end diff --git a/actionpack/test/controller/http/url_for_test.rb b/actionpack/test/controller/http/url_for_test.rb deleted file mode 100644 index fba24011a22..00000000000 --- a/actionpack/test/controller/http/url_for_test.rb +++ /dev/null @@ -1,20 +0,0 @@ -require 'abstract_unit' - -class UrlForHTTPController < ActionController::HTTP - def one; end - def two; end -end - -class UrlForHTTPTest < ActionController::TestCase - tests UrlForHTTPController - - def setup - super - @request.host = 'www.example.com' - end - - def test_url_for - get :one - assert_equal "http://www.example.com/url_for_http/one", @controller.url_for - end -end diff --git a/railties/guides/source/api_app.textile b/railties/guides/source/api_app.textile deleted file mode 100644 index 6c12b2a6ddf..00000000000 --- a/railties/guides/source/api_app.textile +++ /dev/null @@ -1,271 +0,0 @@ -h2. Using Rails for API-only Apps - -In this guide you will learn: - -* What Rails provides for API-only applications -* How to configure Rails to start without any browser features -* How to decide which middlewares you will want to include -* How to decide which modules to use in your controller - -endprologue. - -h3. What is an API app? - -Traditionally, when people said that they used Rails as an "API", they meant providing a programmatically accessible API alongside their web application. -For example, GitHub provides "an API":http://developer.github.com that you can use from your own custom clients. - -With the advent of client-side frameworks, more developers are using Rails to build a backend that is shared between their web application and other native applications. - -For example, Twitter uses its "public API":https://dev.twitter.com in its web application, which is built as a static site that consumes JSON resources. - -Instead of using Rails to generate dynamic HTML that will communicate with the server through forms and links, many developers are treating their web application as just another client, delivered as static HTML, CSS and JavaScript, and consuming a simple JSON API - -This guide covers building a Rails application that serves JSON resources to an API client *or* client-side framework. - -h3. Why use Rails for JSON APIs? - -The first question a lot of people have when thinking about building a JSON API using Rails is: "isn't using Rails to spit out some JSON overkill? Shouldn't I just use something like Sinatra?" - -For very simple APIs, this may be true. However, even in very HTML-heavy applications, most of an application's logic is actually outside of the view layer. - -The reason most people use Rails is that it provides a set of defaults that allows us to get up and running quickly without having to make a lot of trivial decisions. - -Let's take a look at some of the things that Rails provides out of the box that are still applicable to API applications. - -Handled at the middleware layer: - -* Reloading: Rails applications support transparent reloading. This works even if your application gets big and restarting the server for every request becomes non-viable. -* Development Mode: Rails application come with smart defaults for development, making development pleasant without compromising production-time performance. -* Test Mode: Ditto test mode. -* Logging: Rails applications log every request, with a level of verbosity appropriate for the current mode. Rails logs in development include information about the request environment, database queries, and basic performance information. -* Security: Rails detects and thwarts "IP spoofing attacks":http://en.wikipedia.org/wiki/IP_address_spoofing and handles cryptographic signatures in a "timing attack":http://en.wikipedia.org/wiki/Timing_attack aware way. Don't know what an IP spoofing attack or a timing attack is? Exactly. -* Parameter Parsing: Want to specify your parameters as JSON instead of as a URL-encoded String? No problem. Rails will decode the JSON for you and make it available in +params+. Want to use nested URL-encoded params? That works too. -* Conditional GETs: Rails handles conditional +GET+, (+ETag+ and +Last-Modified+), processing request headers and returning the correct response headers and status code. All you need to do is use the "stale?":http://api.rubyonrails.org/classes/ActionController/ConditionalGet.html#method-i-stale-3F check in your controller, and Rails will handle all of the HTTP details for you. -* Caching: If you use +dirty?+ with public cache control, Rails will automatically cache your responses. You can easily configure the cache store. -* HEAD requests: Rails will transparently convert +HEAD+ requests into +GET+ requests, and return just the headers on the way out. This makes +HEAD+ work reliably in all Rails APIs. - -While you could obviously build these up in terms of existing Rack middlewares, I think this list demonstrates that the default Rails middleware stack provides a lot of value, even if you're "just generating JSON". - -Handled at the ActionPack layer: - -* Resourceful Routing: If you're building a RESTful JSON API, you want to be using the Rails router. Clean and conventional mapping from HTTP to controllers means not having to spend time thinking about how to model your API in terms of HTTP. -* URL Generation: The flip side of routing is URL generation. A good API based on HTTP includes URLs (see "the GitHub gist API":http://developer.github.com/v3/gists/ for an example). -* Header and Redirection Responses: +head :no_content+ and +redirect_to user_url(current_user)+ come in handy. Sure, you could manually add the response headers, but why? -* Caching: Rails provides page, action and fragment caching. Fragment caching is especially helpful when building up a nested JSON object. -* Basic, Digest and Token Authentication: Rails comes with out-of-the-box support for three kinds of HTTP authentication. -* Instrumentation: Rails 3.0 added an instrumentation API that will trigger registered handlers for a variety of events, such as action processing, sending a file or data, redirection, and database queries. The payload of each event comes with relevant information (for the action processing event, the payload includes the controller, action, params, request format, request method and the request's full path). -* Generators: This may be passé for advanced Rails users, but it can be nice to generate a resource and get your model, controller, test stubs, and routes created for you in a single command. -* Plugins: Many third-party libraries come with support for Rails that reduces or eliminates the cost of setting up and gluing together the library and the web framework. This includes things like overriding default generators, adding rake tasks, and honoring Rails choices (like the logger and cache backend). - -Of course, the Rails boot process also glues together all registered components. For example, the Rails boot process is what uses your +config/database.yml+ file when configuring ActiveRecord. - -**The short version is**: you may not have thought about which parts of Rails are still applicable even if you remove the view layer, but the answer turns out to be "most of it". - -h3. The Basic Configuration - -If you're building a Rails application that will be an API server first and foremost, you can start with a more limited subset of Rails and add in features as needed. - -You can generate a new bare Rails app: - - -$ rails new my_api --http - - -This will do three main things for you: - -* Configure your application to start with a more limited set of middleware than normal. Specifically, it will not include any middleware primarily useful for browser applications (like cookie support) by default. -* Make +ApplicationController+ inherit from +ActionController::HTTP+ instead of +ActionController::Base+. As with middleware, this will leave out any +ActionController+ modules that provide functionality primarily used by browser applications. -* Configure the generators to skip generating views, helpers and assets when you generate a new resource. - -If you want to take an existing app and make it an API app, follow the following steps. - -In +config/application.rb+ add the following lines at the top of the +Application+ class: - - -config.middleware.http_only! -config.generators.http_only! - - -Change +app/controllers/application_controller.rb+: - - -# instead of -class ApplicationController < ActionController::Base -end - -# do -class ApplicationController < ActionController::HTTP -end - - -h3. Choosing Middlewares - -An API application comes with the following middlewares by default. - -* +Rack::Cache+: Caches responses with public +Cache-Control+ headers using HTTP caching semantics. See below for more information. -* +Rack::Sendfile+: Uses a front-end server's file serving support from your Rails application. -* +Rack::Lock+: If your application is not marked as threadsafe (+config.threadsafe!+), this middleware will add a mutex around your requests. -* +ActionDispatch::RequestId+: -* +Rails::Rack::Logger+: -* +Rack::Runtime+: Adds a header to the response listing the total runtime of the request. -* +ActionDispatch::ShowExceptions+: Rescue exceptions and re-dispatch them to an exception handling application -* +ActionDispatch::DebugExceptions+: Log exceptions -* +ActionDispatch::RemoteIp+: Protect against IP spoofing attacks -* +ActionDispatch::Reloader+: In development mode, support code reloading. -* +ActionDispatch::ParamsParser+: Parse XML, YAML and JSON parameters when the request's +Content-Type+ is one of those. -* +ActionDispatch::Head+: Dispatch +HEAD+ requests as +GET+ requests, and return only the status code and headers. -* +Rack::ConditionalGet+: Supports the +stale?+ feature in Rails controllers. -* +Rack::ETag+: Automatically set an +ETag+ on all string responses. This means that if the same response is returned from a controller for the same URL, the server will return a +304 Not Modified+, even if no additional caching steps are taken. This is primarily a client-side optimization; it reduces bandwidth costs but not server processing time. - -Other plugins, including +ActiveRecord+, may add additional middlewares. In general, these middlewares are agnostic to the type of app you are building, and make sense in an API-only Rails application. - -You can get a list of all middlewares in your application via: - - -$ rake middleware - - -h4. Using Rack::Cache - -When used with Rails, +Rack::Cache+ uses the Rails cache store for its entity and meta stores. This means that if you use memcache, for your Rails app, for instance, the built-in HTTP cache will use memcache. - -To make use of +Rack::Cache+, you will want to use +stale?+ in your controller. Here's an example of +stale?+ in use. - - -def show - @post = Post.find(params[:id]) - - if stale?(:last_modified => @post.updated_at) - render json: @post - end -end - - -The call to +stale?+ will compare the +If-Modified-Since+ header in the request with +@post.updated_at+. If the header is newer than the last modified, this action will return a +304 Not Modified+ response. Otherwise, it will render the response and include a +Last-Modified+ header with the response. - -Normally, this mechanism is used on a per-client basis. +Rack::Cache+ allows us to share this caching mechanism across clients. We can enable cross-client caching in the call to +stale?+ - - -def show - @post = Post.find(params[:id]) - - if stale?(:last_modified => @post.updated_at, :public => true) - render json: @post - end -end - - -This means that +Rack::Cache+ will store off +Last-Modified+ value for a URL in the Rails cache, and add an +If-Modified-Since+ header to any subsequent inbound requests for the same URL. - -Think of it as page caching using HTTP semantics. - -NOTE: The +Rack::Cache+ middleware is always outside of the +Rack::Lock+ mutex, even in single-threaded apps. - -h4. Using Rack::Sendfile - -When you use the +send_file+ method in a Rails controller, it sets the +X-Sendfile+ header. +Rack::Sendfile+ is responsible for actually sending the file. - -If your front-end server supports accelerated file sending, +Rack::Sendfile+ will offload the actual file sending work to the front-end server. - -You can configure the name of the header that your front-end server uses for this purposes using +config.action_dispatch.x_sendfile_header+ in the appropriate environment config file. - -You can learn more about how to use +Rack::Sendfile+ with popular front-ends in "the Rack::Sendfile documentation":http://rubydoc.info/github/rack/rack/master/Rack/Sendfile - -The values for popular servers once they are configured to support accelerated file sending: - - -# Apache and lighttpd -config.action_dispatch.x_sendfile_header = "X-Sendfile" - -# nginx -config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" - - -Make sure to configure your server to support these options following the instructions in the +Rack::Sendfile+ documentation. - -NOTE: The +Rack::Sendfile+ middleware is always outside of the +Rack::Lock+ mutex, even in single-threaded apps. - -h4. Using ActionDispatch::ParamsParser - -+ActionDispatch::ParamsParser+ will take parameters from the client in JSON and make them available in your controller as +params+. - -To use this, your client will need to make a request with JSON-encoded parameters and specify the +Content-Type+ as +application/json+. - -Here's an example in jQuery: - - -jQuery.ajax({ - type: 'POST', - url: '/people' - dataType: 'json', - contentType: 'application/json', - data: JSON.stringify({ person: { firstName: "Yehuda", lastName: "Katz" } }), - - success: function(json) { } -}); - - -+ActionDispatch::ParamsParser+ will see the +Content-Type+ and your params will be +{ :person => { :firstName => "Yehuda", :lastName => "Katz" } }+. - -h4. Other Middlewares - -Rails ships with a number of other middlewares that you might want to use in an API app, especially if one of your API clients is the browser: - -* +Rack::MethodOverride+: Allows the use of the +_method+ hack to route POST requests to other verbs. -* +ActionDispatch::Cookies+: Supports the +cookie+ method in +ActionController+, including support for signed and encrypted cookies. -* +ActionDispatch::Flash+: Supports the +flash+ mechanism in +ActionController+. -* +ActionDispatch::BestStandards+: Tells Internet Explorer to use the most standards-compliant available renderer. In production mode, if ChromeFrame is available, use ChromeFrame. -* Session Management: If a +config.session_store+ is supplied, this middleware makes the session available as the +session+ method in +ActionController+. - -Any of these middlewares can be adding via: - - -config.middleware.use Rack::MethodOverride - - -h4. Removing Middlewares - -If you don't want to use a middleware that is included by default in the API-only middleware set, you can remove it using +config.middleware.delete+: - - -config.middleware.delete ::Rack::Sendfile - - -Keep in mind that removing these features may remove support for certain features in +ActionController+. - -h3. Choosing Controller Modules - -An API application (using +ActionController::HTTP+) comes with the following controller modules by default: - -* +ActionController::UrlFor+: Makes +url_for+ and friends available -* +ActionController::Redirecting+: Support for +redirect_to+ -* +ActionController::Rendering+: Basic support for rendering -* +ActionController::Renderers::All+: Support for +render :json+ and friends -* +ActionController::ConditionalGet+: Support for +stale?+ -* +ActionController::ForceSSL+: Support for +force_ssl+ -* +ActionController::RackDelegation+: Support for the +request+ and +response+ methods returning +ActionDispatch::Request+ and +ActionDispatch::Response+ objects. -* +ActionController::DataStreaming+: Support for +send_file+ and +send_data+ -* +AbstractController::Callbacks+: Support for +before_filter+ and friends -* +ActionController::Instrumentation+: Support for the instrumentation hooks defined by +ActionController+ (see "the source":https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/instrumentation.rb for more). -* +ActionController::Rescue+: Support for +rescue_from+. - -Other plugins may add additional modules. You can get a list of all modules included into +ActionController::HTTP+ in the rails console: - - -$ irb ->> ActionController::HTTP.ancestors - ActionController::Metal.ancestors - - -h4. Adding Other Modules - -All ActionController modules know about their dependent modules, so you can feel free to include any modules into your controllers, and all dependencies will be included and set up as well. - -Some common modules you might want to add: - -* +AbstractController::Translation+: Support for the +l+ and +t+ localization and translation methods. These delegate to +I18n.translate+ and +I18n.localize+. -* +ActionController::HTTPAuthentication::Basic+ (or +Digest+ or +Token): Support for basic, digest or token HTTP authentication. -* +AbstractController::Layouts+: Support for layouts when rendering. -* +ActionController::MimeResponds+: Support for content negotiation (+respond_to+, +respond_with+). -* +ActionController::Cookies+: Support for +cookies+, which includes support for signed and encrypted cookies. This requires the cookie middleware. - -The best place to add a module is in your +ApplicationController+. You can also add modules to individual controllers. diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 0fb463c44d5..d81206bdc6d 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -6,20 +6,6 @@ require 'rails/rack' module Rails module Configuration - module HttpOnly #:nodoc: - def initialize - @http_only = false - end - - def http_only! - @http_only = true - end - - def http_only? - @http_only - end - end - # MiddlewareStackProxy is a proxy for the Rails middleware stack that allows # you to configure middlewares in your application. It works basically as a # command recorder, saving each command to be applied after initialization @@ -58,10 +44,7 @@ module Rails # Cookies, Session and Flash, BestStandardsSupport, and MethodOverride. You # can always add any of them later manually if you want. class MiddlewareStackProxy - include HttpOnly - def initialize - super @operations = [] end @@ -99,10 +82,7 @@ module Rails attr_accessor :aliases, :options, :templates, :fallbacks, :colorize_logging attr_reader :hidden_namespaces - include HttpOnly - def initialize - super @aliases = Hash.new { |h,k| h[k] = {} } @options = Hash.new { |h,k| h[k] = {} } @fallbacks = {} diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 3965e058236..b9c1b01f546 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -46,7 +46,6 @@ module Rails :assets => true, :force_plural => false, :helper => true, - :http => false, :integration_tool => nil, :javascripts => true, :javascript_engine => :js, @@ -62,7 +61,6 @@ module Rails } def self.configure!(config) #:nodoc: - http_only! if config.http_only? no_color! unless config.colorize_logging aliases.deep_merge! config.aliases options.deep_merge! config.options @@ -72,7 +70,7 @@ module Rails hide_namespaces(*config.hidden_namespaces) end - def self.templates_path + def self.templates_path #:nodoc: @templates_path ||= [] end @@ -106,25 +104,6 @@ module Rails Thor::Base.shell = Thor::Shell::Basic end - # Configure generators for http only applications. It basically hides - # everything that is usually browser related, such as assets and session - # migration generators, and completely disable views, helpers and assets - # so generators such as scaffold won't create them. - def self.http_only! - hide_namespaces "assets", "css", "js", "session_migration" - - options[:rails].merge!( - :assets => false, - :helper => false, - :http => true, - :javascripts => false, - :javascript_engine => nil, - :stylesheets => false, - :stylesheet_engine => nil, - :template_engine => nil - ) - end - # Track all generators subclasses. def self.subclasses @subclasses ||= [] diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index ffdfb32abae..f0745df6673 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -144,9 +144,6 @@ module Rails class AppGenerator < AppBase add_shared_options_for "application" - class_option :http, :type => :boolean, :default => false, - :desc => "Preconfigure smaller stack for HTTP only apps" - # Add bin/rails options class_option :version, :type => :boolean, :aliases => "-v", :group => :rails, :desc => "Show Rails version number and quit" @@ -159,10 +156,6 @@ module Rails if !options[:skip_active_record] && !DATABASES.include?(options[:database]) raise Error, "Invalid value for --database option. Supported for preconfiguration are: #{DATABASES.join(", ")}." end - - # Force sprockets to be skipped when generating http only app. - # Can't modify options hash as it's frozen by default. - self.options = options.merge(:skip_sprockets => true).freeze if options.http? end public_task :create_root @@ -177,7 +170,6 @@ module Rails def create_app_files build(:app) - remove_file("app/views") if options.http? end def create_config_files diff --git a/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt b/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt index 4dc85ec1560..3ddc86ae0a2 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt @@ -1,5 +1,5 @@ -class ApplicationController < ActionController::<%= options.http? ? "HTTP" : "Base" %> +class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :reset_session instead. - <%= comment_if :http %>protect_from_forgery :with => :exception -end + protect_from_forgery :with => :exception +end \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index ba3785be357..c8a3c13b959 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -66,15 +66,6 @@ module <%= app_const_base %> # Version of your assets, change this if you want to expire all your assets. config.assets.version = '1.0' -<% end -%> -<% if options.http? -%> - - # Only loads a smaller set of middleware suitable for HTTP only apps. - # Middleware like session, flash, cookies can be added back manually. - config.middleware.http_only! - - # Skip views, helpers and assets when generating a new resource. - config.generators.http_only! <% end -%> end end diff --git a/railties/lib/rails/generators/rails/resource/resource_generator.rb b/railties/lib/rails/generators/rails/resource/resource_generator.rb index 11326388b45..7c7b289d195 100644 --- a/railties/lib/rails/generators/rails/resource/resource_generator.rb +++ b/railties/lib/rails/generators/rails/resource/resource_generator.rb @@ -21,7 +21,6 @@ module Rails return if options[:actions].present? route_config = regular_class_path.collect{ |namespace| "namespace :#{namespace} do " }.join(" ") route_config << "resources :#{file_name.pluralize}" - route_config << ", except: :edit" if options.http? route_config << " end" * regular_class_path.size route route_config end diff --git a/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb b/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb index 17d462fa40f..083eb49d65f 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb @@ -14,8 +14,7 @@ module Rails :desc => "Generate controller with HTTP actions only" def create_controller_files - template_file = options.http? ? "http_controller.rb" : "controller.rb" - template template_file, File.join('app/controllers', class_path, "#{controller_file_name}_controller.rb") + template "controller.rb", File.join('app/controllers', class_path, "#{controller_file_name}_controller.rb") end hook_for :template_engine, :test_framework, :as => :scaffold diff --git a/railties/lib/rails/generators/rails/scaffold_controller/templates/http_controller.rb b/railties/lib/rails/generators/rails/scaffold_controller/templates/http_controller.rb deleted file mode 100644 index 3f44ac18a49..00000000000 --- a/railties/lib/rails/generators/rails/scaffold_controller/templates/http_controller.rb +++ /dev/null @@ -1,60 +0,0 @@ -<% module_namespacing do -%> -class <%= controller_class_name %>Controller < ApplicationController - # GET <%= route_url %> - # GET <%= route_url %>.json - def index - @<%= plural_table_name %> = <%= orm_class.all(class_name) %> - - render json: @<%= plural_table_name %> - end - - # GET <%= route_url %>/1 - # GET <%= route_url %>/1.json - def show - @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %> - - render json: @<%= singular_table_name %> - end - - # GET <%= route_url %>/new - # GET <%= route_url %>/new.json - def new - @<%= singular_table_name %> = <%= orm_class.build(class_name) %> - - render json: @<%= singular_table_name %> - end - - # POST <%= route_url %> - # POST <%= route_url %>.json - def create - @<%= singular_table_name %> = <%= orm_class.build(class_name, "params[:#{singular_table_name}]") %> - - if @<%= orm_instance.save %> - render json: @<%= singular_table_name %>, status: :created, location: @<%= singular_table_name %> - else - render json: @<%= orm_instance.errors %>, status: :unprocessable_entity - end - end - - # PATCH/PUT <%= route_url %>/1 - # PATCH/PUT <%= route_url %>/1.json - def update - @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %> - - if @<%= orm_instance.update_attributes("params[:#{singular_table_name}]") %> - head :no_content - else - render json: @<%= orm_instance.errors %>, status: :unprocessable_entity - end - end - - # DELETE <%= route_url %>/1 - # DELETE <%= route_url %>/1.json - def destroy - @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %> - @<%= orm_instance.destroy %> - - head :no_content - end -end -<% end -%> diff --git a/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb b/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb index e875c813401..9e76587a0d7 100644 --- a/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +++ b/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb @@ -14,10 +14,8 @@ module TestUnit :desc => "Generate functional test with HTTP actions only" def create_test_files - template_file = options.http? ? "http_functional_test.rb" : "functional_test.rb" - - template template_file, - File.join('test/functional', controller_class_path, "#{controller_file_name}_controller_test.rb") + template "functional_test.rb", + File.join("test/functional", controller_class_path, "#{controller_file_name}_controller_test.rb") end private diff --git a/railties/lib/rails/generators/test_unit/scaffold/templates/http_functional_test.rb b/railties/lib/rails/generators/test_unit/scaffold/templates/http_functional_test.rb deleted file mode 100644 index 5bb61cb263a..00000000000 --- a/railties/lib/rails/generators/test_unit/scaffold/templates/http_functional_test.rb +++ /dev/null @@ -1,50 +0,0 @@ -require 'test_helper' - -<% module_namespacing do -%> -class <%= controller_class_name %>ControllerTest < ActionController::TestCase - setup do - @<%= singular_table_name %> = <%= table_name %>(:one) - @request.accept = "application/json" - end - - test "should get index" do - get :index - assert_response :success - assert_not_nil assigns(:<%= table_name %>) - end - - test "should get new" do - get :new - assert_response :success - end - - test "should create <%= singular_table_name %>" do - assert_difference('<%= class_name %>.count') do - post :create, <%= "#{singular_table_name}: { #{attributes_hash} }" %> - end - - assert_response 201 - assert_not_nil assigns(:<%= singular_table_name %>) - end - - test "should show <%= singular_table_name %>" do - get :show, id: @<%= singular_table_name %> - assert_response :success - end - - test "should update <%= singular_table_name %>" do - put :update, id: @<%= singular_table_name %>, <%= "#{singular_table_name}: { #{attributes_hash} }" %> - assert_response 204 - assert_not_nil assigns(:<%= singular_table_name %>) - end - - test "should destroy <%= singular_table_name %>" do - assert_difference('<%= class_name %>.count', -1) do - delete :destroy, id: @<%= singular_table_name %> - end - - assert_response 204 - assert_not_nil assigns(:<%= singular_table_name %>) - end -end -<% end -%> diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb index 15a71260c15..bf58bb3f74c 100644 --- a/railties/test/application/generators_test.rb +++ b/railties/test/application/generators_test.rb @@ -125,33 +125,5 @@ module ApplicationTests assert_equal expected, c.generators.options end end - - test "http only disables options from generators" do - add_to_config <<-RUBY - config.generators.http_only! - RUBY - - # Initialize the application - require "#{app_path}/config/environment" - Rails.application.load_generators - - assert !Rails::Generators.options[:rails][:template_engine], - "http only should have disabled generator options" - end - - test "http only allow overriding generators options" do - add_to_config <<-RUBY - config.generators.helper = true - config.generators.http_only! - config.generators.template_engine = :my_template - RUBY - - # Initialize the application - require "#{app_path}/config/environment" - Rails.application.load_generators - - assert_equal :my_template, Rails::Generators.options[:rails][:template_engine] - assert_equal true, Rails::Generators.options[:rails][:helper] - end end end diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb index cb321f0dd43..a08e5b2374b 100644 --- a/railties/test/application/initializers/frameworks_test.rb +++ b/railties/test/application/initializers/frameworks_test.rb @@ -130,33 +130,6 @@ module ApplicationTests assert_equal "false", last_response.body end - test "action_controller http initializes successfully" do - app_file "app/controllers/application_controller.rb", <<-RUBY - class ApplicationController < ActionController::HTTP - end - RUBY - - app_file "app/controllers/omg_controller.rb", <<-RUBY - class OmgController < ApplicationController - def show - render :json => { :omg => 'omg' } - end - end - RUBY - - app_file "config/routes.rb", <<-RUBY - AppTemplate::Application.routes.draw do - match "/:controller(/:action)" - end - RUBY - - require 'rack/test' - extend Rack::Test::Methods - - get '/omg/show' - assert_equal '{"omg":"omg"}', last_response.body - end - # AD test "action_dispatch extensions are applied to ActionDispatch" do add_to_config "config.action_dispatch.tld_length = 2" diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb index 43f86f40e49..2f62d978e30 100644 --- a/railties/test/application/middleware_test.rb +++ b/railties/test/application/middleware_test.rb @@ -52,36 +52,6 @@ module ApplicationTests ], middleware end - test "http only middleware stack" do - add_to_config "config.middleware.http_only!" - add_to_config "config.force_ssl = true" - add_to_config "config.action_dispatch.x_sendfile_header = 'X-Sendfile'" - - boot! - - assert_equal [ - "Rack::SSL", - "Rack::Sendfile", - "ActionDispatch::Static", - "Rack::Lock", - "ActiveSupport::Cache::Strategy::LocalCache", - "Rack::Runtime", - "ActionDispatch::RequestId", - "Rails::Rack::Logger", - "ActionDispatch::ShowExceptions", - "ActionDispatch::DebugExceptions", - "ActionDispatch::RemoteIp", - "ActionDispatch::Reloader", - "ActionDispatch::Callbacks", - "ActiveRecord::ConnectionAdapters::ConnectionManagement", - "ActiveRecord::QueryCache", - "ActionDispatch::ParamsParser", - "ActionDispatch::Head", - "Rack::ConditionalGet", - "Rack::ETag" - ], middleware - end - test "Rack::Sendfile is not included by default" do boot! diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index 545020357a7..b6cbb101415 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -132,26 +132,6 @@ module ApplicationTests assert_no_match(/Errors running/, output) end - def test_http_scaffold_tests_pass_by_default - add_to_config <<-RUBY - config.middleware.http_only! - config.generators.http_only! - RUBY - - app_file "app/controllers/application_controller.rb", <<-RUBY - class ApplicationController < ActionController::HTTP - end - RUBY - - output = Dir.chdir(app_path) do - `rails generate scaffold user username:string password:string; - bundle exec rake db:migrate db:test:clone test` - end - - assert_match(/6 tests, 12 assertions, 0 failures, 0 errors/, output) - assert_no_match(/Errors running/, output) - end - def test_rake_dump_structure_should_respect_db_structure_env_variable Dir.chdir(app_path) do # ensure we have a schema_migrations table to dump diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 363155bc55f..27960c63e9d 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -361,39 +361,6 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_file "config/application.rb", /config\.active_record\.dependent_restrict_raises = false/ end - def test_http_generates_config_middleware_and_generator_http_setup - run_generator [destination_root, "--http"] - assert_file "config/application.rb", /config\.middleware\.http_only!/, - /config\.generators\.http_only!/ - end - - def test_http_generates_application_controller_with_action_controller_http - run_generator [destination_root, "--http"] - assert_file "app/controllers/application_controller.rb", - /class ApplicationController < ActionController::HTTP/ - end - - def test_http_generates_application_controller_with_protect_from_forgery_commented_out_setup - run_generator [destination_root, "--http"] - assert_file "app/controllers/application_controller.rb", /^ # protect_from_forgery/ - end - - def test_http_does_not_generate_app_views_dir - run_generator [destination_root, "--http"] - assert_no_directory "app/views" - end - - def test_http_skip_sprockets_entries_in_gemfile_and_application - run_generator [destination_root, "--http"] - assert_file "Gemfile" do |content| - assert_no_match(/group :assets/, content) - end - assert_file "config/application.rb" do |content| - assert_match(/^# require "sprockets/, content) - assert_no_match(/config\.assets/, content) - end - end - def test_pretend_option output = run_generator [File.join(destination_root, "myapp"), "--pretend"] assert_no_match(/run bundle install/, output) diff --git a/railties/test/generators/resource_generator_test.rb b/railties/test/generators/resource_generator_test.rb index 4ba3ad8c41f..73804dae451 100644 --- a/railties/test/generators/resource_generator_test.rb +++ b/railties/test/generators/resource_generator_test.rb @@ -86,10 +86,4 @@ class ResourceGeneratorTest < Rails::Generators::TestCase assert_no_match(/resources :accounts$/, route) end end - - def test_http_only_does_not_generate_edit_route - run_generator ["Account", "--http"] - - assert_file "config/routes.rb", /resources :accounts, except: :edit$/ - end end diff --git a/railties/test/generators/scaffold_controller_generator_test.rb b/railties/test/generators/scaffold_controller_generator_test.rb index ed54ce43da9..1eea50b0d92 100644 --- a/railties/test/generators/scaffold_controller_generator_test.rb +++ b/railties/test/generators/scaffold_controller_generator_test.rb @@ -142,41 +142,4 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase assert_match(/\{ render action: "new" \}/, content) end end - - def test_http_only_generates_controller_without_respond_to_block_and_html_format - run_generator ["User", "--http"] - - assert_file "app/controllers/users_controller.rb" do |content| - assert_match(/render json: @user/, content) - assert_no_match(/respond_to/, content) - assert_no_match(/format\.html/, content) - end - end - - def test_http_only_generates_functional_tests_with_json_format_and_http_status_assertions - run_generator ["User", "--http"] - - assert_file "test/functional/users_controller_test.rb" do |content| - assert_match(/class UsersControllerTest < ActionController::TestCase/, content) - assert_match(/@request\.accept = "application\/json"/, content) - assert_match(/test "should get index"/, content) - - assert_match(/assert_response 201/, content) - assert_no_match(/assert_redirected_to/, content) - end - end - - def test_http_only_does_not_generate_edit_action - run_generator ["User", "--http"] - - assert_file "app/controllers/users_controller.rb" do |content| - assert_match(/def index/, content) - assert_no_match(/def edit/, content) - end - - assert_file "test/functional/users_controller_test.rb" do |content| - assert_match(/test "should get index"/, content) - assert_no_match(/test "should get edit"/, content) - end - end end diff --git a/railties/test/generators_test.rb b/railties/test/generators_test.rb index 9e7ec86fdfd..60e7e57a913 100644 --- a/railties/test/generators_test.rb +++ b/railties/test/generators_test.rb @@ -213,55 +213,4 @@ class GeneratorsTest < Rails::Generators::TestCase Rails::Generators.hide_namespace("special:namespace") assert Rails::Generators.hidden_namespaces.include?("special:namespace") end - - def test_http_only_hides_generators - generators = %w(assets js css session_migration) - - generators.each do |generator| - assert !Rails::Generators.hidden_namespaces.include?(generator) - end - - with_http_only! do - generators.each do |generator| - assert Rails::Generators.hidden_namespaces.include?(generator), - "http only should hide #{generator} generator" - end - end - end - - def test_http_only_enables_http_option - options = Rails::Generators.options[:rails] - - assert !options[:http], "http option should be disabled by default" - - with_http_only! do - assert options[:http], "http only should enable generator http option" - end - end - - def test_http_only_disables_template_and_helper_and_assets_options - options = Rails::Generators.options[:rails] - disable_options = [:assets, :helper, :javascripts, :javascript_engine, - :stylesheets, :stylesheet_engine, :template_engine] - - disable_options.each do |disable_option| - assert options[disable_option], "without http only should have generator option #{disable_option} enabled" - end - - with_http_only! do - disable_options.each do |disable_option| - assert !options[disable_option], "http only should have generator option #{disable_option} disabled" - end - end - end - - private - - def with_http_only! - Rails::Generators.http_only! - yield - ensure - Rails::Generators.instance_variable_set(:@hidden_namespaces, nil) - Rails::Generators.instance_variable_set(:@options, nil) - end end