I am trying to make my urls prettier and still use restful resources. I understand that you can override the to_param method if you object has a name property like this:
def to_param
self.name
end
which will give you the route /:model/:name. This is all straightforward, but I have to be capable of having the same name with multiple different languages. I haven't been able to find a blog entry on how to do this, so how can i override the to_param method to provide me a route similar to /:model/:language/:name ?
You could always do:
/language/:language/model/:name
You'd do this with nested routes:
map.resources :languages do |l|
l.resources :profiles
end
Then your route would be:
langauge_profile_url('spanish', #profile)
However...
Depending on what you're trying to do you might be better of using the built in rails i18n stuff. Is this so users can browse the site in different languages??
Related
i'm doing a course system, and i would like to simplify the routes.
i routed like this:
resources :courses do
resources :modules do
resources :lesson
end
end
and returned this:
/courses/:course_id/modules/:module_id/lesson/:id
/courses/:course_id/modules/:id
/courses/:id
etc...
i want my routes like that:
/courses/:course_name/:module_name/:lesson_name
/courses/:course_name/:module_name/
/courses/:course_name/
etc...
but how?! :(
in the routes file
get "/courses/:course_name/:module_name/:lesson_name", as: :courses
then you should be able to generate the path:
courses_path(course_name: course.name, module_name: module.name, lesson_name: lesson.name)
But I would recommend against it as:
1) This is fighting conventions: don't expect good support for this, none of the new developers who join the project will like you for this.
2) You will have to make sure all course/module/lesson names are unique and url-friendly
3) You'll have to make sure the names never change, because then the urls would change.
I would advice sticking to the default nested paths and overriding #to_param on every module
to smth like:
def to_param
"#{super}-#{name.downcase.gsub(' ', '-')}" # you need a better regex here
end
so the urls look like
/courses/33-computer-science/modules/23-engineering/lesson/56-design-patterns
More about custom routes: http://guides.rubyonrails.org/routing.html#dynamic-segments
I am little bit confused in using rails route. I need some suggestion about customizing my url.
This is my current url
http://localhost:3000/posts/product/41?product_id=2
and
http://localhost:3000/posts/product/41?model_id=24&product_id=2
This is my link
<%= link_to product_model.name, controller: :posts,action: :product,product_id: params[:product_id],model_id: product_model.id
Logically product should come first in url. But why model prefers first here.
And i need my url something like this
http://localhost:3000/posts/product/41/mobile
and
http://localhost:3000/posts/product/41/mobile/nokia
Since i am not familiar with rails route i didn't write any special coding in my route
Here is the simple route exist
resources :posts
Ok your question here actually contains two different problems, so i will give suggestions to both.
1. Nested resources
Your first problem is to use "nested routes". Rails guide has a long and good article about routes and how to write and use them, including nested routes. You can check it out here: http://guides.rubyonrails.org/routing.html#nested-resources.
However in your situation would the solution look something like this:
resources :category do
resources :sub_category do
resources :products do
resources :models
end
end
end
You can now greate links like this
<%= link_to product_model.name, category_sub_category_product_model_path(#category, #sub_category, #product, product_model) %>
You can see that i have removed posts, see 3. Refactor design to see why. If you really want this as a action on posts, should you however do something like this (but would recommend this!):
get "posts/product/:category_id/:subcategory_id/:product_id/:model_id", to "posts#product", as: :posts_product
This would be used like this in your views:
<%= link_to product_model.name, posts_product_path(#category, #sub_category, #product, product_model) %>
2. Pretty URL's
Your second problem is to use model names instead of id's in your urls. The simpels solution for this is having a unique attribute on your model that you can use instead of id, and then just add a to_param method. Fx for product could we do something like this:
class Product < ActiveRecord::Base
def to_param
name
end
end
Ryan Bates have made a good screencast about this: http://railscasts.com/episodes/63-model-name-in-url-revised. If you want something more flexible should you use the gem Friendly Id. And again does Ryan comes to the rescue with another great RailsCast: http://railscasts.com/episodes/314-pretty-urls-with-friendlyid.
3. Change design
Ok well so this is just my opinion, feel free to ignore it. But their is some bad practices and signs in your examples, so let me just quickly go through what i think you should improve on.
Restful actions
You should, when possible always avoid creating controller actions that is not restful (simply put is the base actions index, show, new, create, edit, update and destroy the only restful actions). In your example does this mean that the product action of the posts controller should be changed to something restful. Why not move it to the product model controller and call it "show"?
Deeply nested resources
You should avoid nesting your routes to deeply. Is it really important to show both the category, the sub category, the product AND the model in your url? Maybe that's how your models are associated internally in your application but why should the user know this? If you don't have a list of subcategories at "/posts/product" and a list of products at "posts/product/41" is there no reason to have so long a route. A rule of thumb is "nest no deeper then two levels", ie. ":category/:sub_category". Further more does short routes mean better SEO.
As i said, feel free to ignore these suggestions, your application would work without these changes. However changing these things would greatly help you structure you code, and keep your codebase clean and maintainable. These rules and principles is not something i have just conjured out of nothing, but very accepted principles in the Rails community. You can google each of these principles or patterns and see a lot of articles and posts on why it's a good idea to follow them, especially when you work with Rails.
Resources
Rails Routing from the Outside In — Ruby on Rails Guides
norman/friendly_id - Github
#314 Pretty URLs with FriendlyId - RailsCasts
#63 Model Name in URL (revised) - RailsCasts
Take a look at the friendly-id gem
There's a great RailsCast about it
Add this to your model inmodel.rb
def to_param
name
end
and then add
#model = Model.find_by_name(params[:id]) to your show method, then you can get the url as you mentioned above.
PS: You Should have name field for Model table in your schema.
I think you are looking for nested routes. Please refer this link http://guides.rubyonrails.org/routing.html#nested-resources
and use to_param method in the model if you want to display model_name instead of id as explained by #Ajay Kumar
def to_param
name
end
where name is the model attribute for that specific model.
Why not a namespace?
namespace :posts do
resources :products
end
This should do I think..
Namespace does not include restful ids into the scope..
I have a question about browser string in rails.
For example i have rails app with routes:
resources :posts
and this resource create :
post/:id
post/21
post/167
post/356
but i create a simple blog and i want to rename ':id' to
post/some-name
post/another-name
post/another-different-name
in post i have title, text field
but i dont know how do this
I know that this can be achieved through manipulation of the :id
can you post some link with detailed answer on this question, or some simple example
You can of course put anything you want in the URL and actually there is railcast about it:
http://railscasts.com/episodes/63-model-name-in-url
It is preferable (read: easier) to also keep model.id in the URL, or it means that post name MUST be unique, otherwise you can put anything you want:
/post/2465-my-pretty-post-name
Also, there is a gem friendly_id and related railcast:
http://railscasts.com/episodes/314-pretty-urls-with-friendlyid
Hope that helps.
Why do you want to change /post/:id ?
You can achieve something like /post/:id/comments
You can do that using nested resources like this in your routes.rb
resources :posts do
resources :comments
end
Check here for more details
http://guides.rubyonrails.org/getting_started.html
If you add the to_param method to the model then you can use that within your URL system.
class SomeModel < ...
def to_param
self.title
end
end
Then inside your controller, setup a filter to fetch the model using the title attribute instead of the ID attribute which is used for the find method.
before_filter :setup_record
def setup_record
#record ||= Record.find_by_title(params[:id])
end
You will have to ensure that your title stays unique and if you change it then you will either have to discard all other previous URLS or keep a history of older names.
I am using nested routes in my application (rails 3.2) as follows:
resources :networks do
resources :groups
end
The route for groups show page is as follows
network_group GET /networks/:network_id/groups/:id(.:format)
How can I change the parameters to :network_name and :group_name respectively? Also, I would like to rename the route to group_path (instead of network_group_path ). I would like these changes reflected for all the routes without having to use 'match' for the individual routes.
Is it possible to have something like group_path(#network, #group) return '/networks/global/groups/all', where 'global' and 'all' are both 'name' attribute for the respective models. (by default I get the id's in the url)
We can do that by adding a to_param method in our model
http://railscasts.com/episodes/63-model-name-in-url
In your network and group model, add a #to_param method that returns what you want in the URL (network_name, group_name).
Or else you can use friendly_id gem which gives pretty urls.
You can use friendly_id gem. https://github.com/norman/friendly_id
Is there a simple way of making rails routes to generate urls with permalink rather than id
what i mean is ..
resources :posts #=> generates urls like posts/12, posts/45/edit, ...
which can be used in controller as find(params[:id])
now with
def to_param
self.permalink
end
urls become /posts/what-is-rails, /posts/what-is-rails/edit,
now to find the record with permalink we still have to do
*find_by_permalink(params[:id])*
Now the question is, is there a easier way to generate urls with permalink in them
Use FriendlyId gem as seen at #314 Pretty URLs with FriendlyId Railscast.