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 提供了一些钩子?

4

1 回答 1

11

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.Scope(只设置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 路由中的命名空间。

希望能帮助到你

于 2013-05-26T08:26:08.307 回答