diff --git a/guides/source/rails_on_rack.md b/guides/source/rails_on_rack.md index 0e59395c8a718badaa3ce09fb517e69c8a30dec8..ba96c0c0a9667c5b0452b8a9254aad1438fdddc8 100644 --- a/guides/source/rails_on_rack.md +++ b/guides/source/rails_on_rack.md @@ -162,8 +162,8 @@ You can add a new middleware to the middleware stack using any of the following config.middleware.use Rack::BounceFavicon # Add Lifo::Cache after ActiveRecord::QueryCache. -# Pass { :page_cache => false } argument to Lifo::Cache. -config.middleware.insert_after ActiveRecord::QueryCache, Lifo::Cache, :page_cache => false +# Pass { page_cache: false } argument to Lifo::Cache. +config.middleware.insert_after ActiveRecord::QueryCache, Lifo::Cache, page_cache: false ``` #### Swapping a Middleware diff --git a/guides/source/routing.md b/guides/source/routing.md index 3acb7fa0e517d3635b50dbaba4d15a0efa4fc55c..469fcf49fb1e46c21dbd3e2a53c0201497d61979 100644 --- a/guides/source/routing.md +++ b/guides/source/routing.md @@ -30,14 +30,14 @@ it asks the router to match it to a controller action. If the first matching rou get "/patients/:id" => "patients#show" ``` -the request is dispatched to the `patients` controller's `show` action with `{ :id => "17" }` in `params`. +the request is dispatched to the `patients` controller's `show` action with `{ id: "17" }` in `params`. ### Generating Paths and URLs from Code You can also generate paths and URLs. If the route above is modified to be ```ruby -get "/patients/:id" => "patients#show", :as => "patient" +get "/patients/:id" => "patients#show", as: "patient" ``` If your application contains this code: @@ -73,7 +73,7 @@ it asks the router to map it to a controller action. If the first matching route resources :photos ``` -Rails would dispatch that request to the `destroy` method on the `photos` controller with `{ :id => "17" }` in `params`. +Rails would dispatch that request to the `destroy` method on the `photos` controller with `{ id: "17" }` in `params`. ### CRUD, Verbs, and Actions @@ -186,7 +186,7 @@ This will create a number of routes for each of the `posts` and `comments` contr If you want to route `/posts` (without the prefix `/admin`) to `Admin::PostsController`, you could use ```ruby -scope :module => "admin" do +scope module: "admin" do resources :posts, :comments end ``` @@ -194,7 +194,7 @@ end or, for a single case ```ruby -resources :posts, :module => "admin" +resources :posts, module: "admin" ``` If you want to route `/admin/posts` to `PostsController` (without the `Admin::` module prefix), you could use @@ -208,7 +208,7 @@ end or, for a single case ```ruby -resources :posts, :path => "/admin/posts" +resources :posts, path: "/admin/posts" ``` In each of these cases, the named routes remain the same as if you did not use `scope`. In the last case, the following paths map to `PostsController`: @@ -375,7 +375,7 @@ Within the block of member routes, each route name specifies the HTTP verb that ```ruby resources :photos do - get 'preview', :on => :member + get 'preview', on: :member end ``` @@ -397,7 +397,7 @@ Just as with member routes, you can pass `:on` to a route: ```ruby resources :photos do - get 'search', :on => :collection + get 'search', on: :collection end ``` @@ -407,7 +407,7 @@ To add an alternate new action using the `:on` shortcut: ```ruby resources :comments do - get 'preview', :on => :new + get 'preview', on: :new end ``` @@ -449,10 +449,10 @@ An incoming path of `/photos/show/1/2` will be dispatched to the `show` action o NOTE: You can't use `:namespace` or `:module` with a `:controller` path segment. If you need to do this then use a constraint on :controller that matches the namespace you require. e.g: ```ruby -get ':controller(/:action(/:id))', :controller => /admin\/[^\/]+/ +get ':controller(/:action(/:id))', controller: /admin\/[^\/]+/ ``` -TIP: By default dynamic segments don't accept dots - this is because the dot is used as a separator for formatted routes. If you need to use a dot within a dynamic segment, add a constraint that overrides this – for example, `:id => /[^\/]+/` allows anything except a slash. +TIP: By default dynamic segments don't accept dots - this is because the dot is used as a separator for formatted routes. If you need to use a dot within a dynamic segment, add a constraint that overrides this – for example, `id: /[^\/]+/` allows anything except a slash. ### Static Segments @@ -462,7 +462,7 @@ You can specify static segments when creating a route: get ':controller/:action/:id/with_user/:user_id' ``` -This route would respond to paths such as `/photos/show/1/with_user/2`. In this case, `params` would be `{ :controller => "photos", :action => "show", :id => "1", :user_id => "2" }`. +This route would respond to paths such as `/photos/show/1/with_user/2`. In this case, `params` would be `{ controller: "photos", action: "show", id: "1", user_id: "2" }`. ### The Query String @@ -472,7 +472,7 @@ The `params` will also include any parameters from the query string. For example get ':controller/:action/:id' ``` -An incoming path of `/photos/show/1?user_id=2` will be dispatched to the `show` action of the `Photos` controller. `params` will be `{ :controller => "photos", :action => "show", :id => "1", :user_id => "2" }`. +An incoming path of `/photos/show/1?user_id=2` will be dispatched to the `show` action of the `Photos` controller. `params` will be `{ controller: "photos", action: "show", id: "1", user_id: "2" }`. ### Defining Defaults @@ -487,7 +487,7 @@ With this route, Rails will match an incoming path of `/photos/12` to the `show` You can also define other defaults in a route by supplying a hash for the `:defaults` option. This even applies to parameters that you do not specify as dynamic segments. For example: ```ruby -get 'photos/:id' => 'photos#show', :defaults => { :format => 'jpg' } +get 'photos/:id' => 'photos#show', defaults: { format: 'jpg' } ``` Rails would match `photos/12` to the `show` action of `PhotosController`, and set `params[:format]` to `"jpg"`. @@ -497,7 +497,7 @@ Rails would match `photos/12` to the `show` action of `PhotosController`, and se You can specify a name for any route using the `:as` option. ```ruby -get 'exit' => 'sessions#destroy', :as => :logout +get 'exit' => 'sessions#destroy', as: :logout ``` This will create `logout_path` and `logout_url` as named helpers in your application. Calling `logout_path` will return `/exit` @@ -505,7 +505,7 @@ This will create `logout_path` and `logout_url` as named helpers in your applica You can also use this to override routing methods defined by resources, like this: ```ruby -get ':username', :to => "users#show", :as => :user +get ':username', to: "users#show", as: :user ``` This will define a `user_path` method that will be available in controllers, helpers and views that will go to a route such as `/bob`. Inside the `show` action of `UsersController`, `params[:username]` will contain the username for the user. Change `:username` in the route definition if you do not want your parameter name to be `:username`. @@ -515,13 +515,13 @@ This will define a `user_path` method that will be available in controllers, hel In general, you should use the `get`, `post`, `put` and `delete` methods to constrain a route to a particular verb. You can use the `match` method with the `:via` option to match multiple verbs at once: ```ruby -match 'photos' => 'photos#show', :via => [:get, :post] +match 'photos' => 'photos#show', via: [:get, :post] ``` -You can match all verbs to a particular route using `:via => :all`: +You can match all verbs to a particular route using `via: :all`: ```ruby -match 'photos' => 'photos#show', :via => :all +match 'photos' => 'photos#show', via: :all ``` You should avoid routing all verbs to an action unless you have a good reason to, as routing both `GET` requests and `POST` requests to a single action has security implications. @@ -531,19 +531,19 @@ You should avoid routing all verbs to an action unless you have a good reason to You can use the `:constraints` option to enforce a format for a dynamic segment: ```ruby -get 'photos/:id' => 'photos#show', :constraints => { :id => /[A-Z]\d{5}/ } +get 'photos/:id' => 'photos#show', constraints: { id: /[A-Z]\d{5}/ } ``` This route would match paths such as `/photos/A12345`. You can more succinctly express the same route this way: ```ruby -get 'photos/:id' => 'photos#show', :id => /[A-Z]\d{5}/ +get 'photos/:id' => 'photos#show', id: /[A-Z]\d{5}/ ``` `:constraints` takes regular expressions with the restriction that regexp anchors can't be used. For example, the following route will not work: ```ruby -get '/:id' => 'posts#show', :constraints => {:id => /^\d/} +get '/:id' => 'posts#show', constraints: {id: /^\d/} ``` However, note that you don't need to use anchors because all routes are anchored at the start. @@ -551,7 +551,7 @@ However, note that you don't need to use anchors because all routes are anchored For example, the following routes would allow for `posts` with `to_param` values like `1-hello-world` that always begin with a number and `users` with `to_param` values like `david` that never begin with a number to share the root namespace: ```ruby -get '/:id' => 'posts#show', :constraints => { :id => /\d.+/ } +get '/:id' => 'posts#show', constraints: { id: /\d.+/ } get '/:username' => 'users#show' ``` @@ -562,14 +562,14 @@ You can also constrain a route based on any method on the {:subdomain => "admin"} +get "photos", constraints: {subdomain: "admin"} ``` You can also specify constraints in a block form: ```ruby namespace :admin do - constraints :subdomain => "admin" do + constraints subdomain: "admin" do resources :photos end end @@ -592,7 +592,7 @@ end TwitterClone::Application.routes.draw do get "*path" => "blacklist#index", - :constraints => BlacklistConstraint.new + constraints: BlacklistConstraint.new end ``` @@ -601,7 +601,7 @@ You can also specify constraints as a lambda: ```ruby TwitterClone::Application.routes.draw do get "*path" => "blacklist#index", - :constraints => lambda { |request| Blacklist.retrieve_ips.include?(request.remote_ip) } + constraints: lambda { |request| Blacklist.retrieve_ips.include?(request.remote_ip) } end ``` @@ -639,16 +639,16 @@ NOTE: Starting from Rails 3.1, wildcard routes will always match the optional fo get '*pages' => 'pages#show' ``` -NOTE: By requesting `"/foo/bar.json"`, your `params[:pages]` will be equals to `"foo/bar"` with the request format of JSON. If you want the old 3.0.x behavior back, you could supply `:format => false` like this: +NOTE: By requesting `"/foo/bar.json"`, your `params[:pages]` will be equals to `"foo/bar"` with the request format of JSON. If you want the old 3.0.x behavior back, you could supply `format: false` like this: ```ruby -get '*pages' => 'pages#show', :format => false +get '*pages' => 'pages#show', format: false ``` -NOTE: If you want to make the format segment mandatory, so it cannot be omitted, you can supply `:format => true` like this: +NOTE: If you want to make the format segment mandatory, so it cannot be omitted, you can supply `format: true` like this: ```ruby -get '*pages' => 'pages#show', :format => true +get '*pages' => 'pages#show', format: true ``` ### Redirection @@ -681,10 +681,10 @@ In all of these cases, if you don't provide the leading host (`http://www.exampl Instead of a String, like `"posts#index"`, which corresponds to the `index` action in the `PostsController`, you can specify any Rack application as the endpoint for a matcher. ```ruby -match "/application.js" => Sprockets, :via => :all +match "/application.js" => Sprockets, via: :all ``` -As long as `Sprockets` responds to `call` and returns a `[status, headers, body]`, the router won't know the difference between the Rack application and an action. This is an appropriate use of `:via => :all`, as you will want to allow your Rack application to handle all verbs as it considers appropriate. +As long as `Sprockets` responds to `call` and returns a `[status, headers, body]`, the router won't know the difference between the Rack application and an action. This is an appropriate use of `via: :all`, as you will want to allow your Rack application to handle all verbs as it considers appropriate. NOTE: For the curious, `"posts#index"` actually expands out to `PostsController.action(:index)`, which returns a valid Rack application. @@ -693,7 +693,7 @@ NOTE: For the curious, `"posts#index"` actually expands out to `PostsController. You can specify what Rails should route `"/"` to with the `root` method: ```ruby -root :to => 'pages#main' +root to: 'pages#main' root 'pages#main' # shortcut for the above ``` @@ -719,7 +719,7 @@ While the default routes and helpers generated by `resources :posts` will usuall The `:controller` option lets you explicitly specify a controller to use for the resource. For example: ```ruby -resources :photos, :controller => "images" +resources :photos, controller: "images" ``` will recognize incoming paths beginning with `/photos` but route to the `Images` controller: @@ -741,7 +741,7 @@ NOTE: Use `photos_path`, `new_photo_path`, etc. to generate paths for this resou You can use the `:constraints` option to specify a required format on the implicit `id`. For example: ```ruby -resources :photos, :constraints => {:id => /[A-Z][A-Z][0-9]+/} +resources :photos, constraints: {id: /[A-Z][A-Z][0-9]+/} ``` This declaration constrains the `:id` parameter to match the supplied regular expression. So, in this case, the router would no longer match `/photos/1` to this route. Instead, `/photos/RR27` would match. @@ -749,7 +749,7 @@ This declaration constrains the `:id` parameter to match the supplied regular ex You can specify a single constraint to apply to a number of routes by using the block form: ```ruby -constraints(:id => /[A-Z][A-Z][0-9]+/) do +constraints(id: /[A-Z][A-Z][0-9]+/) do resources :photos resources :accounts end @@ -757,14 +757,14 @@ end NOTE: Of course, you can use the more advanced constraints available in non-resourceful routes in this context. -TIP: By default the `:id` parameter doesn't accept dots - this is because the dot is used as a separator for formatted routes. If you need to use a dot within an `:id` add a constraint which overrides this - for example `:id => /[^\/]+/` allows anything except a slash. +TIP: By default the `:id` parameter doesn't accept dots - this is because the dot is used as a separator for formatted routes. If you need to use a dot within an `:id` add a constraint which overrides this - for example `id: /[^\/]+/` allows anything except a slash. ### Overriding the Named Helpers The `:as` option lets you override the normal naming for the named route helpers. For example: ```ruby -resources :photos, :as => "images" +resources :photos, as: "images" ``` will recognize incoming paths beginning with `/photos` and route the requests to `PhotosController`, but use the value of the :as option to name the helpers. @@ -784,7 +784,7 @@ will recognize incoming paths beginning with `/photos` and route the requests to The `:path_names` option lets you override the automatically-generated "new" and "edit" segments in paths: ```ruby -resources :photos, :path_names => { :new => 'make', :edit => 'change' } +resources :photos, path_names: { new: 'make', edit: 'change' } ``` This would cause the routing to recognize paths such as @@ -799,7 +799,7 @@ NOTE: The actual action names aren't changed by this option. The two paths shown TIP: If you find yourself wanting to change this option uniformly for all of your routes, you can use a scope. ```ruby -scope :path_names => { :new => "make" } do +scope path_names: { new: "make" } do # rest of your routes end ``` @@ -810,7 +810,7 @@ You can use the `:as` option to prefix the named route helpers that Rails genera ```ruby scope "admin" do - resources :photos, :as => "admin_photos" + resources :photos, as: "admin_photos" end resources :photos @@ -821,7 +821,7 @@ This will provide route helpers such as `admin_photos_path`, `new_admin_photo_pa To prefix a group of route helpers, use `:as` with `scope`: ```ruby -scope "admin", :as => "admin" do +scope "admin", as: "admin" do resources :photos, :accounts end @@ -847,7 +847,7 @@ This will provide you with URLs such as `/bob/posts/1` and will allow you to ref By default, Rails creates routes for the seven default actions (index, show, new, create, edit, update, and destroy) for every RESTful route in your application. You can use the `:only` and `:except` options to fine-tune this behavior. The `:only` option tells Rails to create only the specified routes: ```ruby -resources :photos, :only => [:index, :show] +resources :photos, only: [:index, :show] ``` Now, a `GET` request to `/photos` would succeed, but a `POST` request to `/photos` (which would ordinarily be routed to the `create` action) will fail. @@ -855,7 +855,7 @@ Now, a `GET` request to `/photos` would succeed, but a `POST` request to `/photo The `:except` option specifies a route or list of routes that Rails should _not_ create: ```ruby -resources :photos, :except => :destroy +resources :photos, except: :destroy ``` In this case, Rails will create all of the normal routes except the route for `destroy` (a `DELETE` request to `/photos/:id`). @@ -867,8 +867,8 @@ TIP: If your application has many RESTful routes, using `:only` and `:except` to Using `scope`, we can alter path names generated by resources: ```ruby -scope(:path_names => { :new => "neu", :edit => "bearbeiten" }) do - resources :categories, :path => "kategorien" +scope(path_names: { new: "neu", edit: "bearbeiten" }) do + resources :categories, path: "kategorien" end ``` @@ -900,7 +900,7 @@ The `:as` option overrides the automatically-generated name for the resource in ```ruby resources :magazines do - resources :ads, :as => 'periodical_ads' + resources :ads, as: 'periodical_ads' end ``` @@ -952,8 +952,8 @@ Routes should be included in your testing strategy (just like the rest of your a `assert_generates` asserts that a particular set of options generate a particular path and can be used with default routes or custom routes. ```ruby -assert_generates "/photos/1", { :controller => "photos", :action => "show", :id => "1" } -assert_generates "/about", :controller => "pages", :action => "about" +assert_generates "/photos/1", { controller: "photos", action: "show", id: "1" } +assert_generates "/about", controller: "pages", action: "about" ``` #### The `assert_recognizes` Assertion @@ -961,13 +961,13 @@ assert_generates "/about", :controller => "pages", :action => "about" `assert_recognizes` is the inverse of `assert_generates`. It asserts that a given path is recognized and routes it to a particular spot in your application. ```ruby -assert_recognizes({ :controller => "photos", :action => "show", :id => "1" }, "/photos/1") +assert_recognizes({ controller: "photos", action: "show", id: "1" }, "/photos/1") ``` You can supply a `:method` argument to specify the HTTP verb: ```ruby -assert_recognizes({ :controller => "photos", :action => "create" }, { :path => "photos", :method => :post }) +assert_recognizes({ controller: "photos", action: "create" }, { path: "photos", method: :post }) ``` #### The `assert_routing` Assertion @@ -975,5 +975,5 @@ assert_recognizes({ :controller => "photos", :action => "create" }, { :path => " The `assert_routing` assertion checks the route both ways: it tests that the path generates the options, and that the options generate the path. Thus, it combines the functions of `assert_generates` and `assert_recognizes`. ```ruby -assert_routing({ :path => "photos", :method => :post }, { :controller => "photos", :action => "create" }) +assert_routing({ path: "photos", method: :post }, { controller: "photos", action: "create" }) ``` diff --git a/guides/source/security.md b/guides/source/security.md index 2f9aebae9b331a23ab1496f25b49ea01c90b3c5f..5ef68d22722f764f69078992720a31cd0fe1371b 100644 --- a/guides/source/security.md +++ b/guides/source/security.md @@ -96,8 +96,8 @@ That means the security of this storage depends on this secret (and on the diges ```ruby config.action_dispatch.session = { - :key => '_app_session', - :secret => '0x0dkfj3927dkc7djdh36rkckdfzsg...' + key: '_app_session', + secret: '0x0dkfj3927dkc7djdh36rkckdfzsg...' } ``` @@ -233,7 +233,7 @@ Or the attacker places the code into the onmouseover event handler of an image: There are many other possibilities, including Ajax to attack the victim in the background.
The _solution to this is including a security token in non-GET requests_ which check on the server-side. In Rails 2 or higher, this is a one-liner in the application controller: ```ruby -protect_from_forgery :secret => "123456789012345678901234567890..." +protect_from_forgery secret: "123456789012345678901234567890..." ``` This will automatically include a security token, calculated from the current session and the server-side secret, in all forms and Ajax requests generated by Rails. You won't need the secret, if you use CookieStorage as session storage. If the security token doesn't match what was expected, the session will be reset. **Note:** In Rails versions prior to 3.0.4, this raised an `ActionController::InvalidAuthenticityToken` error. @@ -264,7 +264,7 @@ Whenever the user is allowed to pass (parts of) the URL for redirection, it is p ```ruby def legacy - redirect_to(params.update(:action=>'main')) + redirect_to(params.update(action:'main')) end ``` @@ -334,7 +334,7 @@ basename = File.expand_path(File.join(File.dirname(__FILE__), '../../files')) filename = File.expand_path(File.join(basename, @file.public_filename)) raise if basename != File.expand_path(File.join(File.dirname(filename), '../../../')) -send_file filename, :disposition => 'inline' +send_file filename, disposition: 'inline' ``` Another (additional) approach is to store the file names in the database and name the files on the disk after the ids in the database. This is also a good approach to avoid possible code in an uploaded file to be executed. The attachment_fu plugin does this in a similar way. @@ -383,7 +383,7 @@ any model's attributes by manipulating the hash passed to a model's `new()` meth ```ruby def signup - params[:user] # => {:name=>"ow3ned", :admin=>true} + params[:user] # => {name:"ow3ned", admin:true} @user = User.new(params[:user]) end ``` @@ -402,7 +402,7 @@ http://www.example.com/user/signup?user[name]=ow3ned&user[admin]=1 This will set the following parameters in the controller: ```ruby -params[:user] # => {:name=>"ow3ned", :admin=>true} +params[:user] # => {name:"ow3ned", admin:true} ``` So if you create a new user using mass-assignment, it may be too easy to become @@ -459,9 +459,9 @@ should be allowed for mass updating using the slice pattern. For example: ```ruby def signup params[:user] - # => {:name=>"ow3ned", :admin=>true} + # => {name:"ow3ned", admin:true} permitted_params = params.require(:user).permit(:name) - # => {:name=>"ow3ned"} + # => {name:"ow3ned"} @user = User.new(permitted_params) end @@ -648,7 +648,7 @@ Since this is a frequent mistake, the format validator (validates_format_of) now ```ruby # content should include a line "Meanwhile" anywhere in the string - validates :content, :format => { :with => /^Meanwhile$/, :multiline => true } + validates :content, format: { with: /^Meanwhile$/, multiline: true } ``` Note that this only protects you against the most common mistake when using the format validator - you always need to keep in mind that ^ and $ match the **line** beginning and line end in Ruby, and not the beginning and end of a string. @@ -686,7 +686,7 @@ NOTE: _When sanitizing, protecting or verifying something, whitelists over black A blacklist can be a list of bad e-mail addresses, non-public actions or bad HTML tags. This is opposed to a whitelist which lists the good e-mail addresses, public actions, good HTML tags and so on. Although sometimes it is not possible to create a whitelist (in a SPAM filter, for example), _prefer to use whitelist approaches_: -* Use before_filter :only => [...] instead of :except => [...]. This way you don't forget to turn it off for newly added actions. +* Use before_filter only: [...] instead of except: [...]. This way you don't forget to turn it off for newly added actions. * Use attr_accessible instead of attr_protected. See the mass-assignment section for details * Allow <strong> instead of removing <script> against Cross-Site Scripting (XSS). See below for details. * Don't try to correct user input by blacklists: @@ -769,7 +769,7 @@ Model.where("login = ? AND password = ?", entered_user_name, entered_password).f As you can see, the first part of the array is an SQL fragment with question marks. The sanitized versions of the variables in the second part of the array replace the question marks. Or you can pass a hash for the same result: ```ruby -Model.where(:login => entered_user_name, :password => entered_password).first +Model.where(login: entered_user_name, password: entered_password).first ``` The array or hash form is only available in model instances. You can try `sanitize_sql()` elsewhere. _Make it a habit to think about the security consequences when using an external string in SQL_. @@ -864,7 +864,7 @@ This returned "some<script>alert('hello')</script>", which makes an ```ruby tags = %w(a acronym b strong i em li ul ol h1 h2 h3 h4 h5 h6 blockquote br cite sub sup ins p) -s = sanitize(user_input, :tags => tags, :attributes => %w(href title)) +s = sanitize(user_input, tags: tags, attributes: %w(href title)) ``` This allows only the given tags and does a good job, even against all kinds of tricks and malformed tags.