Rails Contained: A Container for Web Application Development and Deployment

February 21, 2012 Mike Barinek

You might call this post Part 2 in a component based architecture series. The first post describes a solution for better organizing loosely-coupled, highly-cohesive components within a singe Rails application.

This post describes a component based solution that aims to support vastly different user experiences and client side strategies across multiple web applications that share a common domain while allowing developers to work independently within individual web applications or components.

Here’s the scenario…

You’re tasked with building a fairly large web application, several user roles each packed with handfuls of high-level activities. The larger application could clearly be broken apart into smaller web applications. It’s a clear win to break things down. The smaller applications would have unique responsibilities and developers could work within the context of one application without worrying about introducing breaking changes across applications. However, the smaller applications, although independent, share a common domain or database.

You start thinking about how you’d expose subsets of the domain as RESTful services and maybe introduce a single sign-on approach, although you’re concerned about managing, versioning, and deploying multiple web applications and services, not to mention how this might impact the early development rhythm. There’s no clear path to success, so you write the classic uber app.

The tide could be changing in your direction. Here’s a solution that’s shown early success for developing and deploying large Rails applications: move loosely-coupled, highly-cohesive web applications and components to a components directory within a container Rails project.

Until recently such an approach might be difficult to imagine. Although, with the addition of mountable engines in the latest versions of Rails, the approach is now possible. Here’s an example that describes the project structure…

container_rails_app/
  app
  config
  components/
    component_1/
      lib/component_1.rb
      lib/component_1
      test/lib
      test/test_helper.rb
      Gemfile
      component_1.gemspec
      Rakefile
    component_2/
    component_3/
    web_app_1/
      app
      config
      test/lib
      test/test_helper.rb
      Gemfile
      Rakefile
    web_app_2/
      app
      config
      ...
  ...

The container application simply mounts dependent web applications as Engines, exposing each with their own context or url. Engines in turn reference in any Engines or Gems they depend on.

However, there is one twist, we keep everything in a single Git repository.

Engines are organized as prescribed within their corresponding directories, although they’re not built nor do they have their own Git repository. They’re referenced directly from the containers Gemfile.

As database migrations trigger sweeping changes, the refactorings become simpler and you don’t need to worry about deploying updates to multiple applications/services as all your code is in one place, versioned together.

As important, each Engine or Gem has it’s own Gemfile, test_helper, test suite, and continuous integration environment. As mentioned in the first post, the unique Gemfile and test helper allows you to remove unnecessary dependencies while the individual test suite and continuous integration environment helps to avoid circular dependencies.

About the Author

Biography

Previous
Tracker Ecosystem: Meta collaboration tools
Tracker Ecosystem: Meta collaboration tools

Is it a sign of the times that the cloud-based tools that allow us to work together better now need a tool ...

Next
Unbuilt Rails Dependencies: How to design for loosely-coupled, highly-cohesive components within a Rails application
Unbuilt Rails Dependencies: How to design for loosely-coupled, highly-cohesive components within a Rails application

I'm sure a few of you have encountered this scenario... You're a year in and your Rails application is gro...