I have many resources in routes.rb where many few resources are used and repeated.
Is there a way to avoid code duplication?
resources :pages do
resources :comments
##other routes
member { post :vote }
end
resources :videos do
resources :comments
##other routes
member { post :vote }
end
resources :images do
resources :comments
##other routes
member { post :vote }
end
You can organize your routes file so as to keep it from becoming a massive, unmanageable mess. But, it's not via Concerns ... it's actually more "basic" than that. Just break up the files and include them in the main routes file :).
I read a good post on this a while back: splitting routes,rb into smaller parts
Hope it helps.
I've used procs for this myself. Then I just call it in each namespace or resource block where I need it.
But concerns are likely a better and more readable solution.
Related
I have many resources where I want to have a delete view before destroying a record, for example:
resources :assignments do
get 'delete'
end
resources :occupations do
get 'delete'
end
resources :extra_shifts do
get 'delete'
end
resources :events do
get 'delete'
end
Is there a way I can DRY this up?
I'm aware of Routing Concerns, but that way I'd just shift the route line outside of the block and set it beside the resources line, which could save some lines but still have lots of duplication.
pretty sure
resources :assignments, :events,
:occupations, :extra_shifts do
get 'delete'
end
would work
In my application, a User can make a Post, and a User can make Correction (think of it as a comment) on another user's post. Each User can have many Posts, and each Post can have many Corrections.
On each show page for a Post, there is a form to create a new Correction. This uses the user_post_corrections path.
On the show page for each User, I would like to display each Correction they've submitted for any Post. This requires a user_corrections path.
In order to achieve this, I have the following in my routes.rb:
resources :users do
resources :posts do
resources :corrections
end
end
resources :users do
resources :corrections
end
This intuitively feels bad to me, as I've created two nested routes that are very similar to one another.
Is there a better way to do this? My code is working fine as it is but is there a best practice method for implementing this kind of model?
Routing concerns are an excellent but underused tool for DRYing out your routes:
concern :correctable do
resources :corrections
end
# just an example of multiple concerns
concern :commentable do
resources :comments
end
resources :users, concerns: :correctable
resources :posts, concerns: [:correctable, :commentable]
However you should take when creating nested routes so that you are not nesting needlessly.
Often you might want the collective actions [new, index, create] to be scoped by the parent:
GET|POST /posts/:post_id/corrections
GET /posts/:post_id/corrections/new
While you want the member actions to be unscoped since you can always access a record directly if it has a unique id.
GET /corrections/:id
GET /corrections/:id/edit
PATCH /corrections/:id
DELETE /corrections/:id
To do this you would declare the routes like so:
resources :corrections, only: [:show, :update, :edit]
concern :correctable do
resources :corrections, only: [:new, :index, :create]
end
resources :users, :posts, concerns: [:correctable]
The shallow: true option does something like this but does not work well when you declare the same resources several times as it adds unscoped routes for every call.
How might I be able to shorten these extremely lengthy routes in my rails application?
# routes.rb
resources :courses do
resources :sections do
resources :lessons do
resources :sub_lessons
end
end
end
I recommend to follow the rails oficial guides. It is considered a good practice to avoid nesting resources more than 1 level deep. That said, if you really need this level of nesting you can use the shallow option. this way at least your routes will be cleaner. As noted in the documentation cited above:
One way to avoid deep nesting (as recommended above) is to generate the collection actions scoped under the parent, so as to get a sense of the hierarchy, but to not nest the member actions. In other words, to only build routes with the minimal amount of information to uniquely identify the resource
You could try something like this:
resources :courses, shallow: true do
resources :sections, shallow: true do
resources :lessons, shallow: true do
resources :sub_lessons
end
end
end
Just play around with this a little and use rake routes to see how your routes are looking like.
However, what you should ask yourself is, for example do I need to have lessons routed under sections? May be its better to split them, something like:
resources :courses do
resources :sections
end
resources :lessons do
resources :sub_lessons
end
It all depends on the scope you need in what action, for example if at certain action you need to limit lessons based on courses but not in sections, then you will only need the course id passed as a parameter.
I am working on this project that has products and under products I have cars and trucks and each have comments and the ability to vote on both the car model and comments. The car models all work correctly but the trucks model does not have the correct routes. I am thinking it has something to do with having comments shallow, but honestly, I am not sure what I am doing wrong. Any guidance would be appreciated.
resources :products do
resources :cars do
member { post :vote }
resources :car_comments, shallow: true do
member { post :vote }
end
end
resources :trucks do
member { post :vote }
resources :truck_comments, shallow: true do
member { post :vote }
end
end
end
UPDATE
After looking over one of the controller files, I found the error and now the routes work as expected. However, I still feel that my routes look clunky, and since there will be more models, boats, tractors, etc, I dont think the way the routes are written now will hold up.
I believe it is because you are using resources :trucks, when you use the resouces it calls the CRUD methods. if you want certain routes you need to specify them, for example: resources :trucks, only: [:create, :destroy]
I know I can specify nested resources on routes.rb in Rails 3 this way:
resources :users do
resources :posts
end
However, I would like to add comments to posts. What should I write in my routes.rb file? Is this the correct way? Can I keep nesting them?
resources :users do
resources :posts do
resources :comments
end
end
You can keep nesting the way you have shown and things will work fine. There are quite a few sources that will tell you not to go crazy nesting routes though. Take a look at Rails Best Practices for example (I think the article was created for rails 2 but the principals still apply). Jamis Buck also blogged about this a while ago.
Yes, you can keep nesting and nesting and nesting and so forth.
Yes. What you wrote is the correct way.
I've been interested in this same problem and I think you're suppose to do:
resources :users do
resources :posts
end
resources :posts do
resources :comments
end
Check out the API on Resources.