Rails nested resources and url helpers - how to shorten - ruby-on-rails

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.

Related

Customize nested routes for a cleaner URL in 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

Removing resources from url

I have a few nested resources (namespaces, pages and comments), and url looks like this:
http://example.com/namespaces/objects/pages/super-page — it's too long.
What is the best way to remove resources names from routes? I want to get something similar to this:
http://example.com/objects/super-page/
Update: there are only show action in the namespaces controller.
You can set the path attribute on the reources
resources :pages, :path => '' do
I found this article very helpful in customizing my url's http://jasoncodes.com/posts/rails-3-nested-resource-slugs
There is also a great gem for getting rid of the id's and customizing the slug, friendly_id's, http://railscasts.com/episodes/314-pretty-urls-with-friendlyid
you can use shallow parameter in routing
e.g.:
resources :namespaces, :shallow => true do
resources :objects do
resources :pages
end
end
and then you can use routes like
page_path(1) #=> '/pages/1'
object_page_path(1,1) #=> '/object/1/pages/1'
namespace_page_path(1, 1) #=> '/namespace/1/pages/1'

Router for nested resources in a "not usual" Ruby on Rails way

I am using Ruby on Rails 3.0.7 and I am trying to set nested resource routing to make it to work in a "not regular" RoR way.
In my routes.rb file I have
resources :articles do
resources :categories, :only => [:index], :controller => 'articles/categories' # The related controller is Articles::CategoriesController
end
so that I can browse following URLs:
<my_site>/articles/1/categories
<my_site>/articles/2/categories
...
What I would to do is to access new, edit and show controller actions for categories by using the same articles/categories controller used for the nested resource stated above (that is, Articles::CategoriesController) and by accessing these URLs:
<my_site>/articles/categories/new
<my_site>/articles/categories/edit
<my_site>/articles/categories/1
<my_site>/articles/categories/2
...
How can I do that? How I must code the router?
Maybe I can do something by using the router collection method like this
resources :articles do
collection do
# match something here for the Articles::CategoriesController...
end
resources :categories, :only => [:index], :controller => 'articles/categories'
end
but I don't know how to do that.
I'm not real sure what you're trying to do with those routes, so I'm not quite sure how to answer your questions. If your intent is to be able to add a new category for a particular article, or edit all the categories for a particular article, you have to pass an ID for the article. If you're trying to create a new article and a new category all at once, you don't need category in the route, just the article and you can do something like form_for([#article,#category]) in your form and use the build method in your controller. If you can clarify, I might be able to help you further (in other words, it's not hard to construct those routes -- but it depends on what you want to do with them.

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