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
Related
I have many controllers which has an action download_excel. Action generates xls file defined using axlsx gem.
Problem is many controllers have same action. Is there anyway to write a single line route in routes.rb file?
I tried.
match ':controller(/:download_excel)', :via => [:get]
and
resource "#{:controller}" do
get download_excel, on: :collection
end
and
[:countries, :pricetypes].each do |file|
resources "#{file}" do
collection do
get "#{file}"+'/excel' => "#{file}"+'#excel'
end
end
end
etc. Nothing worked.
How can I write dynamic routes. Want to DRY code in routes as much as possible.
Try This
match ':controller(/:action(/:id))', :via => [:get, :post]
I use it as a catch all route, but if you want to your app to be restfull you should use the resources routes
So I have just created my rails 4.1.2 project with a controller, login_controller.rb and view login.html.erb. I have edited my routes.rb and removed the already put in route by rails after creating a controller and added another default match route which is :controller(/:action(/:id))', :via => :get
When I run my server using rails s and open localhost:3000/login it gives me this error:
The action 'index' could not be found for LoginController
I do not know why is it looking for an action named 'index'. If I am right then the default action taken by rails without actually specifying one is 'index' so I tried to change my URL and requested this:
localhost:3000/login/login
Which gave me this error:
No route matches [GET] "/login/login"
How can I fix this issue? Thanks.
Here's what my rake routes outputs:
Prefix Verb URI Pattern Controller#Action
GET /:controller(/:action:(/:id))(.:format) :controller#:action
Say you have a model User and controller UsersController. In your routes.rb file, you list resources and routes to match based on controller actions. By default, that resource includes :index, :show, :new, :edit, :create, :update, :destroy. You can specify which you want (or not) by doing:
# config/routes.rb
# blacklisting - these are not in your controller
resource :users, exclude: [:show, :destroy], via: [:get, :post]
# whitelisting - these are in your controller
resource :users, only: [:index], via: [:get, :post]
To my understanding, the filename of your view (unless rendered or an asset) corresponds to the controller action. Is the view for your login page named index.html.(erb|haml)?If so, you should define the index even as simply as def index; end. However, I suggest you include something that redirects the user to home or the login page, depending whether they are already logged in.
From there, the real magic happens in your controller as you define a method login. Here, check the incoming parameters and log the user in if correct. Think of this similar to an #update action.
Similar to how you define which actions to include in the routes, you can make your own custom ones. Do note: the order of routes matter. I am not 100% on that concept myself, but this is what I would suggest in your case:
#config/routes.rb
resource :login, only: [:index], via: [:get, :post]
match '/login/login' => 'login#login', via: [:get, :post]
You can also use match to link /login/index to the #login method. The view would be called index still. And just because there is a route for it, you do not need a view for the login action -- it simply parses the parameters, while the index would show error messages.
Add an index action on your LoginController
def index
end
This will give you the desired result. localhost:3000/login/login. Rember to restart server at the end.
app/controller/login_contrtoller.rb
class LoginController < ApplicationController
def login
end
end
routes
get 'login/login'
/app/views/login/login.html.erb
<h1>Login#login</h1>
<p>Find me in app/views/login/login.html.erb</p>
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.
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.
Feel like I'm doing this right, but apparently not.
I have a restful resource, Posts, with index, show, new, update, edit, etc actions in the controller. In routes, I have
resources :posts
I wanted to make the index action occur at the URL '/archive' instead of '/posts'
So I added this line in the routes.rb file, after the resources one:
match '/archive', to: "posts#index"
But when I click on a link to posts_path, it still goes to /post (though if I type in /archive as a url, it works -- not ideal, though). Confused. Could this have to do with my having installed friendly_id?
resources :posts, except: [:index]
get 'archive' => 'posts#index', as: :posts
You need to use something like match '/archive', :to => 'posts#index', :as => 'archived'. Then you will have a new route to the tune of archived_posts_path. The method posts_path does not dynamically changed based on custom matchers. You can always run rake routes to see a list of routes for your site.