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>
Related
I'm getting this error :
"The action 'create' could not be found for ObjectController"
I know it should be obvious but I'm missing something, that's my controller :
class ObjectController < ApplicationController
def index
end
def create
end
end
And that is my routes :
Rails.application.routes.draw do
get 'object/index'
get 'object/create'
match ':controller(/:action(/:id))', :via => :get
resources :objets
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
root 'object#index'
You probably want to scrap those routes and try something simpler like
resources :objects, only: [:get, :create, :show]
Then use
$ rake routes
To make sure your routes are as the should be. You will want a POST route to /objects to create a new object etc..
Ok that one was dumb, actually I had two directories and I wasn't modifying the right one, sorry about that...
Your routes could be greatly improved:
#config/routes.rb
Rails.application.routes.draw do
root 'objects#index'
resources :objects
--
Next, the "standard" way to achieve what you're looking for is to use the new action; IE not the "create" action. If you wanted to use the create path name (instead of new), you'll be able to define it in the path_names argument:
#config/routes
resources :objects, path_names: { new: "create", create: "create" } #-> url.com/objects/create
To understand why you should be using new instead of create, you should look up resourceful routing, and how it pertains to object orientated programming.
Finally, your controller should be named in the plural:
#app/controllers/objects_controller.rb
class ObjectsController < ApplicationController
...
end
Whilst you can call it whatever you like, Rails defaults to plural controller names, singular model names.
In Rails 4 I'm trying to make a custom root for a particular action in the users controller, so i want my restful resources for users still like they are, but change only the url for the create action and make it to be for example /account/register. I'm trying do this as the follow but it seem not work :
resources :users, except: [:create] # first i eliminate creation of create root
resources :users, path: "account/register", as: :users, only: [:create] # then i just try to make a custom route for only create action
i want still using users_path and not change any of my routing helper in the view, please any idea ?
Try:
match '/account/register' => 'user#create', via: :post
How about:
post "/account/register" => "users#create", as: :users
This will create a route where /account/register points to UsersController#create. This can be referenced with users_path.
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
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.
I have a controller SubscriptionsController with only actions new and create. How would I redirect to new if say someone tries to visit GET /subscriptions which would normally trigger the index action?
config/routes.rb
resource :subscriptions, :only => [:new, :create]
Using rails3 you can do it from a route, something like:
match "/subscriptions", :to => redirect("/subscriptions/new")
Edit:
From the comments it was made clear you want to capture more than that, using a wild card you can make it more generic. You may need to combine this form with the previous to deal with the non-slash form (or try the below form without a slash, I havent tried that). Also make sure to put these "catch all" routes below your other ones since routes are matched from top to bottom.
match "/subscriptions/*other", :to => redirect("/subscriptions/new")