Ruby on Rails Routing for Wildcard URL - ruby-on-rails

I was trying to pull a segment from the URL and since I'm a rookie, kind of confused by the routing.
My code to get the last segment works fine, it's my routing that is messed up.
Ideally the URL would like this:
http://localhost.com/track/item/1234
I'm using Rails v4.0.8 & Ruby v2.0.0p451
The error is No route matches [GET] "/track/item/1234"
Here's the whole routes.rb file:
SepContact::Application.routes.draw do
get "track/item"
get "track/item/:id"
get "contacts/contact"
resources "contacts", only: [:new, :create]
end

I think CWitty's should work as well but here is a more explicit format.
match "track/items", to: 'controller#index', via: :get, as: "items"
match "track/items/:id", to: 'controller#show', via: :get, as: "item"
Note I updated your url to be more rails like items rather than item
I think most of your problem is with the track segment of the url.
I don't see how get 'track/items' would map the the items#index controller / method
I think the match method would be needed here to explicitly map the url to the correct controller and method.
Is there a good reason you are naming you url like that?
You can read all about routing here:
http://guides.rubyonrails.org/routing.html
Here is the section of the above document that discusses using the match method:
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
Routing both GET and POST requests to a single action has security implications. In general, you should avoid routing all verbs to an action unless you have a good reason to.

Your routes should be like:
SepContact::Application.routes.draw do
get "track/item/:id", to: 'controller#action'
get "track/item", to: 'controller#action'
get "contacts/contact" to: 'controller#action'
resources :contacts, only: [:new, :create]
end
You need to specify a to: pointing to a controller and action unless you use the resource or resources helper.

Related

Understanding rails routing that include (=>) and (:as)

While reading about rails routing I found routing that include =>. But I don't understnad what it means. Also I found some routing example with :as. It would be nice if someone explained a little bit about it. I have read rails guide but still I am not quite clear about them.
Please explain what this means
get 'customer_details' => "customers#details"
and
get 'customer_details' => "customers#details", :as => :customerdetails
Each time you define a route, you have to define a controller#action for that route:
#config/routes.rb
get :customer_details => "customers#details"
get :customer_details, to: "customers#details"
get :customer_details, controller: :customers, action: :details
The routing module provides URL rewriting in native Ruby. It's a way to redirect incoming requests to controllers and actions.
The following symbols are special:
:controller maps to your controller name
:action maps to an action with your controllers
Other names simply map to a parameter as in the case of :id.
Using => is simply a shortcut for the to: option...
When a pattern points to an internal route, the route's :action and :controller should be set in options or hash shorthand. Examples:
match 'photos/:id' => 'photos#show', via: :get
match 'photos/:id', to: 'photos#show', via: :get
match 'photos/:id', controller: 'photos', action: 'show', via: :get
In short, it's another way to pass the required "controller#action" arguments to the Rails router.
--
Of course, this is negated by using the resources directive, which sets the controller & actions implicitly:
#config/routes.rb
resources :customers, only: [], path: "" do
get :customer_details, on: :collection #-> url.com/customer_details
end
The routing middleware (ActionDispatch::Routing) takes inbound URL paths, and matches them against your defined routes -- sending the user to the appropriate controller / action.
The entire routing structure (even when you use link_to) depends on having the controller & action set for a route; especially true with a path helper.
Setting as: gives you the ability to explicitly define the name of the path, for example:
#config/routes.rb
get "search/:query", to: "application#search", as: :app_search
... the above will create the helper <%= app_search %>
Update
In response to your comment, you'll want to use either of the following:
#config/routes.rb
get "customers/details", to: "customers#details" #-> url.com/customers/details
- or -
resources :customers do
get :details, on: :collection #-> url.com/customers/details
end
If you're defining a single route, only use symbols if Ruby can interpret that data without any interpolation. For example get :details can be treated as get "details", however get "customers/details" cannot be treated as a symbol.

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

No route matches [GET] "/api/v1/users"

I am getting this error and can not figure out why. All my other routes work in local and remote when I open in browser but users. I am totally new to ruby and Xcode
thanks for any help
Looks to me like you need to also specify the :index action when defining the users routes:
ParkApp::Application.routes.draw do
namespace :api do
namespace :v1 do
resources :users, only: [:index, :create, :update] do
collection do
match '/me', to: 'users#show', via: :get
end
end
## Needed to allow cross origin request from webapp
match '/users/:id', to: 'users#update', via: :post
resources :sweetches, only: [:create, :update, :index]
match '/sweetches/:id', to: 'sweetches#update', via: :post
# Get the messages to display on the views
match '/message_views', to: 'message_views#index', as: :message_views, via: :get
resources :posts
end
end
match '/admin', to: 'admin#index', via: :get
match '/admin', to: 'admin#create', via: :post
match '/admin/:id', to: 'admin#destroy', as: :delete_fake, via: :delete
end
This should make the route you are trying to follow valid. If you take a look at the last snippet in your question you will see that the api/v1/users GET route isn't defined, my change to your routes will fix that.
You are getting the error because, as the error says, your application does not have a route that matches "/users".
See api_v1_users_path POST /api/v1/users(.:format) api/v1/users#create in your post. This means that the POST request to path /api/v1/users invokes the create method of your API::V1::UsersController. So send request to /api/v1/users, but not to '/users`.
I've never used Objective-C, but I guess you need to replace NSString stringWithFormat:#"/users" with NSString stringWithFormat:#"/api/v1/users".
Note that you need to send a POST request. Opening the above path in browser sends a GET request to your application, resulting in 404 not found error.

Matching and Routes in 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.

Rails API Routing Issue

I have the following specified in my Rails Routes. I want to allow both GET and POST on this route, but whatever I try, it only allows the #index action, and doesn't access the #create action when a POST is requested.
match ':user_id/special_deals', to: 'special_deals#index'
I've tried this too:
match ':user_id/special_deals', to: 'special_deals#index', :via => [:get, :post]
I need the User ID to be specified first since people with access to the API can access multiple User's info.
It is working exactly as you asked it to do. If you want POST to routed to create action here are your route configs:
match ':user_id/special_deals', to: 'special_deals#index', :via => [:get]
match ':user_id/special_deals', to: 'special_deals#create', :via => [:post]
There are simpler ways of writing these but I just wanted to use the same format you wrote it. Please check this guide to know about them.
If you already have a User controller, you can write more structured routes like:
resources :users do
resources :special_deals, :only => [:index, :create]
end
This will make routes for special_deals like (#shows where it will be routed to):
GET /users/:user_id/special_deals #special_deals#index
POST /users/:user_id/special_deals #special_deals#create

Resources