根据QueryString设置Rails路由

Har*_*arv 15 routes ruby-on-rails query-string

我已经看到了类似的问题,但并不是我正在寻找的......忘记这样做的智慧,是否有可能做到这一点?...

/object/update/123?o=section    # ==> route to SectionController#update
/object/update/456?o=question   # ==> route to QuestionController#update
Run Code Online (Sandbox Code Playgroud)

......如果是的话,怎么办呢?

小智 16

假设您正在使用Rails 3+,您可以使用"高级约束"(在http://guides.rubyonrails.org/routing.html#advanced-constraints上阅读更多相关信息).

以下是如何解决您的示例:

module SectionConstraint
  extend self

  def matches?(request)
    request.query_parameters["o"] == "section"
  end
end

module QuestionConstraint
  extend self

  def matches?(request)
    request.query_parameters["o"] == "question"
  end
end

Rails.application.routes.draw do
  match "/object/update/:id" => "section#update", :constraints => SectionConstraint
  match "/object/update/:id" => "question#update", :constraints => QuestionConstraint
end
Run Code Online (Sandbox Code Playgroud)


Chr*_*bek 11

@ moonmaster9000的答案更简洁routes.rb:

match "/object/update/:id" => "section#update", 
  :constraints => lambda { |request| request.params[:o] == "section" }
match "/object/update/:id" => "question#update", 
  :constraints => lambda { |request| request.params[:o] == "question" }
Run Code Online (Sandbox Code Playgroud)


zet*_*tic 3

抛开这样做是否明智的问题,“这可能吗”的答案是“是”:

class QueryControllerApp
  def self.call(env)
    controller_name = env['QUERY_STRING'].split('=').last
    controller = (controller_name.titleize.pluralize + "Controller").constantize
    controller.action(:update).call(env)
  rescue NameError
    raise "#{controller_name} is an invalid parameter"
  end
end

MyRailsApp::Application.routes.draw do
  put 'posts/update/:id' =>  QueryControllerApp
end
Run Code Online (Sandbox Code Playgroud)

基本上,路由映射器可以接受任何机架应用程序作为端点。我们的简单应用程序解析查询字符串,构建控制器名称并调用 ActionController 方法action(它本身就是一个 Rack 应用程序)。未显示:如何处理除'o=<controller_name>'

  • 我会使用:`Rack::Utils.parse_nested_query(env["QUERY_STRING"])`,而不是`.split`来获取查询字符串。 (2认同)