Matching and Routes in Rails - ruby-on-rails

I generated a controller and changed the routes but opening the links yields errors on my local server.
Generating controller and routes
rails generate controller StaticPages home about team contact
Change routes.rb
MyApp::Application.routes.draw do
root to: 'static_pages#home'
match '/about', to: 'static_pages#about'
match '/team', to: 'static_pages#team'
match '/contact', to: 'static_pages#contact'
end
The root path work but none of the 'about, 'team', or 'contact' links work. This is the error I get:
"You should not use the match method in your router without specifying an HTTP method. If you want to expose your action to both GET and POST, add via: [:get, :post] option. If you want to expose your action to GET, use get in the router: Instead of: match "controller#action" Do: get "controller#action""
Why can't I use 'match'?

match method has been deprecated.
Use get for GET and post for POST.
get '/about', to: 'static_pages#about'

You can use match, you've gotta add a via: option:
match '/about', to: 'static_pages#about', via: :get
match '/team', to: 'static_pages#team', via: :get
match '/contact', to: 'static_pages#contact', via: :get
You can also pass other HTTP verbs to via: if you need to, like via: [:get, :post]
Source: Rails Routing Guide

First, you must specify the HTTP method by adding via: :get at the end of match 'st' => 'controller#action
And it's better to use get '/home', to: 'static_pages#home'
But, there is a problem, that your code doesn't follow RESTful, that only support 7 actions: index, new, edit, create, update, show and destroy.
These are 2 solutions:
SOL 1: Put them in different controller (homes, abouts..) and all of these controllers have action index.
SOL 2: If it's too much work, we can match them to show action. We use static_pages controller, and each page (home, about) will be a item.
The routes will look likes
/static_pages/home
/static_pages/about
I know it isn't good because of the prefix static_pages.
We can easily get rid of this by adding a custom routes at the end of routes file:
get '/:id', to: 'static_pages#show'
That's it. And if you think it's too much work (I think so too), check out this gem High Voltage. Have fun.

Related

My routes file doesn't match expected result

Thanks in advance for any help.
I'm working my way through Michael Hartl's "learn enough" RoR lessons and am at the point where we're working with authenticating users via sessions.
Per the lesson, I've just run rails generate controller Sessions new and nothing blew chunks:
$ rails generate controller Sessions new
Running via Spring preloader in process 4407
create app/controllers/sessions_controller.rb
route get 'sessions/new'
invoke erb
create app/views/sessions
create app/views/sessions/new.html.erb
invoke test_unit
create test/controllers/sessions_controller_test.rb
invoke helper
create app/helpers/sessions_helper.rb
invoke test_unit
invoke assets
invoke coffee
create app/assets/javascripts/sessions.coffee
invoke scss
create app/assets/stylesheets/sessions.scss
However, there's a discrepancy between what the lesson says routes.rb should look like and what it actually does look like.
Expected result in routes.rb, as implied by the lesson:
Rails.application.routes.draw do
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
resources :users
end
Actual result in routes.rb:
Rails.application.routes.draw do
get 'sessions/new'
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
post '/signup', to: 'users#create'
resources :users
end
Am I missing something obvious? Why the difference?
I feel like there's a missing chapter between here and the last one, which only explains the really high level difference between browser-close-ending sessions and cookie-expired sessions.
You ran rails generate controller Sessions new, which means you want to generate a controller with the new action only. By default, new generates the view route (GET) and the actual resource creation route (POST).
To create the controller and routes following the CRUD pattern, you should run rails generate controller Sessions.
Solved.
The reason for the discrepancy is that rails generate controller Sessions new only generates the GET route #vnbrs mentioned.
The lesson calls for 3 routes that need to be supported: a GET request to the login form, a POST request to create the session, and a DELETE request to destroy the session.
Those need to be added to routes.rb manually:
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
Beginner's disorientation, I couldn't see the forest for the trees and broke my brain. (P.S. I don't recommend trying to tackle this tutorial discontinuously over a series of months...your brain does NOT pick up where it left off.)

Generic Routing match ':controller(/:action(/:id))(.:format)' not available in Rails 4. Way Out?

As far as I read, I understood that Rails 4 doesn't support match keyword.
But I want to make a default generic route something like following
match ':controller(/:action(/:id))(.:format)', :via => :get
When I use above code in routes.rb, it throws me following error:
Missing :action key on routes definition, please check your routes
Can someone help me how to implement this in Rails 4.
Yes it is supported, from the Rails Routing from the Outside In guide
3.7 HTTP Verb Constraints
In general, you should use the get, post, put, patch 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:
match 'photos', to: 'photos#show', via: [:get, :post]
You can match all verbs to a particular route using via: :all:
match 'photos', to: 'photos#show', via: :all
and from the documentation:
http://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Base.html#method-i-match
# sets :controller, :action and :id in params
match ':controller/:action/:id', via: [:get, :post]
If you add this line to your routes:
match ':controller/:action/(:id)', via: :get
it will produce the following route:
Prefix Verb URI Pattern Controller#Action
GET /:controller/:action(/:id)(.:format) :controller#:action

POST / GET not working correctly with Ruby on Rails Root

Im using RoR to write my website and i've run into this issue with routes.
My routes file looks as such
root to: "static#index"
match '/index', to: 'static#index', via: [:get, :post]
match '/download', to: 'static#download', via: [:get, :post]
match '/terms', to: 'static#terms', via: 'get'
match '/privacy', to: 'static#privacy', via: 'get'
match '/jobs', to: 'static#jobs', via: 'get'
match '/android', to: 'static#android', via: [:get, :post]
match '/apply', to: 'static#apply', via: 'get'
match '/faq', to: 'static#faq', via: 'get'
When I preform a GET request to https://www.website.com/ the page gets displayed.
However when I preform a POST request to the same address it returns a 404 page not found.
I do not have a index.html in my public directory.
So why is this POST request returning a 404 when it is matched to both GET and POST and the GET works correctly?
EDIT
i've added this line
match '/', to: 'static#index', via: [:get, :post]
just below my root to declaration, however now my page shows a 422 error instead of a 404
You can try this:
post '/' => "static#index", as: "root"
Rails routes: resourcing from the root path "/"
Your root URL is the one that handles https://www.website.com/ from your example. When you specify
root to: "static#index"
You have declared a GET route for /, which maps to StaticController#index. The POST request that you are making to https://www.website.com/ is not handled by the root route, thus properly returns a 404.
I'm guessing that you want the POST request to go to either /index, /download or /android. You need to specify the endpoint fully in the URL in order for the request to be routed properly.
My preference and I think the cleanest implementation would be:
resources :static, :only => [:index, :create], :path => "/"

Routing to a subdirectory in Rails 4.0?

I am just getting started with RoR and have a basic question.
Currently I am creating simple static_pages e.g. about contact etc, for my application that will route as follow:
root "static_pages#home"
match "/about", to: 'static_pages#about', via: 'get'
match "/contact", to: 'static_pages#contact', via: 'get'
Which will look as follows:
localhost:3000/about
localhost:3000/contact
Now I would to create a sub directory called "legal" with an index page for the directory and other some pages, which will look like:
localhost:3000/legal
localhost3000:/legal/terms
Would I need to create a new controller to do this and include all the action or is there a way I can do this with my "StaticPages" controller some how?
Thanks in advance :)
You can do something like:
scope '/legal' do
match "/about", to: 'static_pages#about', via: 'get'
match "/contact", to: 'static_pages#contact', via: 'get'
end
For more info check out the guides for namespacing: http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing

Rails routes helper not updating to new "match"ed route

I have a "list" model and "ListsController" controller for it. By default, the route for lists was /lists/1, /lists/1/edit/, etc. I changed my routes.rb file to make it so the show path was "/:id", the new path was "/new".
Here's my routes file:
ToDo::Application.routes.draw do
root to: 'pages#home'
match '/about', to: 'pages#about'
match '/contact', to: 'pages#contact'
match '/help', to: 'pages#help'
resources :lists
match '/new', to: 'lists#new'
match '/:id', to: 'lists#show'
match '/:id/new', to: 'lists#new_item'
end
I can access a list by doing "localhost:3000/1" perfectly fine. But now I'm trying to use link_to, and when I do "link_to "List", list", it generates a url to the original route, which is "localhost:3000/lists/1".
Does anyone know how to fix this? Is there anything I should be doing better with my routes?
Thanks!
Instead of using match you could simply provide alternative path for resources:
resources :lists, path: ''
You will need to specify as: 'name' option to create a named route for your match rules, and to overwrite the named route provided by resource :lists.
resource :lists
match '/new', to: 'lists#new', as: 'new_list'
match '/:id', to: 'lists#show', as: 'list'

Resources