Rails: Sub-routing. No route matches - ruby-on-rails

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

Related

How to remove /posts/ from URL?

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'

Routes on Rails application are failing

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.

Rails routes for get request with query params

I need a route to accept a request reports#show with an attached :query parameter and I can't figure out how to write it. It needs to respond to this link in my view:
= link_to report_path(query: params[:query]) do
config/routes.rb
resources :reports do
resources :chapters
resources :pages
end
Tried variations of: get '/reports/:id/:query', :as => 'reports_query' but I keep getting:
Routing Error
No route matches {:action=>"show", :controller=>"reports", :query=>"europe"}
Project is mostly RESTful but I'll take anything that works at this point. Thanks for any help.
You should define your route to query with code like this
# routes.rb
resources :reports do
get ':query', to: 'reports#show', on: :member, as: :query
end
It will generate path helper you can use that way
= link_to 'Query Report', query_report_path(#report, query)
I went through the same problem here, and I solved it using the default param while defining my routes.
get :twitter_form, defaults: { form: "twitter" }, as: :twitter_form, to: "campaigns#show"

Rails routing. Singular resource

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.

using form_for with a singular model

I have a Wizard model that the client references w/o an ID (it's saved in the session), so I've created a singular resource for :show and :update. I want the admin to have access to all instances of that model via index so admin can delete strays, so I've added a plural resources for :index and :destroy. The index and destroy works, but I can't figure out the right arguments to pass to form_for in the update view.
The setup
# config/routes.rb
WTest::Application.routes.draw.do
resource :wizard, :only => [:show, :update]
resources :wizards, :only => [:index, :destroy]
...
end
resulting in
$ rake routes
wizards GET /wizards(.:format) {:action=>"index", :controller=>"wizards"}
wizard DELETE /wizards/:id(.:format) {:action=>"destroy", :controller=>"wizards"}
GET /wizard(.:format) {:action=>"show", :controller=>"wizards"}
PUT /wizard(.:format) {:action=>"update", :controller=>"wizards"}
This sets up routes the way I'd expect.
The question (revised since original post)
In the console:
>> app.wizard_path
raises the error ActionController::RoutingError: No route matches {:action=>"destroy", :controller=>"wizards"}
Why is this? Have I set up my routes incorrectly? I need to specify :url => wizard_path for form_for() in the wizards's update view.
The details
If I specify an explicit path in my call to form_for:
# app/view/wizards/update.html.erb
<%= form_for #wizard, :url => wizard_path do |f| %>
<%= f.submit %>
<% end %>
... then attempting to render this for gets an error on the form_for line:
No route matches {:action=>"destroy", :controller=>"wizards"}
I have no idea why it's trying to match the destroy action. How do I get the form to submit to the {action=>"update", :controller=>"wizards"} route?
(By the way, I looked at bug 267, and I don't think it is the same as what I'm observing. But if it is this bug, is there a workaround?)
Carrying on the long tradition of answering my own questions (meh!), I think I figured it out. If my analysis is wrong, I'd be happy to give someone else the checkmark...
The cause of the problem
Look at the output of rake routes
$ rake routes
wizards GET /wizards(.:format) {:action=>"index", :controller=>"wizards"}
wizard DELETE /wizards/:id(.:format) {:action=>"destroy", :controller=>"wizards"}
GET /wizard(.:format) {:action=>"show", :controller=>"wizards"}
PUT /wizard(.:format) {:action=>"update", :controller=>"wizards"}
The path method 'wizard_path' is ambiguous: it can either refer to the DELETE clause, in which case it needs an :id argument (wizard_path(22)), or it can refer to the GET and PUT clauses, in which case it doesn't take an ID argument.
The solution
So my solution was to create a route specifically for deletion. My revised routes.rb file now reads:
resources :wizards, :only => [:index]
resource :wizard, :only => [:show, :update]
match 'wizard/:id' => 'wizards#destroy', :via => :delete, :as => :delete_wizard
and rake routes now produces:
$ rake routes
wizards GET /wizards(.:format) {:action=>"index", :controller=>"wizards"}
wizard GET /wizard(.:format) {:action=>"show", :controller=>"wizards"}
PUT /wizard(.:format) {:action=>"update", :controller=>"wizards"}
delete_wizard DELETE /wizard/:id(.:format) {:controller=>"wizards", :action=>"destroy"}
I needed to make a one-line change to the delete link in wizards/index.html.erb to use the new delete_wizard_path, but everything works now.

Resources