命名空间API和资源路由

5

我有一个版本化的命名空间中的API,

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

但现在当我让我的控制器执行 redirect_to @post 时,我会得到一个关于 Post 的路由错误,因为没有为其定义路由。

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>

我知道我可以更新控制器以重定向到命名路由,这并不是世界末日:

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

有没有办法让redirect_to @post自动检测应该在正确的api版本中使用(因此Rails会使用api_v1_post_url)?我知道我可以重写redirect_to,但我真正想要的是一个命名空间感知的url_for,也许Rails提供了一些钩子来实现这一点?

1个回答

12

在 Ruby on Rails 路由器中有三个选项。

1. 命名空间(你现在正在使用的东西)

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

控制器: app/controllers/api/v1/PostsController.rb

示例URL路径: example.com/api/v1/posts


2. 范围(仅设置URL路径)

scope 'api/v1' do
 resources :posts
end

控制器:app/controllers/PostsController.rb

示例URL路径:example.com/api/v1/posts


3. 模块(仅设置控制器)

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

控制器:app/controllers/api/v1/PostsController.rb

示例URL路径:example.com/posts


正如您从上面所注意到的那样,所有三个都与您想要的方式类似,但不是您想要的方式。

我能想到的唯一解决方法,是使用命名路由来缩短笨拙的长路径助手api_v1_post_url

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

所以,与其使用 api_v1_post_url

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

你可以使用稍微简短一些的a_1_post_url

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

最后,很抱歉,我不知道如何在Rails路由中智能自动检测名称空间。

希望这有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接