diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 3df3c341bb31dacc529f7c5e2f8241880aac00f5..032769a5c6798136d1b278861298de3c559af57c 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -43,12 +43,62 @@ def build(action, app=nil, &block) end end - # Provides a way to get a valid Rack application from a controller. + # ActionController::Metal is the simplest possible controller, providing a + # valid Rack interface without the additional niceties provided by + # ActionController::Base. + # + # A sample Metal controller might look like this: + # + # class HelloController < ActionController::Metal + # def index + # self.response_body = "Hello World!" + # end + # end + # + # And then to route requests to your Metal controller, you would add + # something like this to config/routes.rb: + # + # match '/hello', :to => HelloController.action(:index), + # :as => 'hello' + # + # The action method returns a valid Rack application for the \Rails + # router to dispatch to. + # + # == Rendering Helpers + # + # ActionController::Metal by default provides no utilities for rendering + # views, partials, or other responses aside from explicitly calling of + # response_body=, content_type=, and status=. To + # add the render helpers you're used to having in a normal controller, you + # can do the following: + # + # class HelloController < ActionController::Metal + # include ActionController::Rendering + # append_view_path Rails.root + "app/views" + # + # def index + # render "hello/index" + # end + # end + # + # == Redirection Helpers + # + # To add redirection helpers to your Metal controller, do the following: + # + # class HelloController < ActionController::Metal + # include ActionController::Redirecting + # + # def index + # redirect_to root_url + # end + # end + # + # == Other Helpers + # + # You can refer to the modules defined in ActionController to see + # the other features in ActionController::Base that you can bring + # into your Metal controller. # - # In AbstractController, dispatching is triggered directly by calling #process on a new controller. - # ActionController::Metal provides an action method that returns a valid Rack application for a - # given action. Other rack builders, such as Rack::Builder, Rack::URLMap, and the \Rails router, - # can dispatch directly to actions returned by controllers in your application. class Metal < AbstractController::Base abstract! diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index 8810227a59fa9f3cc66d18fe4479356b45b3fca4..43fd93adf6978c7ad4c542b3bef02b510ab85c06 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -56,6 +56,18 @@ module ActionDispatch # resources :posts, :comments # end # + # Alternately, you can add prefixes to your path without using a separate + # directory by using +scope+. +scope+ takes additional options which + # apply to all enclosed routes. + # + # scope :path => "/cpanel", :as => 'admin' do + # resources :posts, :comments + # end + # + # For more, see Routing::Mapper::Resources#resources, + # Routing::Mapper::Scoping#namespace, and + # Routing::Mapper::Scoping#scope. + # # == Named routes # # Routes can be named by passing an :as option, diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index f65a294eca1de915e429e67b445e4f93478eda2d..b28b68ad83ab88a2b2f62ae6f17b49f2c0b4f54b 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -256,15 +256,94 @@ def root(options = {}) match '/', options.reverse_merge(:as => :root) end - # When you set up a regular route, you supply a series of symbols that - # Rails maps to parts of an incoming HTTP request. + # Matches a pattern to one or more urls. Any symbols in a pattern are + # interpreted as url parameters: # - # match ':controller/:action/:id/:user_id' + # # sets parameters :controller, :action and :id + # match ':controller/:action/:id' # - # Two of these symbols are special: :controller maps to the name of a - # controller in your application, and :action maps to the name of an - # action within that controller. Anything other than :controller or - # :action will be available to the action as part of params. + # Two of these symbols are special: :controller maps to the + # controller name and :action to the action name within that + # controller. Anything other than :controller or + # :action will be available to the action as part of +params+. + # If a pattern does not have :controller and :action symbols, then they + # must be set in options or shorthand. For example: + # + # match 'photos/:id' => 'photos#show' + # match 'photos/:id', :to => 'photos#show' + # match 'photos/:id', :controller => 'photos', :action => 'show' + # + # === Supported options + # + # [:controller] + # The route's controller. + # + # [:action] + # The route's action. + # + # [:path] + # The path prefix for the routes. + # + # [:module] + # The namespace for :controller. + # + # match 'path' => 'c#a', :module => 'sekret', :controller => 'posts' + # #=> Sekret::PostsController + # + # See Scoping#namespace for its scope equivalent. + # + # [:as] + # The name used to generate routing helpers. + # + # [:via] + # Allowed HTTP verb(s) for route. + # + # match 'path' => 'c#a', :via => :get + # match 'path' => 'c#a', :via => [:get, :post] + # + # [:to] + # Shorthand for specifying :controller and :action. + # + # match 'path' => 'c#a', :to => 'controller#action' + # + # [:on] + # Shorthand for wrapping routes in a specific RESTful context. Valid + # values are :member, :collection, and :new. Only use within + # resource(s) block. For example: + # + # resource :bar do + # match 'foo' => 'c#a', :on => :member, :via => [:get, :post] + # end + # + # Is equivalent to: + # + # resource :bar do + # member do + # match 'foo' => 'c#a', :via => [:get, :post] + # end + # end + # + # [:constraints] + # Constrains parameters with a hash of regular expressions or an + # object that responds to #matches? + # + # match 'path/:id', :constraints => { :id => /[A-Z]\d{5}/ } + # + # class Blacklist + # def matches?(request) request.remote_ip == '1.2.3.4' end + # end + # match 'path' => 'c#a', :constraints => Blacklist.new + # + # See Scoping#constraints for more examples with its scope + # equivalent. + # + # [:defaults] + # Sets defaults for parameters + # + # # Sets params[:format] to 'jpg' by default + # match 'path' => 'c#a', :defaults => { :format => 'jpg' } + # + # See Scoping#defaults for its scope equivalent. def match(path, options=nil) mapping = Mapping.new(@set, @scope, path, options || {}).to_route @set.add_route(*mapping) @@ -349,7 +428,7 @@ def define_generate_prefix(app, name) module HttpHelpers # Define a route that only recognizes HTTP GET. - # For supported arguments, see +match+. + # For supported arguments, see Base#match. # # Example: # @@ -359,7 +438,7 @@ def get(*args, &block) end # Define a route that only recognizes HTTP POST. - # For supported arguments, see +match+. + # For supported arguments, see Base#match. # # Example: # @@ -369,7 +448,7 @@ def post(*args, &block) end # Define a route that only recognizes HTTP PUT. - # For supported arguments, see +match+. + # For supported arguments, see Base#match. # # Example: # @@ -379,7 +458,7 @@ def put(*args, &block) end # Define a route that only recognizes HTTP PUT. - # For supported arguments, see +match+. + # For supported arguments, see Base#match. # # Example: # @@ -458,7 +537,7 @@ def initialize(*args) #:nodoc: super end - # Used to scope a set of routes to particular constraints. + # Scopes a set of routes to the given default options. # # Take the following route definition as an example: # @@ -471,50 +550,25 @@ def initialize(*args) #:nodoc: # rather than /accounts/rails/projects/2. # # === Supported options - # [:module] - # If you want to route /posts (without the prefix /admin) to - # Admin::PostsController, you could use - # - # scope :module => "admin" do - # resources :posts - # end - # - # [:path] - # If you want to prefix the route, you could use - # - # scope :path => "/admin" do - # resources :posts - # end # - # This will prefix all of the +posts+ resource's requests with '/admin' + # Takes same options as Base#match and Resources#resources. # - # [:as] - # Prefixes the routing helpers in this scope with the specified label. - # - # scope :as => "sekret" do - # resources :posts - # end - # - # Helpers such as +posts_path+ will now be +sekret_posts_path+ - # - # [:shallow_path] - # - # Prefixes nested shallow routes with the specified path. + # === Examples # - # scope :shallow_path => "sekret" do - # resources :posts do - # resources :comments, :shallow => true - # end + # # route /posts (without the prefix /admin) to Admin::PostsController + # scope :module => "admin" do + # resources :posts + # end # - # The +comments+ resource here will have the following routes generated for it: + # # prefix the posts resource's requests with '/admin' + # scope :path => "/admin" do + # resources :posts + # end # - # post_comments GET /sekret/posts/:post_id/comments(.:format) - # post_comments POST /sekret/posts/:post_id/comments(.:format) - # new_post_comment GET /sekret/posts/:post_id/comments/new(.:format) - # edit_comment GET /sekret/comments/:id/edit(.:format) - # comment GET /sekret/comments/:id(.:format) - # comment PUT /sekret/comments/:id(.:format) - # comment DELETE /sekret/comments/:id(.:format) + # # prefix the routing helper name: sekret_posts_path instead of posts_path + # scope :as => "sekret" do + # resources :posts + # end def scope(*args) options = args.extract_options! options = options.dup @@ -577,43 +631,31 @@ def controller(controller, options={}) # admin_post GET /admin/posts/:id(.:format) {:action=>"show", :controller=>"admin/posts"} # admin_post PUT /admin/posts/:id(.:format) {:action=>"update", :controller=>"admin/posts"} # admin_post DELETE /admin/posts/:id(.:format) {:action=>"destroy", :controller=>"admin/posts"} - # === Supported options - # - # The +:path+, +:as+, +:module+, +:shallow_path+ and +:shallow_prefix+ options all default to the name of the namespace. - # - # [:path] - # The path prefix for the routes. # - # namespace :admin, :path => "sekret" do - # resources :posts - # end - # - # All routes for the above +resources+ will be accessible through +/sekret/posts+, rather than +/admin/posts+ - # - # [:module] - # The namespace for the controllers. + # === Supported options # - # namespace :admin, :module => "sekret" do - # resources :posts - # end + # The +:path+, +:as+, +:module+, +:shallow_path+ and +:shallow_prefix+ + # options all default to the name of the namespace. # - # The +PostsController+ here should go in the +Sekret+ namespace and so it should be defined like this: + # For options, see Base#match. For +:shallow_path+ option, see + # Resources#resources. # - # class Sekret::PostsController < ApplicationController - # # code go here - # end + # === Examples # - # [:as] - # Changes the name used in routing helpers for this namespace. - # - # namespace :admin, :as => "sekret" do - # resources :posts - # end + # # accessible through /sekret/posts rather than /admin/posts + # namespace :admin, :path => "sekret" do + # resources :posts + # end # - # Routing helpers such as +admin_posts_path+ will now be +sekret_posts_path+. + # # maps to Sekret::PostsController rather than Admin::PostsController + # namespace :admin, :module => "sekret" do + # resources :posts + # end # - # [:shallow_path] - # See the +scope+ method. + # # generates sekret_posts_path rather than admin_posts_path + # namespace :admin, :as => "sekret" do + # resources :posts + # end def namespace(path, options = {}) path = path.to_s options = { :path => path, :as => path, :module => path, @@ -680,9 +722,9 @@ def constraints(constraints = {}) end # Allows you to set default parameters for a route, such as this: - # defaults :id => 'home' do - # match 'scoped_pages/(:id)', :to => 'pages#show' - # end + # defaults :id => 'home' do + # match 'scoped_pages/(:id)', :to => 'pages#show' + # end # Using this, the +:id+ parameter here will default to 'home'. def defaults(defaults = {}) scope(:defaults => defaults) { yield } @@ -827,7 +869,8 @@ def singular alias :member_name :singular - # Checks for uncountable plurals, and appends "_index" if they're. + # Checks for uncountable plurals, and appends "_index" if the plural + # and singular form are the same. def collection_name singular == plural ? "#{plural}_index" : plural end @@ -906,6 +949,9 @@ def resources_path_names(options) # GET /geocoder/edit # PUT /geocoder # DELETE /geocoder + # + # === Supported options + # Takes same options as +resources+. def resource(*resources, &block) options = resources.extract_options! @@ -968,6 +1014,8 @@ def resource(*resources, &block) # DELETE /photos/:id/comments/:id # # === Supported options + # Takes same options as Base#match as well as: + # # [:path_names] # Allows you to change the paths of the seven default actions. # Paths not specified are not changed. @@ -976,20 +1024,60 @@ def resource(*resources, &block) # # The above example will now change /posts/new to /posts/brand_new # - # [:module] - # Set the module where the controller can be found. Defaults to nothing. + # [:only] + # Only generate routes for the given actions. # - # resources :posts, :module => "admin" + # resources :cows, :only => :show + # resources :cows, :only => [:show, :index] # - # All requests to the posts resources will now go to +Admin::PostsController+. + # [:except] + # Generate all routes except for the given actions. # - # [:path] + # resources :cows, :except => :show + # resources :cows, :except => [:show, :index] + # + # [:shallow] + # Generates shallow routes for nested resource(s). When placed on a parent resource, + # generates shallow routes for all nested resources. + # + # resources :posts, :shallow => true do + # resources :comments + # end + # + # Is the same as: + # + # resources :posts do + # resources :comments + # end + # resources :comments + # + # [:shallow_path] + # Prefixes nested shallow routes with the specified path. + # + # scope :shallow_path => "sekret" do + # resources :posts do + # resources :comments, :shallow => true + # end + # end + # + # The +comments+ resource here will have the following routes generated for it: + # + # post_comments GET /sekret/posts/:post_id/comments(.:format) + # post_comments POST /sekret/posts/:post_id/comments(.:format) + # new_post_comment GET /sekret/posts/:post_id/comments/new(.:format) + # edit_comment GET /sekret/comments/:id/edit(.:format) + # comment GET /sekret/comments/:id(.:format) + # comment PUT /sekret/comments/:id(.:format) + # comment DELETE /sekret/comments/:id(.:format) + # + # === Examples # - # Set a path prefix for this resource. + # # routes call Admin::PostsController + # resources :posts, :module => "admin" # - # resources :posts, :path => "admin" + # # resource actions are at /admin/posts. + # resources :posts, :path => "admin" # - # All actions for this resource will now be at +/admin/posts+. def resources(*resources, &block) options = resources.extract_options! diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb index 1558c3ae05c21a1e4493857a25d1c629a4e807c2..77a15f3e97943c048d183824d14cc840ca03ca66 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/response.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb @@ -20,7 +20,7 @@ module ResponseAssertions # # You can also pass an explicit status number like assert_response(501) # or its symbolic equivalent assert_response(:not_implemented). - # See ActionDispatch::StatusCodes for a full list. + # See Rack::Utils::SYMBOL_TO_STATUS_CODE for a full list. # # ==== Examples # diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index 67f88b40885a7b977c605d14e18bbea41d8c8056..34669c1542c0b5e02d6f3ce842ea670ae564adeb 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -237,7 +237,7 @@ def #{matcher.method_name(new_name)}(*args) end end - # Declares a the attributes that should be prefixed and suffixed by + # Declares the attributes that should be prefixed and suffixed by # ActiveModel::AttributeMethods. # # To use, pass in an array of attribute names (as strings or symbols), diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index c592490c84a257967e805c11fe273881f966aa6a..094170080378c13f718f40ee9f8a432b0626d40c 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -779,7 +779,7 @@ def finder_needs_type_condition? #:nodoc: :true == (@finder_needs_type_condition ||= descends_from_active_record? ? :false : :true) end - # Returns a string like 'Post id:integer, title:string, body:text' + # Returns a string like 'Post(id:integer, title:string, body:text)' def inspect if self == Base super diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb index 8f137e3b21c01e37c7d97c81868936f64510072e..ff4ce1b6053eeb2ecbb6aa72c0118753b4ace5e7 100644 --- a/activerecord/lib/active_record/callbacks.rb +++ b/activerecord/lib/active_record/callbacks.rb @@ -25,9 +25,13 @@ module ActiveRecord # Check out ActiveRecord::Transactions for more details about after_commit and # after_rollback. # - # That's a total of ten callbacks, which gives you immense power to react and prepare for each state in the + # Lastly an after_find and after_initialize callback is triggered for each object that + # is found and instantiated by a finder, with after_initialize being triggered after new objects + # are instantiated as well. + # + # That's a total of twelve callbacks, which gives you immense power to react and prepare for each state in the # Active Record life cycle. The sequence for calling Base#save for an existing record is similar, - # except that each _on_create callback is replaced by the corresponding _on_update callback. + # except that each _create callback is replaced by the corresponding _update callback. # # Examples: # class CreditCard < ActiveRecord::Base @@ -185,14 +189,6 @@ module ActiveRecord # 'puts "Evaluated after parents are destroyed"' # end # - # == The +after_find+ and +after_initialize+ exceptions - # - # Because +after_find+ and +after_initialize+ are called for each object found and instantiated by a finder, - # such as Base.find(:all), we've had to implement a simple performance constraint (50% more speed - # on a simple test case). Unlike all the other callbacks, +after_find+ and +after_initialize+ will only be - # run if an explicit implementation is defined (def after_find). In that case, all of the - # callback types will be called. - # # == before_validation* returning statements # # If the returning value of a +before_validation+ callback can be evaluated to +false+, the process will be diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb index d959fd103acd55a7aec387b14c76cf4f433e1bc0..daa8962929a88b2a752c52b35ec00897038e9bfb 100644 --- a/activeresource/lib/active_resource/base.rb +++ b/activeresource/lib/active_resource/base.rb @@ -200,7 +200,7 @@ module ActiveResource # an ActiveResource::MissingPrefixParam will be raised. # # class Comment < ActiveResource::Base - # self.site = "http://someip.com/posts/:post_id/" + # self.site = "http://someip.com/posts/:post_id/" # end # # Comment.find(1) @@ -1095,7 +1095,7 @@ def eql?(other) end # Delegates to id in order to allow two resources of the same type and \id to work with something like: - # [Person.find(1), Person.find(2)] & [Person.find(1), Person.find(4)] # => [Person.find(1)] + # [(a = Person.find 1), (b = Person.find 2)] & [(c = Person.find 1), (d = Person.find 4)] # => [a] def hash id.hash end diff --git a/railties/guides/source/action_controller_overview.textile b/railties/guides/source/action_controller_overview.textile index 8f9afb9c6df1859f81aaee06e8564d8fe05292a4..be015c4f9b15c1d844e679c1e8d0eac8147dc00b 100644 --- a/railties/guides/source/action_controller_overview.textile +++ b/railties/guides/source/action_controller_overview.textile @@ -737,16 +737,12 @@ GET /clients/1.pdf h3. Parameter Filtering -Rails keeps a log file for each environment in the +log+ folder. These are extremely useful when debugging what's actually going on in your application, but in a live application you may not want every bit of information to be stored in the log file. The +filter_parameter_logging+ method can be used to filter out sensitive information from the log. It works by replacing certain values in the +params+ hash with "[FILTERED]" as they are written to the log. As an example, let's see how to filter all parameters with keys that include "password": +Rails keeps a log file for each environment in the +log+ folder. These are extremely useful when debugging what's actually going on in your application, but in a live application you may not want every bit of information to be stored in the log file. You can filter certain request parameters from your log files by appending them to config.filter_parameters in the application configuration. These parameters will be marked [FILTERED] in the log. -class ApplicationController < ActionController::Base - filter_parameter_logging :password -end +config.filter_parameters << :password -The method works recursively through all levels of the +params+ hash and takes an optional second parameter which is used as the replacement string if present. It can also take a block which receives each key in turn and replaces those for which the block returns true. - h3. Rescue Most likely your application is going to contain bugs or otherwise throw an exception that needs to be handled. For example, if the user follows a link to a resource that no longer exists in the database, Active Record will throw the +ActiveRecord::RecordNotFound+ exception. diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index c283a9bd99bcf7b0a0cdf21107c6bd282e25bcf5..cf9ebf44e6b81b1f1c5e8994c9098d98942f88fd 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -2007,7 +2007,7 @@ User.exists?(:email => params[:email]) That syntactic sugar is used a lot in Rails to avoid positional arguments where there would be too many, offering instead interfaces that emulate named parameters. In particular it is very idiomatic to use a trailing hash for options. -If a method expects a variable number of arguments and uses * in its declaration, however, such an options hash ends up being an item of the array of arguments, where kind of loses its role. +If a method expects a variable number of arguments and uses * in its declaration, however, such an options hash ends up being an item of the array of arguments, where it loses its role. In those cases, you may give an options hash a distinguished treatment with +extract_options!+. That method checks the type of the last item of an array. If it is a hash it pops it and returns it, otherwise returns an empty hash. diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile index f0e40b0980249c8c111aef31af754c6abd29953d..fe400d3358d8f22382ad8502c725f366ba304415 100644 --- a/railties/guides/source/layouts_and_rendering.textile +++ b/railties/guides/source/layouts_and_rendering.textile @@ -211,7 +211,7 @@ h5. Wrapping it up The above three ways of rendering (rendering another template within the controller, rendering a template within another controller and rendering an arbitrary file on the file system) are actually variants of the same action. -In fact, in the BooksController class, inside of the edit action where we want to render the edit template if the book does not update successfully, all of the following render calls would all render the +edit.html.erb+ template in the +views/books+ directory: +In fact, in the BooksController class, inside of the update action where we want to render the edit template if the book does not update successfully, all of the following render calls would all render the +edit.html.erb+ template in the +views/books+ directory: render :edit diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile index 5f0889f406515adcfe9d1b7274b7124985e68ed4..a6d70da76c3d5eb2f90dbf2af73f7f433a0550f6 100644 --- a/railties/guides/source/testing.textile +++ b/railties/guides/source/testing.textile @@ -582,7 +582,7 @@ assert_select "ol" do end -The +assert_select+ assertion is quite powerful. For more advanced usage, refer to its "documentation":http://api.rubyonrails.org/classes/ActionController/Assertions/SelectorAssertions.html. +The +assert_select+ assertion is quite powerful. For more advanced usage, refer to its "documentation":http://api.rubyonrails.org/classes/ActionDispatch/Assertions/SelectorAssertions.html. h5. Additional View-Based Assertions diff --git a/railties/lib/rails/generators/test_case.rb b/railties/lib/rails/generators/test_case.rb index cab8708be3a74763544ed32c9dbdbdf89c01fee6..ee85b70bb511c710977bc2dc4d35e4c8ce2d1c27 100644 --- a/railties/lib/rails/generators/test_case.rb +++ b/railties/lib/rails/generators/test_case.rb @@ -114,7 +114,7 @@ def assert_no_file(relative) end alias :assert_no_directory :assert_no_file - # Asserts a given file does not exist. You need to supply an absolute path or a + # Asserts a given migration exists. You need to supply an absolute path or a # path relative to the configured destination: # # assert_migration "db/migrate/create_products.rb"