The action 'index' could not be found for Controller - ruby-on-rails

I am trying to make a controller with one action and when i try and go to the localhost:3000/controllername/action i get this error:
The action 'show' could not be found for LearnController
Here is my controller:
class LearnController < ApplicationController
def more
end
end
and in routes i do this:
resources :learn
I know that resources creates all the show, edit, index and all that but how do I make it so only the actions i create are created in the routes?

As you mention, resources :learn will create a bunch of routes according to the resourceful convention.
If you don't want those, don't use resources in your config/routes.rb file. Instead, use get, match, and friends to define your routes manually. E.g.
get 'learn/more'

Related

Getting 'Unknown action in controller'

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.

Referring to a nested resourse

I have a nested resource:
resources :res1 do
resources :res2
end
And I have a custom action in res2:
def my_action
end
which doesn't appear in the list of the pre-generated paths (there is no res1_res2_my_action_url url). I want to refer to my_action using controller and action notation but the following doesn't work:
url_for(controller: [:res1, :res2], action: :my_action)
Why is that?
The resources directive in your routes file will only create default routes for your controller.
#index
#new
#create
#show
#edit
#update
#destroy
If you want to add custom routes, you'll have to declare them like so:
resources :res1 do
resources :res2 do
get :my_action
end
end
you can hard code a specific route that points to action and controller:
get '/pathname', to: 'controller_name#my_action'
Try running rake routes and see what o/p you get,a try to apply in your view
get 'my_action' => "res2#my_action"
and then write
:url => my_action_path

Trying to create a method in rails controller

I'm still trying to get the hang of rails and i'm trying to create a simple app with a form where i can enter the data and then submit it and it will be stored in the db. I got this very simple by starting a new project and then running:
$ rails generate scaffold RSVP firstName:string lastName:string
Now i want to redirect to a thank you page after adding a new record via the form.
I've manually added the method below to my rsvps_controller.rb file:
# GET /rsvps/thank_you
def thank_you
respond_to do |format|
format.html # thank_you.html.erb
format.json { render json: #rsvps }
end
end
This line is in my routes file:
resources :rsvps
My question is, when i run rake routes, i don't see a route for my thank_you method. Shouldn't my :rsvps resource pick up my thank_you route and how does the routes know which controller method are which http calls(get, post, put, etc)?
In order to get a route that will hit that action in your controller you should have in your routes.rb file something like:
resources :rsvps do
member { get :thank_you }
end
or
resources :rsvps do
collection { get :thank_you }
end
it depends for if you want to access the resource you've just created or not.
You can take a look # http://guides.rubyonrails.org/routing.html it should help you understating the routing mechanism better.
Adding on to what wlad said, the resources :rsvps things in your routes.rb file creates a set of default routes that are going to be needed by most models. Things like index, new, create, or show. The reason your thank_you action isn't showing up in rake routes is because thank_you isn't one of the actions that were so common that they needed to be included out of the box without extra code.
If you are going to need to load a rsvp model on the thank you page to display any data in that model then you will need to use a member route. The :id in the route will be there because this is a resources member route and has to be associated with a particular resource. There has to be something in the url to know what to load.
resources :rsvps do
member { get :thank_you } #GET /rsvps/:id/thank_you(.:format)
end
If you just want a generic route that points to that controller action then you can use something like this:
match "/rsvps/thank_you" => "rsvps#thank_you", as: "rsvp_thank_you"
You can add more actions to any controller but rails will not treat this functions as actions unless you specify them in routes file. It will be treated as just another function in controller class created by user.
so if you want to add the thank_you function as action you need to add this to routes file.
There are multiple ways of doing so as others have explained in their answers.
adding-more-restful-actions
Using member and collection inside resources.
Use member when you want the function to be used only with the some model object.
eg: preview for photo id 1
GET /photos/:id/preview
In our example you member if you want such route and functionality.
GET /rsvps/:id/thank_you
Note :id in params is needed when you specify it as a member action.
resources :rsvps do
member do
get :thank_you #GET /rsvps/:id/thank_you(.:format)
end
end
Use collection if you want to call the action directly like
GET /rsvps/thank_you(.:format)
in resources
resources :rsvps do
collection do
get :thank_you #GET /rsvps/thank_you(.:format)
end
end
You need to specify the type of action (GET|POST) while adding it to routes.
In our example thank_you has been specified as a GET action. You can choose either.
You can create you own preety_urls or non restful routes using match.
(This will also require to have the action defined in resources block).
check out more on match here http://guides.rubyonrails.org/routing.html#non-resourceful-routes
I suggest you to go through this awesome documentation created by the rails team.(once more ;) ) http://guides.rubyonrails.org/routing.html
Cheers.
As you have said you just want to show a thank you page for each rsvp so a member route should be used. like this
resources :rsvps do
member get :thank_you
end
You should use collection of thank_you when you want to show all or some specific collection of thank_you.
when you include this and run rake routes again you will see the new http action there.

Nested singular resource, not showing up in rake routes

I created a search and replace controller, with just an index action. Since it's meant to go under one of my restful controllers created by a scaffold, i setup the following in the routes file:
resources :sites do
resource :search_and_replace, only: [:index]
end
However, it does not appear when I run rake routes. If I switch to resources, it does. But the method name is site_search_and_replace_index. The pluralization of resource doesn't feel right either, since this is not around multiple records in a table.
The index action doesn't exist in a singular resource. This makes sense if you think of the meaning of the action: index of what, there's only one resource? Use show instead:
resources :sites do
resource :search_and_replace, only: [:show]
end
Are you sure you want to have search and replace as a resource? There might be other options that are more useful: Adding more restful actions

Why isn't my 'join' action working, it says the action 'show' can't be found

In my UserController I have:
def join
end
I have a join.html.erb in my /views/user/ folder.
My routes has a :
resources :user
When I go to:
http://localhost:3000/user/join
I get:
The action 'show' could not be found for UserController
Re: why isn't the join action found?
To answer your specific question, what's happening is that you want to have an action "join" for your User model.
Your problem is that you haven't defined a route matching the url http://localhost:3000/user/join
The line resources :user in your routes file only defines routes for the seven standard rest verbs/actions:
index, new, create, show, edit, update, destroy
See: http://apidock.com/rails/ActionController/Resources/resources
Added: to fix, you'll need to add an explicit or generic route. Routing docs
Added: Re: why am I seeing the error message re show? To be ultra-precise, the route selector "GET /usr/:id" (created by your resource call) is being used to select the SHOW action for the User resource. The :id value is being set to "join". Since you don't have a Show method defined in your controller, that's the error that you're seeing.
You're using resources, but have a non-REST action, so you need to add the join action to the route with the appropriate HTTP verb:
map.resources :users, :member => { :join => :get }
Place:
def show
end
in your UserController.
To be certain:
app/controllers/users_controller.rb
def join
end
app/views/users/join.html.erb
config/routes.rb
resources :users

Resources