Rails:根据请求格式路由到不同的控制器

时间:2012-12-06 23:01:21

标签: ruby-on-rails url-routing

我正在编写一个应用程序,我希望所有HTML请求都由同一个控制器操作处理。我有一些其他JSON特定的路由。这是我的路线的样子:

Blog::Application.routes.draw do
  constraints format: :json do
    resources :posts
  end

  match "(*path)" => "web#index"
end

问题是constraints被解释为“此路由仅适用于指定的格式”,而不是“如果请求不是指定的格式,则跳过此路由并尝试下一个路由。”

换句话说,在浏览器中导航到 / posts 会给我一个 406 Not Acceptable ,因为URL被限制为JSON格式。相反,如果请求是针对HTML,我希望它落到 web #index ,如果请求是针对JSON,则命中资源路由。如何实现这一目标?

(使用Rails 3.2.9。)

2 个答案:

答案 0 :(得分:2)

我已经考虑过了,并得出了一些结论。

  • 您可能不希望所有路由都返回单页应用HTML,因为有些路径您理想地希望从中返回HTTP 404状态代码。
  • 您的HTTP路由将与您的JSON路由不同
  • 您肯定应该将不同的格式路由到不同的控制器
  • 在Rails路由器中定义所有HTML路由可能是有利的,这样您就可以使用它来生成javascript路由器。至少有一个宝石可以做到这一点
  • Rails没有这个功能,这个gem https://github.com/svenfuchs/routing-filter看起来不是正确的工具。这是我的尝试:Rails routing-filter route all html requests to one action
  • 必须在模块Api下命名您的JSON API以避免路由冲突并不是坏事。
  • 您的单页应用中没有Google可以看到的内容,或者您​​会因重复内容而被禁止使用。

我采用了一种稍微不同的方法,但并没有真正回答这个问题,但我认为它有一些优点:

这是我的config / routes.rb

FooApp::Application.routes.draw do

  # Route all resources to your frontend controller. If you put this
  # in a namespace, it will expect to find another frontend controller
  # defined in that namespace, particularly useful if, for instance,
  # that namespace is called Admin and you want a separate single page
  # app for an admin interface. Also, you set a convention on the names
  # of your HTML controllers. Use Rails's action_missing method to
  # delegate all possible actions on your frontend controllers.

  def html_resources(name, options, &block)
    resources(name, options.merge(:controller => "frontend"), &block)
  end

  # JSON API
  namespace :api do
    resources :things, :except => [:edit, :new]
  end

  # HTML
  html_resources :things, :only => [:edit, :new, :index, :show] do
    get :other_action
  end
end


class FrontendController < ApplicationController
  def action_missing(*args, &block)
    render :index
  end
end

答案 1 :(得分:0)

首先,我认为同一行动的不同控制器不是“Rails方式”。 您可以使用中间件中的低级自定义请求处理程序来解决您的问题。