Prettier routes for Wicked Wizard - ruby-on-rails

I'm using Wicked to build an object in steps, and would like to clean up my routes a little bit.
Currently, my router looks like this:
resources :surveys, only: [:new, :create], path: 'feedback' do
resources :steps, only: [:show, :update], controller: 'survey/steps'
end
So my routes end up being:
GET '/feedback/new' => 'surveys#new'
POST '/feedback/create' => 'surveys#create'
GET '/feedback/:id/steps/step1' => 'survey/steps#show'
PUT '/feedback/:id/steps/step1' => 'survey/steps#update'
Ideally, I'd like to remove both the survey id and the 'steps' name from my routes, so that they look like this:
GET /feedback => 'surveys#new'
POST /feedback => 'surveys#create'
GET /feedback/step1 => 'survey/steps#show'
PUT /feedback/step1 => 'survey/steps#update'
...
Any simple way to do this?

resource :steps #as singular
resources :surveys, only: [:new, :create], path: 'feedback' do
resource :steps, only: [:show, :update], controller: 'survey/steps'
end

Related

How to name nested routes parameters in Rails?

I've the following nested route:
resources :carts, only: [:show, :update, :create], param: :token do
resources :items, :controller => :cartitems, except: [:new, :edit], param: :product_id
end
This generates
GET /api/merchants/:merchant_id/carts/:cart_token/items(.:format) cartitems#index
POST /api/merchants/:merchant_id/carts/:cart_token/items(.:format) cartitems#create
GET /api/merchants/:merchant_id/carts/:cart_token/items/:product_id(.:format) cartitems#show
PATCH /api/merchants/:merchant_id/carts/:cart_token/items/:product_id(.:format) cartitems#update
PUT /api/merchants/:merchant_id/carts/:cart_token/items/:product_id(.:format) cartitems#update
DELETE /api/merchants/:merchant_id/carts/:cart_token/items/:product_id(.:format) cartitems#destroy
...
I want to remove the controller part in the resources :items parameters. That means: I want to rename the :cart_token parameter to :token. Just like:
GET /api/merchants/:merchant_id/carts/:token/items(.:format) cartitems#index
POST /api/merchants/:merchant_id/carts/:token/items(.:format) cartitems#create
GET /api/merchants/:merchant_id/carts/:token/items/:product_id(.:format) cartitems#show
PATCH /api/merchants/:merchant_id/carts/:token/items/:product_id(.:format) cartitems#update
PUT /api/merchants/:merchant_id/carts/:token/items/:product_id(.:format) cartitems#update
DELETE /api/merchants/:merchant_id/carts/:token/items/:product_id(.:format) cartitems#destroy
...
How can this be achieved?
Don't know if it's the best way to do that, but I got the routes you expected there by:
scope 'api/mechantes/:merchant_id/carts/:token' do
resources :items, :controller => :cartitems, except: [:new, :edit], param: :product_id
end
Hope this can helps. Good luck!

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.

Rails Adding New Page to Resource (with parameter)

I am trying to add a few new pages to a rails resource that I am creating.
What I am doing in my routes file is as follows:
resources :users, :only => [:index, :show] do
collection do
get :show_subpage1
end
end
When I look at my routes, show_subpage1 shows up, but not in the format I want. What shows up in the routes is:
show_subpage1_users GET /users/show_subpage1(.:format)
When what I WANT the route to be is:
show_subpage1_users GET /users/:id/show_subpage1(.:format)
(with the ID).
How would I go about doing that in rails?
To get:
show_subpage1_users GET /users/:id/show_subpage1(.:format)
do not define :show_subpage1 as a collection route:
resources :users, :only => [:index, :show] do
get :show_subpage1
end
or you could define it as a member route as follows:
resources :users, :only => [:index, :show] do
member do
get :show_subpage1
end
end
Also, I'm unsure why you have :only => [:index, :show] defined if you are also going to have a member route :show_subpage1. I assume you do want to add add :show_subpage1 to the only array, i.e. resources :users, :only => [:index, :show, :show_subpage1] do.
Please take a read on "Adding More RESTful Actions"
there are two ways with resources member or collection
resources :users, :only => [ :index, :show ] do
# /users/:id/profile
get 'profile', :on => :member
# /users/profile
get 'profile', :on => :collection
end
hope this helps

Selecting model based off of route in Rails

I have a polymorphic model Discussion. It can be applied to Specialty model and Program model. My routes are set up as:
resources :programs, :only => :show do
resources :discussions, :only => [:show, :create, :destroy, :new]
end
resources :specialties do
resources :discussions, :only => [:show, :create, :destroy, :new]
end
So, new discussions are made either like:
/specialties/yyyyy/discussions/new
/programs/yyyyyy/discussions/new
The problem is in my discussions_controller.rb file. I have the function:
def new
#object = xxxxx.find(params[:id])
end
How do I choose the appropriate model for the form (eg. to replace 'xxxxx') and for determining the discussionable_type. I would assume I could parse the URL, but it doesn't seem clean. Any ideas?
Given your routes, you should either have params[:program_id] or params[:specialty_id] (or alike).
This will tell you what to use.

Resources