Rails routes, using something other than model_id in resources route - ruby-on-rails

I have some nested resources. Here's an example:
resources :contests do
resources :scoring_periods do
resources :entries
end
end
I'd ultimately like to have a URL that looks like the following:
/contests/1/scoring_periods/10/entries/new
The catch here is that the /10/ in scoring_periods is not the ScoringPeriod#id. It is instead another attribute named period_count in this case. I'd like to be able to reference the period_count in the URl instead of the ID as my system might have millions of IDs later and it's just not intuitive to list it there. The actual period_count number, makes a lot more sense to the users entering this contest.
Is there a way to munge the resources entry in routes.rb in order to allow me to reference scoring_periods by an attribute other than :scoring_period_id ?

Something like this should work:
resources :contests do
scope path: '/scoring_periods/:period_count/' do
resources :entries
end
end

Related

Handling Rails routes/models with belongs_to relationship

So this may be more of a convention question, but im writing a todo app to learn how to use rails as an API (Im somewhat intermediate with using rails normally) but this time im using it with React for the front end.
Im making a simple todo app, two models in particular being "Lists" and "ListItems". Lists has_many ListItems of course, and a ListItem belongs_to a List.
So naturally I have the routes set up like so:
resources :lists do
resources :list_items
end
Giving me routes similar to: /api/v1/lists/:list_id/list_items etc.., However I saw some people doing a similar app set it up like:
namespace :v1 do
resources :list_items
resources :lists
end
Which confuses me because how would you handle passing the actual "List" params to the route, when the route itself would not have a List_id param?
Or would this more be used for a join table somehow..but you would still have to populate the List_id regardless when creating a list_item for a specific list correct?
Is there a preferred way of doing this as far as routing goes? (And I suppose creating tables?) Since a has_many_through seems not really necessary in this case?
Unless there is more to the story, you are doing it the more conventional way. I suggest your can safely disregard that not-nested approach. The only enhancement I suggest is using shallow: true, like:
namespace :api do
namespace :v1 do
resources :lists do
resources :list_items, shallow: true
end
end
end
You can read more about shallow nesting in the guide.

how to change multiple nested routes in rails

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

Nested routes without inadvertent top level routes

I have 3 resources that are structured in a hierarchy as follows:
house 1-* residents 1-* books
We know that its not great to have deeply nested routes, so we endeavour to have routes nested at most 1 resource deep. Defined something like:
resources :houses do
resources :residents
end
resources :residents do
resources :books
end
The problem is that we end up defining :residents as a resource that can be accessed without any nesting - as part of the definition of :books. Is there way to define :books as being nested in :residents, without inadvertently registering :residents as a top level route?
This can be accomplished by using scopes, in your case:
scope 'residents/:resident_id' do
resources :books
end
However, as I mentioned in the comment, this practice can end up confusing users who expect URLs to behave in a certain way (deleting the last bit takes them up a level).

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

RESTful nested controller in has_one relationship

Say I have a User that has_one ContactInfo.
An unrestful way to edit the contact_info would be to do this all through a single controller with a route of:
myapp.com/users/15/edit_contact_info
A more restful way would be to use two controllers, and route it like this:
myapp.com/users/15/contact_infos/23/edit
However, I don't like this, as the route includes the contact_info_id, which isn't really necessary for identifying the correct contact_info to update. Additionally, the contact_info_id is a confusing number for a user to see. (They may know their own user id, but the contact_info_id will seem like an arbitrary number).
Is there any way to RESTfully route like below:
myapp.com/users/15/contact_infos/edit
or something similar? Is this a bad idea?
resources :users do
get "contact_info/edit" => 'users#edit_contact_info'
end
I'd used a plural route, instead of a singular route. With the singular route, I get myapp.com/users/15/contact_info/edit.
Had:
resources :users do
resources :contact_infos
end
Changed to
resources :users do
resource :contact_info
end

Resources