Rails - Routes for Nested Resources - ruby-on-rails

I have a conversations controller and a comments controller.
What I would like to do is have the following (from the logs):
Started POST "/conversations/217/comment_beta" for 127.0.0.1
Post the Comments Controller not the Conversations Controller which is what Rails is trying to do now:
AbstractController::ActionNotFound (The action 'comment_beta' could not be found for ConversationsController):
Here is my routes file:
resources :conversations do
resources :comments, :only => [:create, :update,:destroy, :comment_beta], :constraint => {:context_type => "conversations"} do
collection do
post 'comment_beta'
end
end
collection do
get 'read_updater'
end
end
Suggestions? Thanks

your rails routes is actually doing what it is supposed to do. if you conversations/:id/comment_beta to go to your comments controller, either you should change your routes via match or go to the correct url which is /conversations/:id/comments/:comment_id/comment_beta
If you're posting to create a new comment, why aren't you using RESTful routes?
resources :conversations do
resources :comments do
collection do
post 'comment_beta'
end
end
end
should give you /conversations/:id/comments/comment_beta
collection because you don't need an id

Related

Ruby on Rails - How to add a second route for the same action?

I have this route:
resources :posts do
resources :comments
end
A post can be a "User Message" showed at:
/posts
A post can be a "News" showed at:
/news
How can I create the "/news" url inside the routes.rb file and pass a param for know inside the post controller the type of post I want?
This way you can declare routes which can not be declared using resources.
get '/news' => 'posts#index', as: :news

Missing :action key on routes definition Rails

I am getting the following error:
Missing :action key on routes definition, please check your routes.
For this route
resources :groups do
post '/groups/:id/add', on: :member
end
I have looked at several other SO answers on this but am not able to find one that helps me. What action is it missing?
This is not the right way to define routes. Actually router's member/collection accepts a key-value pair to generate the route. As you are defining a member function it will be like:
resources :groups do
member do
post :add
end
end
It will generate a route like: groups/1/add
If you use collection then it will generate: /groups/add
resources :groups do
collection do
post :add
end
end
Hope you get the idea.
Or
You can define specific route for this particular action like below:
match "/groups/:id/add" => "groups#add", via: :post
Key action here means controller action. as in
resources :groups do
post '/groups/:id/add', on: :member, action: "add"
end
Rails can't infer the action from a path. But you can define the action instead and rails will automatically figure out the path:
resources :groups do
post :add, on: :member
end

How to name nested controllers and routes?

I'm working on creating a wiki app from scratch with the following organization:
Main Controller: Wiki
Nested Controller: WikiCategories
Nested Controller: WikiArticles
In my config/routes.rb I have:
resource :wiki do
resources :wiki_categories, :as => :categories
resources :wiki_articles, :as => :articles
end
I've chosen to name the categories and articles controllers as WikiCategories and WikiArticles to differentiate from other category and article controllers that I want to make in the future under a blog nesting.
This gives me the following routes:
/wiki/wiki_categories/new
/wiki/wiki_articles/new
Is there any way to rewrite the routes to be:
/wiki/categories/new
/wiki/articles/new
... while still using the WikiCategories and WikiArticles controller names?
I've chosen to name the categories and articles controllers as WikiCategories and WikiArticles to differentiate from other category and article controllers that I want to make in the future under a blog nesting.
IMO, it seems like you're bucking convention a bit. As discussed in Controller Namespaces and Routing, why not do:
namespace :wiki do
resources :categories, :articles
end
Which will give you:
wiki_categories GET /wiki/categories(.:format) wiki/categories#index
POST /wiki/categories(.:format) wiki/categories#create
new_wiki_category GET /wiki/categories/new(.:format) wiki/categories#new
edit_wiki_category GET /wiki/categories/:id/edit(.:format) wiki/categories#edit
wiki_category GET /wiki/categories/:id(.:format) wiki/categories#show
PATCH /wiki/categories/:id(.:format) wiki/categories#update
PUT /wiki/categories/:id(.:format) wiki/categories#update
DELETE /wiki/categories/:id(.:format) wiki/categories#destroy
wiki_articles GET /wiki/articles(.:format) wiki/articles#index
POST /wiki/articles(.:format) wiki/articles#create
new_wiki_article GET /wiki/articles/new(.:format) wiki/articles#new
edit_wiki_article GET /wiki/articles/:id/edit(.:format) wiki/articles#edit
wiki_article GET /wiki/articles/:id(.:format) wiki/articles#show
PATCH /wiki/articles/:id(.:format) wiki/articles#update
PUT /wiki/articles/:id(.:format) wiki/articles#update
DELETE /wiki/articles/:id(.:format) wiki/articles#destroy
Then, create namespaced controllers, something like:
app/controllers/wiki/categories.rb
class Wiki::CategoriesController < ApplicationController
...
end
and
app/controllers/wiki/articles.rb
class Wiki::ArticlesController < ApplicationController
...
end
Yes it is by specifying the controller, the resource can then be named whichever way you like.
resource :wiki do
resources :categories, controller: 'wiki_categories'
resources :articles, controller: 'wiki_articles'
end
Please see the guide for further information.
You can use the path: option as follows:
resource :wiki do
resources :wiki_categories, path: 'categories', :as => :categories
resources :wiki_articles, path: 'articles', :as => :articles
end
Which will give you:
/wiki/categories/...
/wiki/articles/...
See Translated Paths section of the guides for further details.

Rails 4 Routing conflict

i am rewritting a rails app I did some 5 years ago using rails 1.something.
When I try to browse localhost/companies/search_updates/ I get this error... I know this is a routing error because when I remove the resources :companies from router.rb the thing works fine... How can this be fixed? And do I need to manually add routes for every action I create?
Error when I try to access localhost/companies/search_updates/
The action 'show' could not be found for CompaniesController
Controler
class CompaniesController < ApplicationController
def index
#companies = Company.all
end
def search_updates
# Execute code to search for updates
# Redirect to results
end
end
Routes
resources :accounts
resources :companies
get 'companies/search_updates' => 'companies#search_updates'
search_updates.html.erb
Hello Updates!
The action 'show' could not be found for CompaniesController
Rails routes are matched in the order they are specified, so if you
have a resources :companies above a get 'companies/search_updates' the show action's
route for the resources line will be matched before the get line. To
fix this, move the get line above the resources line so that it is
matched first.
resources :accounts
get 'companies/search_updates' => 'companies#search_updates'
resources :companies
And
Resource routing allows you to quickly declare all of the common
routes for a given resourceful controller. Instead of declaring
separate routes for your index, show, new, edit, create, update and
destroy actions, a resourceful route declares them in a single line of
code.
If you have only index method (default CURD rails) on your controller, you can specific routes for it.
resources :accounts
get 'companies/search_updates' => 'companies#search_updates'
resources :companies, :only => [index]

Rails: Point several nested routes to one customer controller action

How do you point different nested routes to one controller action?
A user can be a member of several groups like company, project, group ect. for which It can request to join, leave or be removed by an admin.
I want to access the remove action for several models and destroy the belongs_to record in the profile model
I already have a polymorphic model that takes requests from a profile to a model( e.g. company) and upon acceptance of the request the profile will belong to the model. once the request is accepted the request recored is destroyed. I feel that the remove action that will destroy the relationship between the profile and the model should be part of the requests_controller, but I guess could be part of the profile_controller.
What I'm thinking I need to end up with is either
/_model_/:id/profile/:id/remove
/company/:id/profile/:id/remove
but how do I get this to point the remove action in my requests controller
or
/_model_/:id/requests/remove
/company/:id/request/remove
I am using the following code in my routes
resources :companies do
resource :requests do
put 'remove', :on => :member
end
resources :requests do
put 'accept', :on => :member
end
end
This is producing a double up of the routes
remove_company_requests PUT /companies/:company_id/requests/remove(.:format)
company_requests POST /companies/:company_id/requests(.:format)
new_company_requests GET /companies/:company_id/requests/new(.:format)
edit_company_requests GET /companies/:company_id/requests/edit(.:format)
GET /companies/:company_id/requests(.:format)
PUT /companies/:company_id/requests(.:format)
DELETE /companies/:company_id/requests(.:format)
accept_company_request PUT /companies/:company_id/requests/:id/accept(.:format)
GET /companies/:company_id/requests(.:format)
POST /companies/:company_id/requests(.:format)
new_company_request GET /companies/:company_id/requests/new(.:format)
edit_company_request GET /companies/:company_id/requests/:id/edit(.:format)
company_request GET /companies/:company_id/requests/:id(.:format)
PUT /companies/:company_id/requests/:id(.:format)
DELETE /companies/:company_id/requests/:id(.:format)
As
My I suggest that you create a new controller to handle this? The advantage is that you can map the route to this controller on any models you want the "remove association" on.
For example:
# RemoveController.rb
class RemoveController < ApplicationController
def destroy
# inplement the logic for deletion. You can use refection to implement
# this function only once for all the applied associations.
end
end
# routes.rb
resources :companies do
resource :requests do
resource :remove, :controller => :remove, :only => [:destroy]
end
end
The above routes would generate:
company_requests_remove DELETE /companies/:company_id/requests/remove(.:format) remove#destroy
You can nest the above line for the remove controller on any nested routes you want and they will all point back to the RemoteController's destroy object, only with different parameters to help you implement the destroy action.
Edit: to add create for specific relationship that you don't want to duplicate you can do this:
# routes.rb
resources :companies do
resource :requests do
resource :remove, :controller => :relationship, :only => [:destroy]
resource :create, :controller => :relationship, :only => [:create]
end
end
company_requests_remove DELETE /companies/:company_id/requests/remove(.:format) relationship#destroy
company_requests_create POST /companies/:company_id/requests/create(.:format) relationship#create
But I think you might need to be careful about breaking the convention of create in the respective controller. I'm not sure if there are any downside to this. The remove part since is only removing association and not the records itself, it doesn't seem to break the convention.
Try
puts 'remove', :on => :member, :controller => :requests, :action => :remove

Resources