I've got Rails routing problem. I would like to use singular resource with user controller but it doesn't work as I expected. Here is the fragment of my routes.rb file:
scope :module => "frontend" do
root :to => "home#index"
resource :user, :controller => "user"
get "/sign_up" => "user#new"
get "/sign_in" => "user#sign_in"
get "/sign_out" => "user#sign_out"
post "/authenticate" => "user#authenticate"
resources :articles
resources :article_categories
end
I thought it will work when I'll use for example "/user" or "/user/new" URL but it didn't. I get a routing error:
No route matches {:controller=>"frontend/user"}
The 'rake routes' command output is:
user POST /user(.:format) frontend/user#create
new_user GET /user/new(.:format) frontend/user#new
edit_user GET /user/edit(.:format) frontend/user#edit
GET /user(.:format) frontend/user#show
PUT /user(.:format) frontend/user#update
DELETE /user(.:format) frontend/user#destroy
sign_up GET /sign_up(.:format) frontend/user#new
sign_in GET /sign_in(.:format) frontend/user#sign_in
sign_out GET /sign_out(.:format) frontend/user#sign_out
authenticate POST /authenticate(.:format) frontend/user#authenticate
What is interesting, when I add route for index action in user controller, like this:
scope :module => "frontend" do
root :to => "home#index"
resource :user, :controller => "user"
get "/user" => "user#index"
get "/sign_up" => "user#new"
get "/sign_in" => "user#sign_in"
get "/sign_out" => "user#sign_out"
post "/authenticate" => "user#authenticate"
resources :articles
resources :article_categories
end
...it works!
But index action is not defined in user controller!
'rake routes' command returns double line for GET /user
GET /user(.:format) frontend/user#show
GET /user(.:format) frontend/user#index
so I suppose that's not the solution. Other actions assigned to '/users' URL don't work.
Is it necessary to define the route for the index action like
get "/controller_name" => "controller_name#index"
What am I doing wrong?
Defining a singular resource in your routes will not generate a route to an index action by design. The singular resource implies you're always going to lookup this resource without specifying an ID and consequently a get to index for a singular resource just doesn't make logical sense. So, a GET to your url "/user" will route to a show action for that singular resource and not an index.
EDIT: Since your issue isn't obvious, I'd simplify your routes until you can at least hit the controller you'd expect and then build from there.
config/routes.rb
scope :module=>"frontend" do
resource :user
end
#ensure you don't have any other user routes listed before this that would match "/user".
app/controllers/frontend/users_controller.rb
module Frontend
class UsersController < ApplicationController
def show
raise "in frontend/show"
end
end
end
Thanks a lot for help! I found the bug.
The routing error was caused by the following line of the layout html file
<%= auto_discovery_link_tag(:rss, {:action => "index"}, {:title => "RSS"}) %>
I was looking for errors in the erb view files but I forgot about the layout.
I must remember to check the entire view layer in such situations.
Related
I have custom CRUD routes for example - for profiles
get '/profiles', to: 'profiles#index'
get '/profiles/new', to: 'profiles#new', :as => 'new_profile'
post '/profiles', to: 'profiles#create'
get '/profiles/edit/:id', to: 'profiles#edit', :as => 'profile'
patch '/profiles/edit/:id', to: 'profiles#update'
get '/profiles/get_profiles', to: 'profiles#get_profiles'
It works okay. But I do the same routing for profile skills, wich is under relation of profile. Routes of ProfileSkills looks like this
get '/profiles/:profile_id/profile_skills', to: 'profile_skills#index'
get '/profiles/:profile_id/profile_skills/new', to: 'profile_skills#new', :as => 'new_profile_skill'
post '/profiles/:profile_id/profile_skills', to: 'profile_skills#create'
get '/profiles/:profile_id/profile_skills//edit/:id', to: 'profile_skills#edit', :as => 'profile_skills'
patch '/profiles/:profile_id/profile_skills/edit/:id', to: 'profiles#update'
When I under the route for creating the new item
http://localhost:3000/profiles/1/profile_skills/new
It throw an exception
No route matches {:action=>"edit", :controller=>"profile_skills", :profile_id=>"1"}, missing required keys: [:id]
On form for line
<%= form_for #profile_skill do |form| %>
Why he don't understand that I'm under the 'new' route and it looking for 'edit', when i'm under the 'new'?
This problem is only when i'm on sub-routes. In 'Porfile' routes for example, if works fine.
In your routes use this
resources :profiles do
resources :profile_skills
end
this will provide you the routes like this
profiles/:profile_id/profile_skill points to index action of profile_skill
profiles/:profile_id/profile_skill/new points to new action of profile_skill
profiles/:profile_id/profile_skill/:profile_skill_id points to show action of profile_skill
profiles/:profile_id/profile_skill/:profile_skill_id/edit points to edit action of profile_skill
and so on.
for more help visit Rails Routing
How can I also show a blog post without /posts/ in the URL?
http://www.anthonygalli.com/posts/i-walk-the-line
http://www.anthonygalli.com/posts/50-shades-of-galli
http://www.anthonygalli.com/posts/tips-for-regaining-momentum
Shortened Version (Goal of Question):
http://www.anthonygalli.com/i-walk-the-line
http://www.anthonygalli.com/50-shades-of-galli
http://www.anthonygalli.com/tips-for-regaining-momentum
I have post as a MVC.
routes.rb
resources :posts
get 'about' => 'posts#about'
get 'feed' => 'posts#feed'
get 'subscribe' => 'posts#subscribe'
Change your routes.rb to:
resources :posts, path: '/' do
collection do
get 'about'
get 'feed'
get 'subscribe'
end
end
For documentation on Rails routing check: http://guides.rubyonrails.org/routing.html
Your routes should be updated to look something like this:
resources :posts
get 'about' => 'posts#about'
get 'feed' => 'posts#feed'
get 'subscribe' => 'posts#subscribe'
get ':id' => 'posts#show', :as => :post_by_slug
That as option will be important for linking to your new route if you want to link to the /post/-less paths:
<%= link_to post.title, post_by_slug_path(post) %>
P. S. I believe that the new route will need to be listed last in your routes so that the routes before it can have precedence. (Otherwise, trying to visit /about would try to load a post with a slug named about instead of the posts#about action. You should try this and see if that's true.)
Resource generates the standard CRUD urls, so you have to specify the posts route specifically. Something like this
get '/desired-url' => 'posts#index'
I'm taking an MOOC and the goal of this exercise is to add a new functionality to typo, where i can merge two articles together.
When I add the route to my new function merge to the routes.rb I'm losing the functionality to delete articles. I think something clashes here, but I have no idea what.
The original routes.rb:
%w{advanced cache categories comments content profiles feedback general pages
resources sidebar textfilters themes trackbacks users settings tags redirects seo post_types }.each do |i|
match "/admin/#{i}", :to => "admin/#{i}#index", :format => false
match "/admin/#{i}(/:action(/:id))", :to => "admin/#{i}", :action => nil, :id => nil, :format => false
end
This method in articles.rb creates the correct url for deleting
def delete_url
blog.url_for(:controller => "/admin/content", :action =>"destroy",:id => id)
end
correct url:
http://example.com/admin/content/destroy/7
If i follow this link i can successfully delete an article.
However, if I add the following before that to my routes.rb:
namespace "admin" do
resources :content do
post :merge, on: :member, as: :merge
end
end
The new merging functionality and forms are working fine, but the method delete_url now produces something like this:
http://example.com/admin/content/7
and if I follow a link created by this method i get:
Unknown action
The action 'show' could not be found for Admin::ContentController
Maybe I'm overwriting something? I can't figure out what's happening here and why this affects the delete action / route.
Thanks in advance!
EDIT: rake routes | grep content:
with the original routes.rb gives me:
admin_content /admin/content {:controller=>"admin/content", :action=>"index"}
/admin/content(/:action(/:id)) {:action=>nil, :id=>nil, :controller=>"admin/content"}
whereas my modified routes.rb produces
merge_admin_content POST /admin/content/:id/merge(.:format) {:action=>"merge", :controller=>"admin/content"}
admin_content_index GET /admin/content(.:format) {:action=>"index", :controller=>"admin/content"}
POST /admin/content(.:format) {:action=>"create", :controller=>"admin/content"}
new_admin_content GET /admin/content/new(.:format) {:action=>"new", :controller=>"admin/content"}
edit_admin_content GET /admin/content/:id/edit(.:format) {:action=>"edit", :controller=>"admin/content"}
admin_content GET /admin/content/:id(.:format) {:action=>"show", :controller=>"admin/content"}
PUT /admin/content/:id(.:format) {:action=>"update", :controller=>"admin/content"}
DELETE /admin/content/:id(.:format) {:action=>"destroy", :controller=>"admin/content"}
/admin/content {:controller=>"admin/content", :action=>"index"}
/admin/content(/:action(/:id)) {:action=>nil, :id=>nil, :controller=>"admin/content"}
Okay, thanks to #guitarman i worked through my routes code and found out I can add the following except:
namespace "admin" do
resources :content, except: [:index, :show, :update, :destroy, :edit, :new, :create] do
post :merge, on: :member, as: :merge
end
end
after that, the rake routes just shows the additional merge route I wanted and my destroy action works fine again.
Check rake routes command. I think there is a route /admin/content/:id which will be created by resources :content in the namespace "admin".
Your request to http://example.com/admin/content/7 will be catched be the defined route but I gess you have no show action in the controller.
Better:
namespace "admin" do
post "/content/:id/merge", to: "admin/content#merge", as: :merge
end
For more information about recources and the CRUD operations please see the rails routing guide.
I've been having trouble with named routes in rails 4 (Named route for non resource nesting).
I've moved onto something else, but still struggling with the same problem of named routes for non resource urls.
This is my route from rake routes:
GET /messages/:id/report/:reply_token(.:format) messages#report
messages POST /messages(.:format) messages#create
and my routes.rb
resources :messages, only: [:create] do
member do
get 'report/:reply_token', :action => 'report'#, :as => :message
end
end
Because of the problem I had in my post linked at the top, I'm trying to get a url to the /messages/:id/report/:reply_token route by doing the following:
"#{messages_url(#message, :host => "localhost:3000")}/report/#{#message.reply_token}"
But it's giving me this:
http://localhost:3000/messages.110/report/6bBw22TdaRYcQ3iVzW1ZwA
Why is there a . between the 'messages' and the '110' (message_id)?
Instead of #message, I've also tried #message.id in the messages_url(). I've also tried this: report_message_path(message_id: #message.id, reply_token: #message.reply_token) but got the same error as in my question linked above. I've also tried message_url() instead but it gives undefined method 'message_url'.
You are mixing up routes. messages_url is to generate a URL for create action which does not have ID in its route. Rails assumes 110 is the format and uses the second route (which is named as messages)
messages POST /messages(.:format)
As a solution, name your route like this and also add show action
resources :messages, only: [:create,:show] do
member do
get 'report/:reply_token', :action => 'report' , :as => :custom_message
end
end
And,
custom_message_url(#message, :host => "localhost:3000")
More about naming routes here.
Answerd here already - Rails _path helper generating path with format not id
I got a User model and a About model. The about model is a page where users have more info about them that due its nature is more appropriate to have it on a separate model rather than in the user model.
I want to be able to route it to something like /:username/about and get all the verbs working on that path (GET POST, PUT, DELETE).
/:username/about
/:username/about/edit
/:username/about
This is what I already have
# routes.rb
resources :users do
resources :abouts
end
match ':username/about' => 'abouts#show', :as => :user_about
match ':username/about/add' => 'abouts#new', :as => :user_new_about
match ':username/about/edit' => 'abouts#edit', :as => :user_edit_about
And in the models I have
# about.rb
belongs_to :user
# user.rb
has_one :about
When I'm doing a post or put to /roses/about It's interpreting It as a show
Started POST "/roses/about" for 127.0.0.1 at Sun Feb 27 16:24:18 -0200 2011
Processing by AboutsController#show as HTML
I'm probably missing the declaration in the routes, but doesn't it get messy declaring each verb for a resource when it's different from the default?
What's the simplest and cleaner way to archive this?
When using a has_one, it might make sense to declare it as a singular resource in your routes. Meaning
resources :users do
resource :about # notice "resource" and not "resources"
end
And if you want to override the paths for new/edit, add a :path_names option to the resource/resources-call:
resources :about, :path_names => { :new => 'add', :edit => 'edit' }
The official documentation has lots of other tips and tricks for routing as well.
You can use scope and controller blocks to cut down on the verbiage:
scope "/:username" do
controller :abouts do
get 'about' => :show
post 'about' => :create
get 'about/add' => :new
get 'about/edit' => :edit
end
end
which produces:
about GET /:username/about(.:format) {:action=>"show", :controller=>"abouts"}
POST /:username/about(.:format) {:action=>"create", :controller=>"abouts"}
about_add GET /:username/about/add(.:format) {:controller=>"abouts", :action=>"new"}
about_edit GET /:username/about/edit(.:format) {:controller=>"abouts", :action=>"edit"}