Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Namespaced API's and resource routes

I have my API in a versioned namespace,

namespace :api do
  namespace :v1 do
    resources :posts
  end
end

but now when I have my controller do a redirect_to @post I get a route error for Post because no routes are defined for it.

def create
  @post = Post.new(params[:post])
  if @post.save
    redirect_to @post
  else
    # ...
  end
end

undefined method `post_url' for #<Api::V1::PostsController:0x007fb9c5fc8858>

I know I can update my controller to redirect to the named route and its not the end of the world:

def create
  @post = Post.new(params[:post])
  if @post.save
    redirect_to api_v1_post_url(@post)
    # or redirect_to [:api, :v1, @post]
  else
    # ...
  end
end

Is there a way to make redirect_to @post automatically detect that it should be in the right api version (so rails works out to use api_v1_post_url)? I know I could overwrite redirect_to but really I want a namespace aware url_for, maybe rails provides some hooks for this?

like image 580
Soup Avatar asked May 26 '13 07:05

Soup


People also ask

What are rails resource routes?

Any object that you want users to be able to access via URI and perform CRUD (or some subset thereof) operations on can be thought of as a resource. In the Rails sense, it is generally a database table which is represented by a model, and acted on through a controller.

What is resources in routes RB?

Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. A single call to resources can declare all of the necessary routes for your index , show , new , edit , create , update , and destroy actions.

What are Ruby routes?

The routing module provides URL rewriting in native Ruby. It's a way to redirect incoming requests to controllers and actions. It replaces the mod_rewrite rules.


1 Answers

There are three options in Ruby on Rails router

1. Namespaces(something which are you using right now)

namespace :api do
  namespace :v1 do
    resources :posts
  end
end

Controller: app/controllers/api/v1/PostsController.rb

Example URL Path: example.com/api/v1/posts


2. Scope(only sets the url path)

scope 'api/v1' do
 resources :posts
end

Controller: app/controllers/PostsController.rb

Example URL Path: example.com/api/v1/posts


3. Module(only sets the controller)

 scope module: 'api/v1' do
   resources :posts
 end

Controller: app/controllers/api/v1/PostsController.rb

Example URL Path: example.com/posts


As you may notice from above, all of three do something similar to what you want but not the way you want it.

the only workaround I can think of against using awkwardly long path helpers api_v1_post_url is to use named routes to shorten it.

namespace :api, :as => "a" do
  namespace :v1, :as => "1" do
    resources :posts
  end
end

so instead of api_v1_post_url

def create
  @post = Post.new(params[:post])
  if @post.save
    redirect_to api_v1_post_url(@post)
  end
end

you can use little shorter a_1_post_url

def create
  @post = Post.new(params[:post])
  if @post.save
    redirect_to a_1_post_url(@post)
  end
end

Lastly, I am afraid, I am not aware of any way to intelligently auto-detect namespacing in rails routing.

Hope it helps

like image 176
CuriousMind Avatar answered Oct 27 '22 01:10

CuriousMind