Removing resources from url - ruby-on-rails

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'

Related

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.

Is it possible to have same routes with different show action in rails?

I am trying to reach the following url in my rails app:
example.com/user12 # It should show user#show
exmple.com/wordpress # It should show category#show
My solution: (it does not work)
In the routes.rb I have added :path => '' to both categories and users in order to remove the controllers' name from the url.
resources :categories, :path => ''
resources :users, :path => ''
When I run rake routes, I have the following urls"
category GET /:id(.:format) category#show
account GET /:id(.:format) accounts#show
So I assumed that It should be working correctly, but surely not. It only works for category names and for usernames it shows ActiveRecord::RecordNotFound.
I know, my solution is wrong because I am confusing rails route system and because the resources :categories has more priority over resources :users, the category show page works fine.
So Is there any solution to solve an issue like this?
I have finally found the solution with constraints option. This option accepts regular expressions.
resources :categories, :path => '', constraints: { id: /wordpress|php/ }
Every category should be added manually in this way OR (I am not sure) maybe there is a way to list all categories from database automatically.
One way of doing that is to override the default rails routes, to do that remove the resources
I tested and this works
SampleRails4::Application.routes.draw do
get '/user12', to: 'users#show' #=> users/show
get '/wordpress', to: 'category#show' #=> assuming u have a controller and action
end
however then you have to update the rest of your code, Ex: users/show might be expecting the user id as a param read more about rails routing

Routing: prefix item name before controller resources

I am trying to get the following routes to work in my Rails 3 app.
Scenario:
I have the following controllers in my app:
Practices
Doctors
Patients
Prescriptions
Putting up :resources for each of them in routes.rb gives me routes from
example.com/practices
example.com/doctors/1/edit etc
What I'd like to have however is the following resourceful routes, for example:
example.com/james_practice/docs that translates to the doctors controller
example.com/james_practice/awesome_prescriptions that routes to the prescriptions controller etc. etc.
both of these giving me access to :practice name and furthermore route the correct controller with all the helpers like edit_docs_path(doctor) etc.
How would I go about this? I've used
resources :prescriptions, :path => "/:practice/awesome_prescriptions"
but although it showed the correct routes in "rake routes", it still wouldn't work as expected.
I think this is the route you're looking for:
scope :path => ":practice" do
resources :docs, :controller => "doctors"
resources :awesome_prescriptions, :controller => "prescriptions"
end
By the way, you didn't give me the example of Patients, so I didn't put it there.
map.resources is just a pattern, more like a shortcut. If you want to have URLs like in your examples you should use "named routes". A good screencast for Rails 2.x: http://railscasts.com/episodes/34-named-routes
Edit: Read section 3.2 in Rails Tutorial: http://guides.rubyonrails.org/routing.html
p.s. Also you'll face a case where people use "." in their names and it'll cause problems.
Here's my route for "tags"
map.resources :tags, :requirements => { :id => %r([^/;,?]+) }

Can I change my map.resources line in routes.rb to change the model name in the URL?

At the moment, I have this line in routes.rb
map.resources :usernotes
so my paths are /usernotes/new etc
But I realise now I want them to be like /notes/new
Is there a way to change the line in routes.rb to do this?
Yep, it's super-easy:
map.resources :usernotes, :as => 'notes'
See section 3.7.4 here:
http://guides.rubyonrails.org/v2.3.8/routing.html#controller-namespaces-and-routing (for Rails 2.3.x)
or here for Rails 3: http://guides.rubyonrails.org/routing.html#naming-routes
This will give you /notes and /notes/new etc
resources :notes, :controller=>"UserNotes"
You'll use new_note_path etc

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