Ruby on Rails
HowToWrapRailsAroundAnExistingApplication (Version #21)

Suppose you have an existing web application that you want to treat as “part” of your rails application. There are any number of reasons you may want to do this:

  • The legacy application may be hosted on another machine and you either want to hide the fact from the users or must hide this fact from the users (e.g., the legacy application runs on a machine behind a firewall, and will respond to requests from the web server but not from the internet at large).
  • The legacy application may use UglyURLs (and you’d rather the user see only PrettyURLs)
  • The legacy application may have security holes (and you want to filter requests/responses)
  • The legacy application may be on its way out (and you want to “grow” the rails replacement around it).

Of course, many—even all—of these reasons may pertain at once!

There are two main ways to do this. You can route a whole slew of legacy URLs to a single method of a single controller, which will then deal with them as needed (but still expose the structure of the legacy application’s URLs to the user). Or you can design custom controllers to present the structure you would like. A mix is possible, and the mix can change over time.

For the project that inspired this Howto, we started by running everything through a single controller which just sanity checked the requests before passing them through to the legacy application (see HowToRenderProxiedPages).

After this was in place we gradually added new controllers that presented the application the way we wanted, and used Filters? to retrofit the PrettyURLs into the rendered pages.

As the final step we are rewriting the legacy application piecemeal in Rails.

A single controller (users see legacy URLs)

If you want all requests to pass through a single controller (either because that is all you’ll need or as an initial step) you will need to create the controller:

ruby script/generate controller Default

Then all you need to know is HowToRouteGenericURLsToAController.

Add a method to the new controller that will pass requests through to the legacy application (see HowToRenderProxiedPages).

app/controllers/default_controller.rb<pre> class DefaultController < ApplicationController def default render_text Net::HTTP.get_response( "realserver.internal.net", @request.env["REQUEST_URI"] ).body end end </pre>

Multiple controllers (users see new URLs)

Consider a simple case first. Suppose that you want to surface what people would see if they went to url://realserver.internal.net/ugly/URL/57-19.php?feature=1&option=a
(assuming they could remember it, and had access to internal.net)
as url://www.myserver.org/legacy_app/feature1/function_a.

To do this you would create a “dummy” controler for Feature1, and add edit app/controllers/feature1_controller.rb to define function_a:


class Feature1Controller < ApplicationController
    def function_a
        render_text Net::HTTP.get_response(
            "realserver.internal.net",
            "/ugly/URL/57-19.php?feature=1&option=a"
            ).body
        end
    end

Of course, you don’t have to return the body unaltered—you have it as a ruby string and can edit it to your hearts content before giving it to render_text.

——

See also: Integrate Rails with a CMS

category: Howto

——
Is a view necessary? I seem to be having troubles without one. If so, it should be explained here too. – PhilipR

Suppose you have an existing web application that you want to treat as “part” of your rails application. There are any number of reasons you may want to do this:

  • The legacy application may be hosted on another machine and you either want to hide the fact from the users or must hide this fact from the users (e.g., the legacy application runs on a machine behind a firewall, and will respond to requests from the web server but not from the internet at large).
  • The legacy application may use UglyURLs (and you’d rather the user see only PrettyURLs)
  • The legacy application may have security holes (and you want to filter requests/responses)
  • The legacy application may be on its way out (and you want to “grow” the rails replacement around it).

Of course, many—even all—of these reasons may pertain at once!

There are two main ways to do this. You can route a whole slew of legacy URLs to a single method of a single controller, which will then deal with them as needed (but still expose the structure of the legacy application’s URLs to the user). Or you can design custom controllers to present the structure you would like. A mix is possible, and the mix can change over time.

For the project that inspired this Howto, we started by running everything through a single controller which just sanity checked the requests before passing them through to the legacy application (see HowToRenderProxiedPages).

After this was in place we gradually added new controllers that presented the application the way we wanted, and used Filters? to retrofit the PrettyURLs into the rendered pages.

As the final step we are rewriting the legacy application piecemeal in Rails.

A single controller (users see legacy URLs)

If you want all requests to pass through a single controller (either because that is all you’ll need or as an initial step) you will need to create the controller:

ruby script/generate controller Default

Then all you need to know is HowToRouteGenericURLsToAController.

Add a method to the new controller that will pass requests through to the legacy application (see HowToRenderProxiedPages).

app/controllers/default_controller.rb<pre> class DefaultController < ApplicationController def default render_text Net::HTTP.get_response( "realserver.internal.net", @request.env["REQUEST_URI"] ).body end end </pre>

Multiple controllers (users see new URLs)

Consider a simple case first. Suppose that you want to surface what people would see if they went to url://realserver.internal.net/ugly/URL/57-19.php?feature=1&option=a
(assuming they could remember it, and had access to internal.net)
as url://www.myserver.org/legacy_app/feature1/function_a.

To do this you would create a “dummy” controler for Feature1, and add edit app/controllers/feature1_controller.rb to define function_a:


class Feature1Controller < ApplicationController
    def function_a
        render_text Net::HTTP.get_response(
            "realserver.internal.net",
            "/ugly/URL/57-19.php?feature=1&option=a"
            ).body
        end
    end

Of course, you don’t have to return the body unaltered—you have it as a ruby string and can edit it to your hearts content before giving it to render_text.

——

See also: Integrate Rails with a CMS

category: Howto

——
Is a view necessary? I seem to be having troubles without one. If so, it should be explained here too. – PhilipR