Nested pages with routing - ruby-on-rails

I need to make nested pages (like when the one page(page1) is a parent for the other page(page2), and routes for these pages looks like: site.com/page1/page2. What gem should help me to do that ?

I don't know if there is a gem for this, but I would start with a route something like:
get 'pages/*parents/:page', to: 'pages#show'
The URL site.com/pages/page1/page2/page3 will be parsed to the params:
params[:parents] = 'page1/page2'
params[:page] = 'page3'
Now you can do something like:
parent_names = params[:parents].split('/')
Not sure if this is what you want but I hope it will get you started.

This is not common good practice. I'm not saying you should not do it as I don't know anything about your business logic but the usual practice is
/model_name/:id/model_name/:id
with at most one level of nesting. That means no such things as
/model_name/:id/model_name/:id/model_name/:id
In general, I favour the shortest possible path. Hence, if the resource can be identified with just its id, I go with /model_name/:id.
This often results in things such as
resources :post do
resources :comments, only: [:new, :create]
end
resources :comments, only: [:show, :edit, :update, :destroy]
I hope that helped.

Related

Rails: How exactly does the "shallow" option benefit us?

So i've been learning rails for a little bit. Sometimes routing I get confused on (Well not so much confused but just figuring out "best practices").
One thing i've never used is the "shallow" option, such as in this example in the docs:
resources :articles do
resources :comments, only: [:index, :new, :create]
end
resources :comments, only: [:show, :edit, :update, :destroy]
Which is what shallow would do if just appended onto the :comments portion.
So how exactly is this a benefit? does it just basically prevent the paths from being /articles/comments/:id for multiple things and instead just being /comments/:id for the methods? Unless im missing something?
Resources should never be nested more than 1 level deep.
Keeping this in mind we always try to avoid deep nesting.
shallow option is just used to avoid complicated(deeply) nested routes wherever possible. It should be used only for the resources which are bound to their parents.

How to use "link_to" in an Admin section correctly in Rails

So I have an app which has an admin section. The admin section has a challenges controller with an index method and a view index.
I have also a challenges controller seperate from the admin folder. This controller has the whole CRUD.
Every challenge belongs_to a subject. The controller subjects in the admin section has an index method and view. The controller subjects not in the admin section has the whole CRUD.
Now, in the view of subjects (NOT the admin section), I can do something like:
<%= link_to "New Challenge".html_safe, new_subject_challenge_path(#subject) %>
I would like to do the same in the admin-section, but I can't really figure out how to do it. Copying the code throws me an error:
No route matches {:action=>"new", :controller=>"challenges", :subject_id=>nil} missing required keys: [:subject_id]
But I was hoping I could do this without additional routes....
It seems like it should be easy but I don't really know how to handle this. Any help would be very much appreciated... I hope I explained myself well enough.
The admin routes are used with a namespace:
namespace :admin do
resources :paths, only: [:index, :new, :create, :update, :edit]
resources :users, only: [:index, :new, :create, :show, :edit, :update]
end
resources :challenges, except: [:index, :destroy] do
resources :solutions, only: [:create]
end
resources :subjects
The link you are creating points to a route that requires a subject id. In the subjects view it works because Rails can find the subject_id in the #subjectthat you are passing to the path helper.
When you copy and try to re-use the same link in your admin view, I expect that #subject is not assigned and so it cannot find the required subject_id. Provide your admin section view with the subject and it should work!
Also if you want to get a clearer idea of routing, the Rails docs are pretty great.

Why does this route setup result in these path variables?

In my rails 4 application, I have a piece in routes.rb that looks like this:
namespace :settings do
resources :profile, only: [:index] do
put :update_user, on: :collection
end
end
The controller is located in app/controllers/settings/profile_controller.rb and looks like this:
class Settings::ProfileController < ApplicationController
def index
end
def update_user
end
end
This results in these paths from rake routes:
PUT update_user_settings_profile_index -> /settings/profile/update_user(.:format)
GET settings_profile_index -> /settings/profile(.:format)
What I don't understand is why these paths have _index in them. I would like to get rid of it. Can I? If so, how?
I think that's because you're using a singular name profile for your resources definition, which should be plural by convention. You can try using resources :profiles instead.
For me, with routes it is always easier to work backwards, asking what are the paths I want? I'm not sure what paths you want, but I'll give you some ideas here, I hope.
I'm going to assume you want one index path, since you explicitly include the the only: [:index] statement, but you do not want not a indexed path on your resources.
Try moving your only: [:index] statement into the outer do loop for settings and add an only: [:update] to your profile (or whichever action you're looking for)
namespace :settings, only: [:index] do
resources :profile, only: [:update] do
put :update_user, on: :collection
end
end
Gets you here:
update_user_settings_profile_index PUT /settings/profile/update_user(.:format) settings/profile#update_user
settings_profile PATCH /settings/profile/:id(.:format) settings/profile#update
PUT /settings/profile/:id(.:format) settings/profile#update

Mapping to the custom route

So far I have my routes like this: ( out of learning purposes I am curious to get it working with nested resources technique, but if you think this will get too complicated please feel free to suggest any other way of routing technique too)
resources :management, only: [:show] do
resources :report, only: [:show], controller: 'report' do
member do
# hmm what to write in here?!
end
end
end
my GOAL is to have a URL like this:
/managment/SOME_ID_WE_PASS_/report
/managment/1/report
But still can't figure out how exactly to write that route? Can you please take a look?
You don't need nested resources.
resources :crowd_management, only: [:show] do
get :exec_report, on: :member
end
That will produce:
/crowd_management/:id mapped to CrowdManagementController#show
/crowd_management/:id/exec_report mapped to CrowdManagementController#exec_report
The helper methods will be:
crowd_management_path
exec_report_crowd_management_path
You can run rake routes for a detailed list of all your routes.

Custom rails routing helper method

I am having issues getting my helper method names to work properly, any suggestions would be great:
#config/routes.rb
resources :junkie, only: [:show, :index, :destroy], as: :junkie do
get :merge, on: :collection
end
So I was having issues because I the singular form of junkies is junky, but when I make this change and look at the routes it changes the #merge helper to:
merge_junkie_index GET /junkies/merge(.:format) junkies#merge
Is there any way to change this to just merge_junkie? I tried removing it from the resource black and using the match syntax: get "junkies/merge" => "junkies#merge", as: :junkie but for some odd reason this directed me to the show method even though the route was right.
The solution is a ugly one but it works, since the show route is the only one that is affected by the as: :junkie you can break it out put the merge route in a separate block. The ordering of the resource also matters for some reason, if you do not put the merge first, it will interpret the url /junkie/merge/ as a id and hit the show action. So it should look like this in your routes file:
resources :junkies, only: [:index] do
get :merge, on: :collection
end
resources :junkies, only: [:show, :destroy], as: :junkie

Resources