I have a routes folder
resources :groups
In my GroupsController here are some actions
def new
#group = Group.new
end
def update
end
def show
#groups = Group.find(params[:id])
end
When I run rake routes I see
new_group GET /groups/new(.:format) groups#new
So now in my html page I have
a.btn.btn-primary href="/groups/new"
The funny thing is whenever I click on the link, it tells me
No route matches {:action=>"show", :controller=>"groups"}
I actually do have a route match for the show action. I also checked and do not have any filters that are redirecting me to the show action in my GroupsController. I have no idea why it's redirecting me to show. What's wrong and how do I fix this? I must be missing something obvious.
UPDATE
If I go and remove the show action from the resources method like so
resources :groups, except: [:show]
Then it tells me that it could not find an update action.
SOLVED
I found out in my new.html page there was a call to group_path, when in reality it should groups_path
I found out in my new.html page there was a call to group_path, when in reality it should groups_path.
Related
I'm a new user of rails so it's complicated to understand how the routes.rb works! So I try to modify a route, I got a path that look like this:
user/:id/edit but i want that the id not appear in the path.
I try to use this method :
get '/users/:id/edit', to: 'users#edit', as: 'users/edit'
but it changes nothing. In my routes.rb i got :
resources :users, only: [:create, :new, :show, :edit]
Someone know how to do this? I already take a look at this guide
If you already take a look at guides, do you read about singular resources?
Sometimes, you have a resource that clients always look up without
referencing an ID. For example, you would like /profile to always show
the profile of the currently logged in user. In this case, you can use
a singular resource to map /profile (rather than /profile/:id) to the
show action:
resource :geocoder
creates six different routes in your application, all mapping to the Geocoders controller:
GET /geocoder/new geocoders#new return an HTML form for creating the geocoder
POST /geocoder geocoders#create create the new geocoder
GET /geocoder geocoders#show display the one and only geocoder resource
GET /geocoder/edit geocoders#edit return an HTML form for editing the geocoder
PATCH/PUT /geocoder geocoders#update update the one and only geocoder resource
DELETE /geocoder geocoders#destroy delete the geocoder resource
If you have taken,
resources :users
Now change this route as follows,
get '/users/edit', to: 'users#edit', as: 'users_edit'
Now in your view file where you have edit link, change the link to,
<%= link_to 'Edit', users_edit_path(:id => user.id) %>
Now this links to the edit action of users controller with an id parameter.
Now, in the users controller file,
class UsersController < ApplicationController
def edit
// params[:id] will be the ID that you sent through the view file.
#user = User.find(params[:id])
end
end
Thats it, you are done with your custom route, now the route will be users/edit instead of users/:id/edit
I am trying to set up routes for the "Page" model nested within the "User" model. Only "Pages" needs to be resourcesful. (User has_many pages)
This is the original way I did it:
resources :users, path: '', only: [] do
resources :pages, path: ''
end
The above worked for me just fine. The routes I got were these:
user_pages GET /:user_id(.:format) pages#index
POST /:user_id(.:format) pages#create
new_user_pages GET /:user_id/new(.:format) pages#new
edit_user_pages GET /:user_id/:id/edit(.:format) pages#edit
user_pages GET /:user_id/:id(.:format) pages#show
PUT /:user_id/:id(.:format) pages#update
DELETE /:user_id/:id(.:format) pages#destroy
This made sense for me because /john-doe/page1 would be user_pages_path(#user, #user.pages.first).
However, new_user_pages didn't make sense because a user can only make a page for himself/herself. Therefore, each user should visit /new, not "/:user_id/new". Furthermore, what happens if the user visits another user's ":another_user_id/new" ? (it would make more sense to do new_pages_path and '/new' instead of new_user_pages_path and /:user_id/new).
Another way I tried to do the above routing:
I also realized the above can be accomplished in a shorter way due to the fact that ":users" does not need to be resourceful:
resources :pages, path => :user_id
However, this resulted in paths w/o "user" in them:
pages GET /:user_id(.:format) pages#index
POST /:user_id(.:format) pages#create
new_pages GET /:user_id/new(.:format) pages#new
edit_pages GET /:user_id/:id/edit(.:format) pages#edit
pages GET /:user_id/:id(.:format) pages#show
PUT /:user_id/:id(.:format) pages#update
DELETE /:user_id/:id(.:format) pages#destroy
What is the "rails" way of doing this? Also, should I remove "new" from the resource and define it separately?
Also, does it make sense to use scope or namespace instead?
Thanks,
Nick
Why don't you want your routes to follow the new_user_pages_path format? There might be reasons for doing it the way you want that I'm not aware of, but for me, it's a lot easier when all of my nested resource paths follow the same format.
To answer your question about preventing a user from visiting /:another_user_id/new, you can prevent this by adding a before_filter to make sure that the id getting passed to the new action matches the id of the user that is currently logged in.
This is what I'm using in the app I'm building currently:
things_controller.rb
class VendorsController < ApplicationController
#other filters
before_filter :correct_user
#controller methods
private
def correct_user
if params[:user_id]
#user = User.find(params[:user_id])
unless #user && current_user == #user
redirect_to(root_path)
end
else
redirect_to(root_path)
end
end
end
Of course, you'll need a current_user method for this to work (mine comes from devise).
When I go to /relationships/index it displays the show page even if it is not mentioned in the controller? Then when I try to just go to an index view without a show page created I get the following error: Unknown action: The action 'show' could not be found for relationships controller, even with no mention of it in the controller or a view file for the action.
routes.rb
Mymanual::Application.routes.draw do
resources :validation_rules
resources :validations
resources :product_types
resources :products
resources :connections
resources :relationships
root :to => 'products#index'
end
relationships_controller.rb
class RelationshipsController < ApplicationController
def index
end
def new
#relationship = Relationship.new
end
end
Then just HTML in a index.html.erb, show.html.erb and new.html.erb file.
It's because /relationship path is for relationships#index. If you go to /relationships/index, Rails router assumes you want to go to relationships#show path with params[:id] == 'index'.
Even though you want the index action, you don't enter index in the url. Otherwise, it thinks you're trying to find a Relationship with an id of index.
So just go to /relationships instead.
Go to a console and then run:
rake routes
It will give you all routes your app understand
In some place of this routes you will have something like:
relationships relationships#index /relationships
relationship relationships#show /relationships/:id
The issue that you have is that the app understand /relationships/index as relationships with id=index
The fix? use /relationships url
When I go to my localhost:3000/users page, I get:
Unknown action
The action 'index' could not be found for UsersController.
If you were following Hartl's tutorial,then accessing localhost:3000/users will cause this error. Try localhost:3000/signup instead.
You need not define the default actions (assuming appropriate http method), all you need to do is add the following to your config/routes.rb
resources :users
First you need to make sure that your controller actually has an index action, so
class UsersController < ApplicationController has to include the def index ... end in it.
Also, make sure your routes are set up correctly using
resources :users
and check it by typing
rake routes
in the terminal to check that the routes are right.
You might also want to check that the root is set up correctly in the config/routes.rb file
if you got the same problem with me (I cant access the localhost:3000/users but I can access my localhost:3000/signup), it might be works for u.
First, in your users_controller.rb (Controller for Users) , add
def index
end
Then , make a file "index/html/erb" in your app/views/users/index.html.erb
and put this code
<% controller.redirect_to "/signup" %>
You might have to rerun your server, and it works on my problem.
Remember, if you've included
get 'signup' => 'users#new
resources :users
…in your routes.rb file, then you need to use localhost:3000/signup instead. I believe if you removed get 'signup' => 'users#new and left only resources :users then using localhost:3000/users would take you to the new user signup form.
Remove the debugger line. Also, make sure you have exit the rails console.
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
debugger
end
def new
end
end
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