Setting up Rails routes based on QueryString

2019-01-13 22:15发布

问题:

I've seen similar questions on this, but not quite what I'm looking for... Forgetting for a moment the wisdom of doing this, is it possible to do this?...

/object/update/123?o=section    # ==> route to SectionController#update
/object/update/456?o=question   # ==> route to QuestionController#update

...and if so, how would that be done?

回答1:

Assuming you're using Rails 3+, you can use an "Advanced Constraint" (read more about them at http://guides.rubyonrails.org/routing.html#advanced-constraints).

Here's how to solve your example:

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


回答2:

More concise than @moonmaster9000's answer for routes.rb only:

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" }


回答3:

Setting aside the question of whether it is wise to do so, the answer to "is this possible" is 'yes':

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

Basically the route mapper can accept any Rack application as an endpoint. Our simple app parses the query string, builds the controller name and calls the ActionController method action (which is itself a Rack application). Not shown: how to deal with query strings with any format other than 'o=<controller_name>'