17

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
  • I only see redirect_ti options in controller in this case Commented Feb 3, 2011 at 18:09

3 Answers 3

17

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
Sign up to request clarification or add additional context in comments.

1 Comment

Where, in which folder should this module be written? I am a newbie to RoR.
12

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

Comments

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>'

2 Comments

As best I can tell this is the only way to "redirect" without having the side effect of having your query string stripped off. Thank you @zetetic
Instead of .split to get at the query sting, I would use: Rack::Utils.parse_nested_query(env["QUERY_STRING"])

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.