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
Related
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
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.
I've been deep nesting my resources and now discover that this should be avoided. Shallow nesting seems to be the answer but I'm struggling on how to properly correct the second level deep nesting. Let me show you my routes file as I think that will make it clearer(I'm using Rails 4):
OLD:
resources :members do
resources :emails
resources :events do
resources :items
end
end
NEW so far:
resources :members, shallow: true do
resources :emails
resources :events
end
My issue is I don't understand where to put the :items now? I thought it should be nested under the :events for the :index, :new, and :create actions?
What am I missing, I'm sure its something silly that I'm just not getting yet, please excuse my ignorance and I think you in advance for any help!!!
Mark
All you need to do is, update the routes as below:
resources :members, shallow: true do
resources :emails
resources :events, shallow: true do
resources :items
end
end
This will create shallow routes for items. Only for :index, :new, and :create actions you would get nested routes prefixed with /events/:event_id.
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
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