Renaming rails route parameter to id - ruby-on-rails

In my routes.rb file, I have the following resources
resources :classrooms, only: [:index, :new, :create] do
resources :students, only: [:index, :edit, :update], controller: 'students' do
get :honor
end
end
My honor route becomes /classrooms/:classroom_id/students/:students_id/honor(.:format)
but I want to replace student_id to id so that I can easily use it in the students controllers.
Ideal route is /classrooms/:classroom_id/students/:id/honor(.:format)

You can do that specifying it's a member route. this way
get :honor, on: :member
or
member do
get :honor
end

Related

rails - how to target nested controller for nested resource route

In my routes.rb I have
namespace :admin do
resources :clients do, only: [:index] do
resources :products, only: [:index, :new, :create]
end
resources :products, only: [:index]
end
Notice that I have two lines for resources :products. One is nested within resources :clients and the other as a top-level resource on :admin; each of these two has a different purpose in the application.
rake routes gives me:
admin_clients GET /admin/clients(.:format) admin/clients#index
admin_client_products GET /admin/clients/:client_id/products(.:format) admin/products#index
POST /admin/clients/:client_id/products(.:format) admin/products#create
new_admin_client_product GET /admin/clients/:client_id/products/new(.:format) admin/products#new
admin_products GET /admin/products(.:format) admin/products#index
I have a admin_client_products for the nested product#index resource. I also have admin_products for the top-level product#index resource. However, they point to the same controller action: admin/product#index.
Question: At this point, I need rails to deduce that these are two different actions. Using rails conventions, is there a way to tell rails that these two resources should have different controller actions i.e. one that should hit admin/products#index and the other should hit admin/clients/products#index?
The nested route should hit this:
class Admin::Clients::ProductsController < Admin::BaseController
def index; end
end
The top-level route should hit this:
class Admin::ProductsController < Admin::BaseController
def index; end
end
Definitely you can!
Here you need to customize your resourceful route by explicitly specifying a controller to use for the resource. The :controller option will let you do that.
So, in your case, specifying the controller as clients/products for the admin_clients_products resource would work in your desired way.
namespace :admin do
resources :clients, only: [:index] do
resources :products, only: [:index, :new, :create], controller: 'clients/products'
end # ------------------------------
resources :products, only: [:index]
end
rails routes will now give you what you want:
admin_client_products GET /admin/clients/:client_id/products(.:format) admin/clients/products#index
POST /admin/clients/:client_id/products(.:format) admin/clients/products#create
new_admin_client_product GET /admin/clients/:client_id/products/new(.:format) admin/clients/products#new
admin_clients GET /admin/clients(.:format) admin/clients#index
admin_products GET /admin/products(.:format) admin/products#index
=========================
Extra bits:
If you want to omit the /admin portion from the url (I mean, if your application's routing design permits to), then you could use: scope module: 'admin' do...end like the following:
scope module: 'admin' do
resources :clients, only: [:index] do
resources :products, only: [:index, :new, :create], controller: 'clients/products'
end
resources :products, only: [:index]
end
and suddenly your routes will start looking awesome :)
client_products GET /clients/:client_id/products(.:format) admin/clients/products#index
POST /clients/:client_id/products(.:format) admin/clients/products#create
new_client_product GET /clients/:client_id/products/new(.:format) admin/clients/products#new
clients GET /clients(.:format) admin/clients#index
products GET /products(.:format) admin/products#index

Static nested resource params name on Rails routes

I'm playing on Rails routing but I can't figure out how to manage this. The problem is at user_posts(1) and user(4) routes, the params have different names - id and user_id
What I'm trying to achieve is a static param name for the same resource.
I have this route file
Rails.application.routes.draw do
shallow do
resources :users, module: :users, only: [:index, :show] do
resources :posts, module: :posts, only: [:index, :show]
end
end
end
The routes generated are
user_posts(1) GET /users/:user_id/posts(.:format) users/posts/posts#index
post(2) GET /posts/:id(.:format) users/posts/posts#show
users(3) GET /users(.:format) users/users#index
user(4) GET /users/:id(.:format) users/users#show
I tried resources :user param: :user but the generated route at user_posts is /users/:user_user_id/posts
Is possible to achieve a :user_id param and :post_id param for every route using resources?
Try this
resources :users, param: :user_id
resources :users, only: [] do
resources :posts, param: :post_id
end
It is not possible 'cause it is useless. Your only option is to nest post into the user resources in such manner:
resources :users, only: [:index, :show] do
resources :posts, only: [:index, :show]
end

Nesting APIs routes

Im trying to create API endpoints from my Post model . It should be able to read, update, delete and create posts.
But a post needs to be assosiated to a Topic in order for it to be created so i nested it under topics. Here are my routes
namespace :api do
namespace :v1 do
resources :users, only: [:index, :show, :create, :update]
resources :posts, only: [:show, :update, :destroy]
resources :topics, except: [:edit, :new] do
resources :posts, only: [:create]
end
end
end
api_v1_post GET /api/v1/posts/:id(.:format) api/v1/posts#show
PATCH /api/v1/posts/:id(.:format) api/v1/posts#update
PUT /api/v1/posts/:id(.:format) api/v1/posts#update
DELETE /api/v1/posts/:id(.:format) api/v1/posts#destroy
api_v1_topic_posts POST /api/v1/topics/:topic_id/posts(.:format) api/v1/posts#create
api_v1_topics GET /api/v1/topics(.:format) api/v1/topics#index
POST /api/v1/topics(.:format) api/v1/topics#create
api_v1_topic GET /api/v1/topics/:id(.:format) api/v1/topics#show
PATCH /api/v1/topics/:id(.:format) api/v1/topics#update
PUT /api/v1/topics/:id(.:format) api/v1/topics#update
DELETE /api/v1/topics/:id(.:format) api/v1/topics#destroy
my issue is im getting a "no routes match" error when i run my Rspec
I think the issue is with the relationship.
Please add the relationship between Topic and Post and then try.
class Topic < ActiveRecord::Base
has_many :posts
end
class Post < ActiveRecord::Base
belongs_to :topic
end
If the route you are trying to create is POST api/v1/topics/:topic_id/create_post going to TopicsController than you would want the nesting to look like this instead:
resources :topics, except: [:edit, :new] do
post 'create_post' => 'topics#create_post'
end
Try this out for creating your routes if you haven't had success yet. It should provide the output that you want.
resources :topics, except: [:edit, :new] do
collection do
post 'create_post'
end
end

Polymorphic Comments in both nested resource and simple resource ruby on rails 4

I have following relationship routes:
resources :courses, only: [:index, :show] do
resources :enrols, only: [:new, :create]
resources :lectures, only: [:show]
end
resources :code_casts, :path => 'casts', :as => 'casts', only: [:index, :show]
resources :blogs, :path => 'blog', :as => 'blog', only: [:index, :show] do
resources :blog_votes, only: [:create, :destroy]
end
I want polymorphic comments in courses, lectures, code_casts and blog.
Problem is lecture has a parent of course so route will be course/course_id/lecture/id and blog path will blog/id where comments will have different show pages.
If I understand the problem correctly, there is nothing special about deeply nested resources. So you might need something like this
# routes.rb
concern :commentable do
resources :comments
end
resources :courses, only: [:index, :show] do
resources :enrols, only: [:new, :create]
resources :lectures, only: [:show], concerns: [:commentable]
end
resources :code_casts, :path => 'casts', :as => 'casts', only: [:index, :show]
resources :blogs, :path => 'blog', :as => 'blog', only: [:index, :show], concerns: [:commentable] do
resources :blog_votes, only: [:create, :destroy]
end
This will create nested comments resources for lectures and blogs.
Than you need to differentiate the path in a comments controller
# comments_controller
def create
Comment.create(commentable: commentable, other_params...) # assuming you have `commentable` polymorphic belongs_to
end
# a little more ugly than Ryan suggests
def commentable
if request.path.include?('blog') # be careful. any path with 'blog' in it will match
Blog.find(params[:id])
elsif params[:course_id] && request.path.include?('lecture')
Course.find(params[:course_id).leactures.find(params[:id]) # assuming Course has_many lectures
else
fail 'unnable to determine commentable type'
end
end
All 'magic' is in commentable method, where youare checking the path and determine which commentable object to pick. I use similar approach, but this exact code is written by memory without testing. Hopefully you've got the idea.

Getting ActionController::RoutingError uninitialized constant while trying to use namespace in Rails routes

I have two controllers dashboard and posts. Im trying to put the post's :new, :create, :destroy, :edit, :update actions within dashboard url like this dashboard/posts/new. But the im talking to the new action in the posts controller. Not in the dash controller. Here's my routes.rb file :
resources :posts, :except => [:new, :create, :destroy, :edit, :update]
get 'dashboard', to: 'dash#show'
namespace :dashboard do
resources :posts, :only => [:new, :create, :destroy, :edit, :update]
end
get 'dashboard/posts', to: 'dash#posts'
The two controllers in question are : dash and posts
Now when I try to visit http://localhost:3000/dashboard/posts/new it says :
ActionController::RoutingError at /dashboard/posts/new
uninitialized constant Dashboard
How to fix this?
Assuming that you have two controllers DashController and PostsController.
And you want to access few of the posts routes within the scope of namespace then you can define the routes as below:
resources :posts, :only => [:index, :show]
get 'dashboard', to: 'dash#show'
scope :dashboard do
resources :posts, controller: :posts ,:only => [:new, :create, :destroy, :edit, :update]
end
get 'dashboard/posts', to: 'dash#posts'
The constant "Dashboard" can't be found. I think the problem is that you sometimes use dash and sometimes use dashboard.

Resources