Customize nested routes for a cleaner URL in Rails? - ruby-on-rails

I am working on a website and I am trying to change how the URL looks for the users.
As I have all my resources nested, I struggle a lot to do what I want.
At the moment, here are my routes
resources :folders do
resources :portfolio_photos
end
I've changed it to this, which works for the folders index.
resources :folders, except: [:index] do
resources :portfolio_photos
end
get '/photos', to: 'folders#index'
The only problem is that I also want the "portfolio_photos" url to look like this
/photos/:id/portfolio_photos
(and I don't want to change the name of my model).
I've tried that:
get '/photos/:id/portfolio_photos', to: 'portfolio_photos#index'
but it is not working.
Even better would be to get a completely custom URL looking like that on the surface : www.xxxx.com/portfolio_photos
even if everything is nested in the backend.
Is there a way to change how the url looks without touching the whole backend?
Thanks a lot for your help!

After 2 hours of researches, I've found this:
resources :folders, :path => 'photos' do
resources :portfolio_photos
end
Works perfectly and I just had to change the routes file!
Posting it as it will maybe help someone :)
Thanks everyone

Related

What's the "Rails way" to route a "diff" between two instances of the same model?

I'm building a "Brand personality" tool that gives you a report based on the text you share on social media.
I have a model PersonalityReport and in routes I have resources :personality_reports.
A new feature is to offer a "diff" between two reports and I'm trying to work out the most "guessable" way to model this in routes.
Ideally I'd like GET /personality_reports/:personality_report_id/diff/:id or something along those lines, and while I could simply put that into routes as a GET route, is there a more Railsy way of specifying a route using the resources / collections style so that my routes.rb file is more easy to understand?
The 'neatest' way can think of is:
resources :personality_reports, param: 'personality_report' do
member do
get 'diff/:id', to: 'personality_reports#action', as: 'diff_route'
end
end
Where obviously to: is your controller#action, and as: is the name of your route. After running rake routes you will see this generates:
diff_route_personality_report GET /personality_reports/:personality_report_id/diff/:id(.:format) personality_reports#action
I think whatever you mentioned is good enough,
resources : personality_reports do
resources :diffs, only: [:show]
end
So, routes like below,
personality_report_diff GET /personality_reports/:personality_report_id/diffs/:id(.:format) diffs#show
NOTE: You can also make diff route in singular resource :diff if you want to make it as singular resource.

Creating custom routes in Rails for SEO

I am following a tutorial on seo in rails and i got my routes.rb like this
resources :blogs,only: [:new,:index]
get "/blogs/:id", to: redirect("/%{id}")
resources :blogs,:path=>'',except:[:new,:index]
everything should be fine but when i create a blog it doesn't show error and doesn't create a blog too.it just redirects to blogs_path.
what am i doing wrong?
it works fine like
resources :blogs
but then i would lose the benefits of the other code. and i need them for my SEO.
after a day of sleeping on it I found that i had to mention the :create and :update actions to my routes it'll be like this
resources :blogs,only: [:new,:index,:create,:update]
get "/blogs/:id", to: redirect("/%{id}")
resources :blogs,:path=>'',except:[:new,:index]

Rails nested resources and url helpers - how to shorten

In my routes.rb file I have the following resources:
resources :educations do
resources :semesters do
resources :module_assignments do
resources :module_exams do
resources :module_marks
end
end
end
end
Which generates this url helper:
logonname_module_assignment_module_exams_path GET /:student/module_assignments/:module_assignment_id/module_exams(.:format) module_exams#index
Is there any way to shorten this? It should redirect to the same controller and the same action. Instead of
logonname_module_assignment_module_exams_path
I would prefer something like
module_exams_path
Is there a way to solve this? I want all url-helpers like this (index, new, edit, show etc.) not just the show path.
You don't have to nest so deeply.
I personally only go as far as two deep, it just makes it easier to maintain.
But that doesn't answer the question. Or maybe it does.
With your setup. You could do something like:
match '/:student/module_assignments/:module_assignment_id/module_exams(.:format)' => 'module_exams#index', :as => :module_exams
This gives you module_exams_path as a helper.

Rails 3 Routing resources scoped to a username

I have a basic understanding of rails routing, but nothing too advanced. So far I've gotten by using the RESTful resource based routes and a few custom named routes.
I am nearly done my app now though and I wanted to make some pretty urls.
In my app, each user has many pages. What's the best way to make the URL's look like www.sitename.com/username/page_name?
This will route to the pages controller's show action. Params hash includes :username and :page_name.
match "/:username/:page_name" => "pages#show"
Remember to put it last or it will match pretty much everything.
I'm not quite sure what you're using this for, but something like this might work in your routes file:
resources :users do
get 'page_name'
end
Which will produce: users/:id/page_name
You might want to check out the Railsguide on routing.
What you are looking for is a member route (section 2.9.1).
resources :users do
member do
get :cool_page
end
end
Will result in /users/:id/cool_page

Do you have to mess with Rails's "routes.rb" file?

I never touch routes.rb beyond calling map.root to set a default route. I've always been content to use URLs of the form...
/controller/action/perhaps_an_id
and it works fine.
Does this make me a bad person? Am I missing out on something totally awesome?
What if I try to adopt RESTful design? Would that mean I have to edit routes.rb or could I continue to pleasantly ignore it?
(I tried to read up on this topic in The Rails Way but it was unbearable.)
If you generate your resources with the default scaffolding then it will even include the restful routing for you in routes.rb.
If you're not using the scaffolding then the reason that it's working is because of the default routes at the bottom by default:
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
I've been following that it's best practice to remove these for production applications and instead make sure that only the resources that need to be exposed are exposed. With Rails 2.2 you can even limit the RESTful methods from map.resources by:
map.resources :posts, :only => [:index, :show]
map.resources :comments, :except => [:edit]
There's also tons of cool things you can do with nested resources, named routes, etc. They have a lot of examples in the docs (http://www.railsbrain.com/api/rails-2.2.2/doc/index.html?a=M000255&name=resources)
You may also want to make custom named routes for your marketing department (eg: mycoolsite.com/free-trial) that go off to specific controllers and actions, etc.
Ryan Bates has a series of screencasts that go over some of the neat things you can do with routes: http://railscasts.com/tags/14
Not having switched to RESTful design does not make you a bad person and if you feel no need to change keep writing your apps the 1.x way.
The majority of Rails developers has adopted REST and seems to be very happy about it. I don't think there is a need here to repeat all pro REST arguments.
You do need to add one line per resource to your routes file such as:
map.resources :posts
If you were to go RESTful, yes you would have to edit routes.rb and add your resources like,
map.resources :your_resource
or if you have nested resources,
map.resources :people do |person|
person.resources :ideas do |idea|
ideas.resources :bad_ones
end
end

Resources