Nested resources linking - ruby-on-rails

I have a category with a subcategory and the subcategory has posts. I'd like to link it as following:
/categoryname/subcategoryname/post_id/postname
I've tried doing so by putting this in my routes:
resources :categories do
resources :subcategories do
resources :posts
end
end
But any time I'd like to create a link for my subcategories (/categoryname/subcategory/) via link_to(subcat.name, category_subcategory_path)
I get:
No route matches {:controller=>"subcategories", :action=>"show"} missing required keys: [:category_id, :id]
How would I approach this to get the desired link setup?
Thanks in advance,

Slugs
Firstly, if you're looking to use slugged routes, you'll be best looking at gems including friendly_id or slugalicious -- basically allows you to manage "slugs" for your models -- saving titles or other attributes in URL encoded format
Paths
Secondly, I think you'll resolve your issue by providing values, rather than using the path helper. I would do this:
link_to subcat.name, category_subcategory_path(category.id , subcat.id)
When you use a path helper, it only cares about which params you send. The path helper you're using requires you to set the category_id and subcategory_id params -- which you should pass to the path helper as demonstrated above
This will create the path using id's - if you'd like to use slugs, you'll need to use one of the aforementioned gems (friendly_id is recommended) to set up the slugs in your app

Related

How to differentiate between :ids in routes/URL that belong to different models using FriendlyID?

I'm wondering how to generate a url that includes friendly ids for two different models. For example, if you have a post titled 'Rails Tutorial' and belonging to a particular User named 'Michael', and they each use a slug in place of their ID, how would you generate a url that looks like site.com/michael/rails-tutorial.
If you set your route to be:
get ':id/:id' => 'posts#show', as: 'show_post'
the URL will either be michael/michael or rails-tutorial/rails-tutorial, yet the way Friendly_id works from what I know is that your slug is represented by :id, so you can't configure it to work with get ':user_id/:post_id'.
I'm sure I just don't understand FriendlyID enough. Any help is appreciated.
In order to get the url you’re looking for, you’ll need to nest your routes:
resources :users do
resources :posts
end
This will give you the route:
localhost:3000/users/slug/post/slug
You’ll also have to extend FriendlyId in each model, add the slug to each model in a migration and use .friendly in the controller action(s).

Change Rails namespaced route to personalized params route

TL;DR: I want to have username621/posts/title-of-post instead of member/posts/1
The changing of post id to post title was easy enough since I used the freindly_id gem to generate the slugs.
However, I am having difficulty routing to a personalized params route instead of the current namespaced route. Here is the current routing:
namespace :member do
resources :posts
end
I want to replace the member namespace to user's username. So if their username is user123, the route should be user123/posts/title-of-post.
I think that this is not very standard Rails routing and tried looking for similar questions with no results.
for more complicated routes.rb, add a path option
namespace :member, path: ":user_id" do
resources :posts
end
should get what you want, e.g. http://localhost:3000/621/posts/1
then we just have to add friendly_id to User and Post to have it become something like http://localhost:3000/username621/posts/title-of-post
however, you'll need to pore through the codebase for things like member_post_path(post) and change to member_post_path(post.user, post)
Try removing the namespace and adding path option:
resources :posts, path: '/:username/posts/'
Then if you access /username621/posts/title-of-post in your controller you'll see params[:username] = 'username621'
If you have other paths of the form /something/posts add them above this route, otherwise they will be caught by :username.

Extract params fro url in rails

From the url below how can I extract the value 1?
`http://localhost:3000/category/products/1`
I tried params[:id] and params[:products][:id] but got nothing.
Did you make suitable change in your routes.rb file? You need to include something like
GET /category/products/:id , ...
to make it work with params[:id].
Routes
The direct answer to your question is to fix your routes.rb file
As per the Rails RESTful routing structure, you should be able to use a named scope to achieve this:
#config/routes.rb
scope 'category' do
resources :products
end
#/category/products/1 -> params[:id]
Nested
What I recommended above should fix your problem directly
However, I think you're trying to achieve nested resources. If this is the case, you should use something like this:
#config/routes.rb
resources :categories do
resources :products
end
This will allow you to do:
#categories/:id/products/:product_id

Get same url structure as on Stack Overflow

A question on SO has this url structure:
http://stackoverflow.com/questions/18474799/changing-the-input-value-in-html5-datalist
If we assume that the number section is the ID, the first two sections (after the domain extension) are obtained by simply using the following in routes.rb
resources :questions
The question is already identified by it's ID, so how do we add the (optional) decorating slug in the simplest of manners? Do we need to use a new link helper (and including additional params) or can the 3-section url be resolved elsewhere?
Update:
To focus this question more on the route-handling, let's presume there is already a slug saved on the object (upon creation) as an attribute, e.g. #question.slug
It would really be an advantage if a rule in routes.rb or/and in the controller could enable and handle the optional slug, instead of having to write long link helpers in all views.
resources :questions do
member: title
end
for slug use friendly_id and yes don't forget to have a look at Rails Routing
You might be able to use the to_param method to create a "friendly id".
Something like this:
class Question < ActiveRecord::Base
def to_param
[id, name.parameterize].join("/")
end
end
More info in this gist
If you just want to handle the GET requests in that manner, it's easy to do:
get '/questions/:id/:title' => 'questions#show', as: :question_with_title
resources :questions
This way you can handle incoming URLs with or without the title (just as StackOverflow can -- try it!). You can create urls dynamically with something like:
question_with_title_path(#question.id, #question.title.to_s.downcase.gsub(/ /, '-')
# probably will want to use a method for processing titles into url-friendly format
More at http://guides.rubyonrails.org/routing.html#static-segments

customization for nested routes in rails 3

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

Resources