Is there any way to simplify nested, namespaced resources? - ruby-on-rails

Is there any less redundant way to do this?
resources :tournaments do
resources :commitments, controller: "tournaments/commitments"
resources :constraints, controller: "tournaments/constraints"
resources :entries, controller: "tournaments/entries"
resources :buildings, controller: "tournaments/buildings" do
resources :rooms, controller: "tournaments/buildings/rooms"
end
end

This is the convention for nested resources. Here all of the controllers are still in the app/controllers directory.
resources :tournaments do
resources :commitments
resources :constraints
resources :entries
resources :buildings do
resources :rooms
end
end
You generally only use directories for your controllers when you need namespacing, like:
namespace :admin do
resources :users
root :to=>"dashboards#admin"
end
#/admin/users

Related

Rails 4 nested routes

routes.rb
Rails.application.routes.draw do
root to: 'visitors#index'
resources :states do
resources :cities do
get 'listings'
end
end
end
I am looking to have my GET URL set up like:
../state.id/city.id/listings.id
I am using friendly_id so the urls will read like:
../OR/Portland/2011-ford-truck
Listing is it's own model (resource) too in this case. You will also need a resources for listing. If it only has a show action, you can limit it like this:
resources :states do
resources :cities do
resources :listings, only: [:show]
end
end

How would I add /api to these routes

So I have bunch of routes that I can access through like localhost:3000/posts localhost:3000/users
config/routes.rb looks like this
resources :posts do
resources :comments, shallow: true do
delete :destroy_all, on: :collection
end
resources :images, shallow: true
end
resources :comments, only: [:new]
resources :users
root 'welcome#index'
How can I modify it so I also have normal access and also API access to them such as
http://localhost:3000/api/posts
http://localhost:3000/api/users/new and such
If you're building an API, you should consider versioning, thus separating your JSON API from your HTML interface; this means pulling your JSON API out into separate controllers that exist in a versioned API namespace.
namespace :api do
namespace :v1 do
resources :posts do
resource :comments, shallow: true do
delete :destroy_all, on: collection
end
end
resources :comments
resources :users
end
end
resources :posts do
resource :comments, shallow: true do
delete :destroy_all, on: collection
end
end
resources :comments
resources :users
These controllers would exist in app/controllers/api/v1.
Your route would now look like:
/api/v1/posts
Versioning your APIs is considered good practice because you want your API to remain consistent.
There's a great RailsCast on API versioning:
http://railscasts.com/episodes/350-rest-api-versioning?view=asciicast

Set the scope based on parent resource while using concerns

I am curious, is there any way to set the scope for nested resources based on parent resource while using concerns in Rails?
concern :commentable do
scope module: ??? do # either :posts or :messages
resources :comments
end
end
resources :messages, concerns: :commentable
resources :posts, concerns: :commentable
I want my routes to be like these:
Path Controller
/messages/:message_id/comments/:id messages/comments#show
/posts/:post_id/comments/:id posts/comments#show
but I also want to use concerns in order to reduce duplication.
Thanks!
Turns out method concerns can take a hash of options.
concern :commentable do |options|
scope module: options[:module] do
resources :comments
end
end
resources :messages do
concerns :commentable, module: :messages
end
resources :posts do
concerns :commentable, module: :posts
end
I started with your solution using an options hash but it turns out I really need this pattern a lot so I worked out another solution for that specific case :
concern :archivable do
scope module: parent_resource.plural do
resources :archiving, only: [:create, :destroy]
end
end
...
resources :messages , concerns: [ :archivable ]
resources :users , concerns: [ :archivable ]
You can use Rails Polymorphism to fit this situation where a comment can belong_to any other model as well...post,video,user etc
Wonderful Railscasts.....which is worth watching.

Nested routes and url helper in Rails 4

I have nested routes which goes something like this:
resources :venues do
#Halls
get "hall/:id/exhibition" => "halls#exhibition", as: :exhibition
get "hall/:id/visit" => "halls#visit", as: :hall_visit
get "venue_structure", :to => "venues#venue_structure"
resources :asset_types, :booths_tags, :tags, :uploaded_files, :events, :chats
resources :halls do
resources :webcasts
resources :booths do
resources :chats
end
end
end
Problem with this approach is that I have to put in three paramters in url helpers for nested ones like below:
venue_hall_booth_path(#booth.hall.venue, #booth.hall, #booth)
Is there a better approach to doing this other than me having to put in three different resources as parameters each time when I use this helper?
You can use shallow routes:
resources :halls, shallow: true do
resources :webcasts
resources :booths do
resources :chats
end
end
This allows you access member urls without having to use the parent. Unless it's a new or create actions.
Or you can define them separately.
resources :booths do
resources :chats
end
resources :halls do
resources :webcasts
resources :booths
end

Rails 3 create a route to nested independent page

I have 3 levels of nesting.
routes.rb looks like this
resources :clients do
resources :departments do
resources :tasks
end
end
I would like to create a custom path that looks like this
/clients/:client_id/departments/:department_id/tasks/data
I have tried adding the following
resources :clients do
resources :departments do
resources :tasks
member do
get "data"
end
end
end
This creates the route
/clients/:client_id/departments/:department_id/tasks/:task_id/data
How would I remove the :task_id part the path?
A member route acts on a member, that's why it requires an id. A collection acts on a collection and so doesn't require an id.
resources :clients do
resources :departments do
resources :tasks do
collection do
get "data"
end
end
end
end
You should use
resources :clients do
resources :departments do
resources :tasks
get "data", :on => :collection
end
end

Resources