links to scoped routes - ruby-on-rails

I'd like to use scoped routes for internationalizing. Here's my routes.rb
scope "(:locale)", locale: /en|pl/ do
resources :announcements, only: [:index], path: '/news'
resources :diplomas, only: [:index, :show], path: '/graduates'
end
Goal is to point urls like website.domain/pl/news to announcements controller and then check params[:locale] in ApplicationController in some before_action method.
But I have problems with generating urls. As I said before I want only good looking urls and my sense of aesthetics tells me that appname.domain/news/?locales=pl is not something I'm looking for. :(
So I have question:
Is there any option to generate links like appname.domain/pl/news/ when using scoped routes?
Thanks for help!

Your routes are scoped in a way, so that they can be called like this:
your.domain/pl/news
your.domain/en/news
if this pleases your aesthetics.
So, in other word, yes.
Have a look here, on how to use and set this:
http://guides.rubyonrails.org/i18n.html#setting-and-passing-the-locale

Related

Overriding routes parameters with NIL in Rails?

Is there a way to use resource routing instead of writing the routes one by one if my methods for which the default expects parameters don't use parameters?
For example, if I had a routes file like below, the expected path for the update method would be like this: /cats/:id (docs)
# routes.rb
Rails.application.routes.draw do
resources :cats, only: [:create, :update]
end
However, I don't require any params for my update method, meaning the path should be /cats.
I know there's a way to rename the params and not use :id, but I didn't find anything on disabling them. I tried adding param: nil to the end of the line but it didn't work.
As I wrote initially, I know this can be done if I write the routes one by one like below. My question is whether I can use resources to do it. Thank you!
# routes.rb
Rails.application.routes.draw do
post 'cats', to: 'cats#create'
put 'cats', to: 'cats#update'
end
This is exactly the use case for singular resources. Quote from the Rails Guides:
Sometimes, you have a resource that clients always look up without referencing an ID. For example, you would like /profile to always show the profile of the currently logged in user.
Change our routing to
resource :cats, only: [:create, :update]
And the following routes will be created:
cats PATCH /cats(.:format) cats#update
PUT /cats(.:format) cats#update
POST /cats(.:format) cats#create
As far as I know, there is not, resource is just a helper to create the standard verb-based CRUD routes, if you want custom routes you need to define your update route the way you did in your second example, of course, you can still use resource for your create route and just pass only: :create.

Is the order of the routes in the routes.rb important?

My routes.rb file looks like:
resources :contents, only: [:show]
get 'contents/by_hardware', to: 'contents#show_by_hardware'
With this setup I am not able to access the contents/by_hardware route.
But if I setup my routes.rb file in a different order, everthing works.
get 'contents/by_hardware', to: 'contents#show_by_hardware'
resources :contents, only: [:show]
Is the order in the routes.rb file important?
Yes, order matters very much.
It works like this: resources :contents, only: [:show] creates this route
content GET /contents/:id(.:format) contents#show
So when you request, for example, http://localhost:3000/contents/by_hardware, it is this route that matches this url. It invokes ContentsController#show action with params {'id' => "by_hardware"}. Your custom action is not considered, because matching route is already found.
Yes, order does matter. Instead of defining routes for the same controller at two different places, I would recommend you to define routes for the above scenario this way
resources :contents, only: [:show] do
get :show_by_hardware, on: :collection, path: :by_hardware
end
Hope that helps!
Yes it is important, the routes will be matched from top to bottom so you can move your route get 'contents/by_hardware', to: 'contents#show_by_hardware' above resource to fix your problem
yes. router will match first route from the top

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

Nested pages with routing

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.

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.

Resources