Routing is the first part you should walk in when you want to get started with framework Rails.
get "/dashboard" => "dashboard#index"
=> when the request has the path ‘/dashboard’, the server will route to controller dashboard with action index
There are some definitions we should learn by heart:
- HTTP Verb/method: Rails supports some HTTP method GET, POST, PATCH/PUT (PATCH is new in the modern version) and DELETE.
- Path: it’s the path of URL from request.
- Controller#Action: It identifies the matching controller and action corresponding with the matching path.
- Route Helper: Rails always generates this helper corresponding with the defined route. It’s usually used for Views to shorten path or URL.
* Note: when you look at 2 routes “new” and “edit” above, the route helper put the text action “new”, “edit” in the first left position. That means when you define new “action” inside the collection or member of the route file, the “action” is always placed in the first left position of the route helper. Otherwise, the “action” will take the last right position.
* Use the command “rake routes” to show the list defined routes.
* For listing routes of the controller: “rake routes -c [controller name]”.
ie:
rake routesrake routes -c articlesrake routes -c articles | grep [searching text]
Some keywords use in Route File:
- "as": (alias) override the route helper.
- “to”: (equivalent to “=>”) keyword is used for pointing a path to a “controller#action”
- "path": override the original path or URL that is generated by Rails.
- “constrains”: advance filter option, we could filter by “regrex”, by “user ip”, by “subdomain”, …
- “format”: there are HTML, JSON, XML, SCRIPT, JPG, GIF, CSS, JS, etc.
ie: “/articles.json” => JSON format. The config tells Rails to recognize or exclude the format from the params. (format: true/false) - “controller”: identify the controller will be matched.
- “params”: override the name “id” of “resources”.
- “defaults”: set some default config. ie: defaults: {format: ‘json’}
single route
- We could define a single route begin with “Http verb/method”: get, post, put/patch, delete. We also have “match” to group multiple “Http verb/method” into a line.
ie:
get “/articles” => “articles#index”, as: :articlespost “/articles/:id” => “articles#create”, as: :create_articlesmatch “/articles/import” => “articles#import”, as: import_articles, via: [:get, :post]
- Note: when declaring the “resources”, run “rake routes” and we could see some route_helper are the same BUT with single-route, we could not define the same route_helper using alias like that.
"resources" and "resource":
- It’s been used a lot. It’s a shortcut to define a CRUD route supporting by Rails.
- "resources": declares separate routes "index", "show", "new", "edit", "create", "update" and "destroy". It generates plural pathname “/photos/:id”.
- “resource”: because it’s a single noun, it has the main purpose that manages special record. “resource” declares separate routes the same with “resources” but no "index", no param “:id” support and all path defined with the single noun.
“member” and “collection”
- When you want to define a new “action” for the “resources” or “resource”, you usually use them.
- “member”, it means that it would be one object and could only find an object with param “:id”. So, “member” goes with the path having “:id”.
- "collection", contrast with "member". It means the whole of the class and not go with ":id".
ie:
resouces :articles do
member do
get “publish”, to: “articles#publish”, as: :publish
# path => /articles/:id/publish
# route helper => publish_articles_path
end collection do
get “chart”, to: “articles#chart”, as: :chart
# path => /articles/chart
# route helper => chart_articles_path
end
end
nested resources:
- It describes the relationship between parents and children.
- You could also reduce the dependency of the children's resources, shorten the path by using “shallow”, “shallow block” and “scope shallow_paths”.
ie:
resources :magazines do
resources :ads
end
Concern Resource:
- When a model is with the polymorphic role, it would be declared as a “child” of some others.
ie: Article has_many Comments and Author has_many Comments too. Instead of declaring two nested resources, we could reduce the duplicated code by using “concern”.
ie:
concern :commentable do
resources :comments
endresources :authors, concerns: :commentable
resources :articles, concerns: :commentable
"namespace":
- When you have many controllers having the same purpose and you want to group them together with a “prefix-path-name”
namespace 'admin' do
resources :articles
end
- It prefixes “name” to the path
ie: /admin/articles - All controller-files would be placed inside a folder with that “name”.
ie: app/controllers/admin/articles_controller.rb - alias “as” also is applied with “name”.
ie: admin_articles_path - The controller-class is appended inside module “name”.
module admin do
class ArticlesController
… (the content of controller)
end
end
"scope":
- When you only want to group the path and not thing else.
- When the scope goes with itself and no external method after, it acts like “path”. Only the path is prefixed with that “name”.
ie:
scope 'admin' do
resources :articles
end
# path => "/admin/articles/:id".
scope with method “module”:
- Back to the namespace example, you could see in the file controller is put inside the folder “name” and in the content file there is the “module” wrap the class controller. So, when we “module”, it means the controller file will be put inside a folder “name” and the content will have the wrapping module.
- In a short way, “scope module” the same with “namespace” but no prefix “the path” and no alias “as”.
ie:
scope module: :admin do
resources :articles
end
# path would be the same with "resources :articles"
scope with method "path_names"
- It changes “action verb” in the path or URL.
ie:
scope path_names: {new: 'make', edit: 'customize'} do
resouces :articles
end
=> path new would be: /articles/make
=> path edit would be: /articles/customize/:id
scope with method “shallow_pathes” and “shallow”
- It’s told that the restful URL should only allow a maximum of one nested resource.
- Some actions like edit, update, delete, etc. (member) should stand alone.
- That’s the way that “scope shallow_pathes”, “scope shallow_prefix” and “shallow” were born.
- The different between “shallow” and “shallow_pathes” and “scope shallow_prefix” is:
- “shallow_pathes” prefixes to the “path”.
- “shallow_prefix” prefixes to the “route helper” (alias)
ie:
resources :campaigns do
resources :ad_groups, shallow: true
end
# shallow applies to :ad_groups
# path is shortened. ie: /adgroups/:id/edit
# route_helper is shortened. ie: edit_adgroup_pathshallow do
resources :campaigns do
resources :ad_groups
end
end
# shallow applies for all block inside :campaigns and :ad_groups, but campaign has no parent. So, campaign has no change.scope shallow_path: 'sekret' do
resources :campaigns do
resources :ad_groups, shallow: true
end
end
# shallow applies for :ad_groups
# path edit: /sekret/ad_groups/:id/edit
# route_helper also changes. ie: edit_ad_group_path
# path update: /sekret/ad_groups/:id/
# path delete:/sekret/ad_groups/:id/delete
# path show: /sekret/ad_groups/:idscope shallow_prefix: “sekret” do
resources :campaigns do
resources :ad_groups, shallow: true
end
end
# the route_helpers are applied shallow would be effected.
# ie: edit_ad_group_path => edit_sekret_ad_group_path