If you've followed the IT blogosphere even slightly over the past months, you've unavoidably heard of a "Web 2.0" web development framework named Ruby on Rails. Ruby on Rails (or, just Rails) is indeed an exciting development and definitely has earned a lot of the attention it's getting. Following the recent 1.0 release of Rails, this article is my feeble attempt to help you see through the hype and see Rails for what it's worth. Specifically, I'd like to pose the question, where does Ruby on Rails fit in the enterprise development landscape?
Before we get started, I feel obliged to state a little disclaimer about myself. I love Rails. I love it. But, while I enjoy writing applications with Rails, I've tried hard to keep an objective perspective on things. It is this perspective I'm hoping to pass on to you, dear reader, for critical evaluation. I'm not expecting anyone to take my perspective and adopt it as-is. I'm expecting you to think for yourself, perhaps focusing your own thoughts through this article.
Let's start by talking a bit about what exactly is Ruby on Rails is.
Ruby on Rails is first and foremost a web framework and the brainchild of David Heinemeier Hansson. It's written with Ruby, a dynamically typed, interpreted programming language originating from the hands of Yukihiro Matsumoto. Rails is composed of a number of little, well-integrated frameworks, each focused on delivering some small slice of the full framework's capability, ranging from object-relational mapping to MVC to web services support.
Rails is designed to keep simple things simple. While the numerous mentions by Rails aficionados about 10-fold productivity improvements might seem ridiculous to the more critical of us, I do believe there's significant potential built right into the framework itself. I've personally found Rails a pleasure to develop with and my jaws have dropped at least a couple of times as I've ventured to trying out new aspects of the framework. Perhaps the biggest question regarding Rails in my mind right now is, how far can Rails stretch without losing its advantage?
What makes a technology suitable for enterprise development is difficult to define exactly. What we can do, however, is discuss aspects that we recognize as being at least somewhat relevant for the discussion. Such aspects include the kind of support available through frameworks, the power handed to us in the form of a programming language, the development environment in general, and, of course, the community at large along with the availability of third party libraries and developer skills on the market. Furthermore, issues like security and support for operations and maintenance cannot be ignored either.
The rest of this article largely follows the general direction of these aspects, hopefully creating a good understanding of how Rails fits into the modern enterprise.
Rails itself is a web development framework. But what is a framework, to start with? A framework, according to a definition I've morphed from a variety of sources over the years, is a set of architectural guidance and reusable infrastructure. In short, by adopting a framework we're getting a bunch of conventions or "how things should be done" along with a pile of actual code we can start building on top of. Rails is just that--a well-integrated set of architectural guidance and structure, and working code to build on.
Speaking of architectural guidance, the Java Blueprints developed by Sun Microsystems to aid J2EE developers with documented "best practices". These patterns have clearly had a huge positive (and also some negative) effect on how the development community has built their enterprise applications with J2EE. Similar guidelines can be observed growing within the community that's growing fast around the Spring Framework, a lightweight open source J2EE application framework. How about Rails? Is there a Rails Pattern Catalog out there?
Yes and no. On one hand, Rails doesn't have a documented set of patterns like the mainstream technology platforms like J2EE and .NET have. On the other hand, we could argue that a Rails developer doesn't really need one because of the delicate simplicity of the framework itself. On yet another hand, Rails itself could be considered to incorporate a set of patterns in the form of idioms--the "Rails way" of doing things. Furthermore, many of the design patterns familiar to enterprise developers from the J2EE pattern catalogs as well as from the Microsoft Patterns and Practices group are equally applicable to systems developed with Ruby on Rails as they are to systems developed with J2EE or .NET.
When discussing architectural guidance, one can also not bypass the enormous support a community can provide. For any technical problem a developer faces and for any this or that decision to make, one of the first sources for help a developer turns to is the community. That community might be a local community, the company guru in technology X, or a global online community, such as a forum like JavaRanch or an IRC channel like #rubyonrails.
One could claim that the body of knowledge represented by an active community is far more important than a documented body of knowledge maintained by a single entity. Why? Because the active community is learning all the time and represents the absolute best information available at any time while the documented body of knowledge is a static snapshot with which one cannot interact and discuss. Furthermore, and perhaps more importantly, the community consists of human beings with huge amounts of tacit knowledge that can be tapped into case by case, as opposed to a static set of documents which at best is a shallow dip into that deep well of knowledge.
While Java and .NET developers enjoy a vast array of printed literature on the respective technologies, a Ruby on Rails developer has less printed literature and fewer online resources to reference. The online community, however, largely represented by the #rubyonrails IRC channel, is thriving and is alive literally 24/7 and with a number of books written to help out with learning the basics of both the Ruby language and the Rails framework, there's certainly plenty of community support available.
One aspect of frameworks and architectural guidance is the kind of idioms they bring forth. A specifically interesting one is Rails' philosophy of convention over configuration. In essence, where many of the incumbent frameworks advocate externalizing configuration into external XML documents or inline comments, Rails advocates smart defaults and minimal configuration.
Obviously there is some amount of configuration needed for Rails as well. The big differentiator, along with smart defaults, is that the Rails developer can do the necessary configuration in simple formats such as Ruby itself and YAML--a kind of structured, text-based properties file format for describing object graphs. This often leads to expressive and easily maintainable configuration files, although it's certainly possible to create a tangle with just about any format if we're not cautious.
One of the things about Rails that has gotten a lot of positive karma is the way automated testing is built into the framework as core feature. In fact, I think it ought to be core functionality for any modern framework.
Rails supports automated testing in a couple of ways. First of all, Rails assumes you're writing automated tests. That is, by default, Rails generates a unit test skeleton for every model class you ask it to generate and a functional test skeleton for every controller class you ask it to generate. That's just a minor plus, though, since there aren't too many lines of code to write anyway in those skeleton test classes.
What gives me the biggest kicks about Rails' testing support is the depth of built-in assertions and utilities for writing functional tests: tests that exercise a controller, verify that the correct database insert occurred, assert that a validation error is displayed when it should, or that the controller redirected to the right template for rendering a response. The kind of tests that we'd need much more laborious setup if it wasn't for the nifty built-ins and the overall simplicity of Rails' components themselves.
In addition to the comprehensive library of assertions and shortcuts, Rails lets us manage the data for our functional tests using the concept of fixtures, data sets described in YAML that Rails automatically populates the database with for every test, if necessary, or just once in the beginning of our test run if we've decided to use transactional fixtures. Furthermore, Rails gives our test code easy access to our test fixtures as well just to make sure we're not tempted to duplicate data between the fixture and our test code.
Simply put, the testing support in Rails is quite brilliant and is definitely setting expectations higher for other frameworks as well.
The programming language itself is a valid concern to discuss when thinking about picking a new tool into your corporate toolbox. From my perspective, the main difference between the Ruby programming language and the mainstream enterprise technologies of the modern IT department is dynamic typing.
Dynamic typing means that for a given variable, we don't need to explicitly tell which type of an object it will reference. Static typing means that we're explicitly telling the compiler that the variable will only be used to refer to objects of a given type (or subtypes thereof). Dynamic typing also means that there's no compiler to tell us when we've screwed up, passing the wrong type of object to a method. Instead, we'll get a runtime exception upon execution of that specific piece of code.
A rather common way of thinking about the different is in terms of "quick and dirty" vs "slow but maintainable", referring to the rather common experience developers share, having been exposed to tedious thousand-line Perl scripts or similarly lengthy Java code from which one can still somehow derive the original author's intent. There's no denying that a mess written in a dynamically typed language is likely harder to figure out than a mess in a statically typed language. The question then becomes, whether we should focus on making it easier to deal with the symptoms or to focus on avoiding the problem in the first place. Furthermore, dynamically typed languages like Ruby often yield more flexibility and expressiveness to our disposal which can make for significantly more readable and thus maintainable code.
A good programmer aware of these issues is far less likely to come up with a mess than a less aware colleague who working in "write-only" mode, not thinking too much about design and maintainability. The good programmer is likely to write smaller methods that have meaningful names, likely to be more careful in dividing responsibilities, and generally more likely to write good code, being aware of the pros and cons of a dynamically typed language. This is a good thing if you're a good programmer. Less so if you're not. It's certainly not all black and white.
In short, dynamically typed languages tend to give us more power and flexibility in exchange for more freedom to shoot ourselves in the foot. Luckily, there are ways to safeguard our precious little toes. One of the most important of them being automated testing.
When writing serious applications with dynamically typed languages such as Ruby, it's even more important to have your codebase covered with automated tests. Why is that? Because the compiler doesn't catch our mistakes anymore? In part, yes, but the compiler never caught all of our mistakes anyway. I'd argue that the importance of automated tests--and techniques that promote automated tests such as test-driven development--is simply highlighted to us when we're using dynamically typed languages and are forced to drop our subconscious beliefs that the compiler catching typos is somehow protecting us from introducing defects as we go about changing our code. And, let's face it, in the enterprise, we're going to be changing a lot of code.
The way I see it, it's a good thing that dynamically typed languages make us face the reality and push us towards following good development practices. At least, that's what tends to happen with developers who've got the experience and the accompanying scars and burns. The good practices do need some support as well, however. Let's talk a bit about how that support realizes itself for the Ruby on Rails developer.
Talking about frameworks such as Ruby on Rails, we cannot blindly focus on the runtime. We have to consider both the runtime features as well as the development time support in terms of development tools such as editors, build tools, and deployment tools.
The IDE support for statically typed languages is generally much better than for dynamically typed languages such as Ruby. This stems from the fact that the static view of Ruby code doesn't convey the types of objects and thus the methods available on those objects, which makes features like auto-completion and refactoring somewhat tricky to implement. In practice, while as a J2EE or .NET developer you have all kinds of wizards, automated refactorings, incremental compilation, and so forth, as a Rails developer you have pretty much none of this. On the other hand, with Rails you don't need most of that stuff, automated refactorings being the exception.
While Rails lacks the great IDE support we're all so used to in our existing toolset for developing enterprise applications, Rails has the advantage of an interactive console to prototype with. Ruby's interactive console, irb, is a nifty little tool for quickly trying out snippets of code. The irb console itself isn't the punch line here, however. What constitutes a major help for the Rails developer is Rails' integration of irb into the rest of the framework.
Rails comes with an executable called "script/console", which basically loads the full environment into an interactive irb session for the developer to play with. From the console, one can quickly try out things that would otherwise be somewhat awkward to do or would require sprinkling "debugging" code around the production code base. With the console, we can inspect our domain model, change values, save objects, delete objects, and so forth. We get all this without any setup at all, since the console script configures the full Rails environment for us. Oh, and we get tab completion as well.
J2EE is probably the leading technology in terms of build tools at the moment. Apache Ant, originally written by James Duncan Davidson (coincidentally a Ruby and Rails convert nowadays) at Sun Microsystems and later donated to Apache along with Tomcat, is currently the de facto build tool for Java and J2EE projects around the world (with Maven catching up slowly but surely).
Ant has a vast number of extensions readily available for pretty much any task conceivable, and there's not many vendors that don't provide Ant tasks for integrating their tool with Ant if the product has anything to do with developing software in Java. The big question is, do these tools work with Rails applications as well or should we look into what the Ruby and Rails community has to offer?
Ruby gives us Rake, a build tool similar to Ant in the sense that it's mainly a descriptive syntax for specifying a build recipe with interdependent tasks. The main difference is that Rake files, unlike Ant scripts which are XML, are written in plain Ruby. This lets the Rake task perform pretty much any operations with the full power of the Ruby language while still preserving the descriptive approach to defining builds.
Ant certainly can be used for managing builds for Rails projects as well, although Rake is by far the more natural choice through its close integration with the Ruby platform in general. To help you make up your mind, we probably should look into the topic of continuous integration. After all, a core requirement for a build tool today is that it can be easily integrated with build servers.
For an advocate of continuous integration, the availability of a good build server is somewhat crucial for a comfortable development experience. While as a J2EE or .NET developer, we have the luxury of choosing from a number of potential tools such as CruiseControl and CruiseControl.NET, "native" build servers for Rails applications aren't too plenty.
The only build server currently available that has explicit support for Ruby (and Ruby on Rails) projects is DamageControl. It's functionally inferior to what CruiseControl, for example, has to offer but does fulfill the basic need for continuous integration as long as you're using Subversion for configuration management. The good news, of course, is that nobody's saying we couldn't use CruiseControl for building our Ruby projects as well. I wouldn't be surprised to see a CruiseControl plugin for Rake builds pop up soon from the Rails community.
Somewhat related to the topic of build tools and continuous integration is deployment after a successful build. We've got a long tradition of starting and stopping servers, deploying all sorts of archives and assemblies, copying files from one place to another, and so forth--all using a mixture of Ant builds, custom tasks, and the odd shell script. Generic build tools like Ant and Rake give us enough power to do all that, although it can get somewhat laborious.
In the Rails world, things are a bit different. First of all, we rarely restart the server during a development cycle because of Rails' edit-and-refresh capability. This can be of great help in those occasions when we'd like to do a quick visual verification of a change we've made and don't want to wait for several seconds or minutes, even, for the server to catch up with us.
The other big difference is Rails' very own Swiss Army knife, SwitchTower. SwitchTower is effectively a deployment tool that supports remote deployment (and rollback thereof) of Rails applications on UNIX/Linux servers over SSH connections. Its fundamental building blocks are shell scripts (thus its reliance on UNIX systems) and it knows how to do most necessary activities out of the box. Another strict requirement is the use of Subversion as the source repository.
There's something vaguely similar on the horizon for J2EE development as well, in the form of Cargo which is a generic API for managing a variety of application servers. Cargo could become a catalyst for a host of deployment tools for the J2EE developer. Time will tell. In the meantime, SwitchTower helps us deploy our Rails applications on clusters of any size with ease.
While good deployment tools are an essential ingredient of any software project in a complex enterprise environment, there are further aspects to consider as well. Perhaps the two most important of these being performance and the ability to integrate with legacy systems. Another important enterprise ingredient is how well a framework or platform supports managing data in the system. Let's talk about the performance of the Rails platform first and come back to the data and integration needs after that.
Performance alone doesn't mean anything. In practice, when we talk about enterprise technologies needing good performance, we're mainly talking about raw speed (the ability of the virtual machine or interpreter to churn through statements in our code) and scalability (the ability to scale our system by throwing in more hardware). A further factor to take into account with web applications is the platforms' support for effective caching between requests. Let's take a look at each of these separately.
In terms of raw speed, Ruby still has a way to go before it has reached its big brothers, the JVM and the CLR. Years of development have evolved the JVM and Hotspot technology into a super-fast machinery that has been recorded beating even native C++ compilers. Ruby, on the other hand, is still waiting for the upgrade that should come with the new virtual machine, YARV.
Early benchmarks have shown 5-10 times faster execution times with YARV compared to the current version of Ruby, which is a clear improvement and certainly is a good sign for Ruby in the enterprise. Plus, for the odd high performance job we'd like to tack into our Ruby application, we can always fall back on writing an extension in native C code.
While Ruby might not compete quite yet with the major platforms like Java and .NET in terms of raw speed, that might actually not matter all that much for a significant portion of enterprise applications. In fact, I'd vager that for most enterprise developers a far more important non-functional requirement is that of scalability rather than raw speed.
Scalability is also a somewhat ambiguous word. Scalability comes in two flavours, horizontal and vertical scalability. Horizontal scalability means scaling "out" by adding more boxes next to the existing ones. Vertical scalability means scaling "up" by adding more memory, more CPUs, faster disks, and so forth, into the existing boxes.
Scaling up is really somewhat trivial with Rails. Being based on multi-process execution through FastCGI on top of web servers like Apache and lighttpd, Rails is well adept to making use of added memory, added CPU speed, and faster I/O.
So, if scaling up is not an issue, then what can we say about scaling out? In short, Rails scales out quite nicely up to a point. Rails delegates clustering, fail-over, load balancing, and so forth, to the web server infrastructure and thus supports whatever Apache, for example, supports in terms of high availability and high throughput properties.
In practice, the interesting question with regards to scaling out becomes a question of how to scale the database. With the platform able to scale out the application itself by adding more nodes behind a load balancer, the way Rails manages its database connections gets to be in the limelight. The multi-process architecture of FastCGI effectively means that each running process reserves a physical database connection which, at least theoretically, limits how far we can scale with such an architecture.
Generally speaking, a multi-threaded architecture like what we have in J2EE has a more scalable approach. In practice, however, these theoretical limits are far from the reality for a significant number of what we call "enterprise applications." Google, Amazon, and other major online websites are scaling out with commodity hardware and architectures similar to Rails' so it's certainly possible to scale out far beyond the departmental level with Rails, although the invested effort in tweaking the system to play nice in such extreme setups could be non-trivial as well, eating away the programmer time we've saved through Rails' productivity boost in the common case.
Speaking of programmer time, a cache for the web layer is something I wouldn't want to write from scratch too many times, not to mention coming up with a custom cache for the entire persistence layer.
Rails offers only very basic caching on the persistence layer but it gives us quite good page and fragment level caching for the web layer. Rails also lacks built-in support for the kind of distributed caches that are available for Hibernate, for example, although there have been reports of people building quite exciting implementations on top of memcached, the same distributed cache implementation Rails can use for storing its sessions.
Rails also supports lazy loading through its object-relational mapping component, ActiveRecord. The most notable difference between ActiveRecord, which, just like Rails itself, is more geared towards ease of use rather than raw performance, implements lazy loading in a somewhat trivial way: every association is lazy. This is, however, quite sufficient for the majority of situations and, where necessary, we always have the option of going around ActiveRecord to perform the necessary joined queries ourselves.
Enterprise systems are almost by definition important and can affect--directly or indirectly--the corporation's bottom line in radical ways when malfunctioning. In today's world with crackers and script kiddies increasingly being after money rather than plain harm, our IT systems must be resilient to attacks of various kinds. Furthermore, few applications can do without some kind of authentication so the ability to integrate with LDAP, to store encrypted passwords in a database, and so forth, is a requirement that's practically a given these days.
As a technology mainly aimed at the web, Rails applications will be subjected to a variety of known attacks based on techniques like cross-site scripting and SQL injection. Enterprise technologies will have to be robust enough for system administrators to be able to harden the systems and shield our crucial business information as well as service delivery to our customers.
Unfortunately, there's no fool-proof way for a framework to prevent the developer from exposing his application to these attacks, but Rails does make it simple for the developer to not fall prey to these kinds of attacks.
For example, Rails gives us a view helper function called "h()" which performs HTML encoding for us with only 3 extra characters (or just 1 if we omit the parenthesis). By making it so easy to use, Rails once again encourages good practice. Similarly, ActiveRecord provides us with a wildcard query syntax similar to JDBC's PreparedStatement, which effectively helps us avoid SQL injection and often makes our code more readable as well.
Rails does introduce a potential vulnerability we have to remember to protect ourselves from, however, through one of its productivity boosting features. Rails makes it ridiculously easy to bind request parameters to domain objects upon a form submit. This, however, means that if we're not careful, a malicious user could intercept and alter--or add--form parameters in ways that could make a lot of damage. Fortunately, there is again an easy way to protect our domain objects from such malicious data injections. In practice, with Rails, such an "easy way" often means a trivial one-liner that declaratively tells Rails how to treat our model objects.
There's more to the security aspect, however, than these basic tools for preventing common attacks. The technology must give us some kind of support for implementing authentication schemes into our applications, for instance. While Rails itself doesn't provide explicit security APIs like some other enterprise technologies do, Rails comes with easy-to-use facilities for quickly putting together simple things that work.
The fundamental building block for such facilities is ActionPack's (the Rails MVC framework) filter architecture, which lets us implement our application's authentication and authorization aspects in a non-intrusive manner without mixing too much security-related code with the actual application logic.
Based on this filter architecture, Rails gives us a choice between a variety of tools called login generators, which are effectively code generators that generate the necessary plumbing code (and database schemas) for us to take care of authentication against a database user table, for example. Some examples of the functionality available through these login generators include password hashing with random salt, email verification with disposable tokens, and password reminders.
None of the readily available login generators support LDAP, however, which means that some systems might require a bit more manual work than others, needing to adjust the outcome of existing login generators with code that connects to a directory server rather than a database. Luckily, the Ruby developer doesn't have to go about implementing the LDAP protocol himself as there are mature libraries available for integrating with most standard protocols, including LDAP.
For any system that's going to live in an enterprise environment for longer than few weeks, the need for operations support becomes something that's painful to ignore. We need tools for monitoring our system's performance, we need tools for fixing simple problems easily without affecting the service, and we need tools for making the larger maintenance operations simple and void of risk. This is an area where Rails' architecture, relying on a web server, proves both an advantage and a disadvantage of sort.
We've been running web sites on top of the Apache web server for a decade by now, and it's probably one of the most stable and most thoroughly stress-tested software products alive. As a de facto standard, the Apache web server also has plenty of support in the form of a large user base, readily available management scripts, graphical tools, and what not. In other words, a Rails application is trivial to manage as long as the tools available for the chosen web server itself provide the desired functionality.
In general, the domain of such management and monitoring tools extends to the infrastructure rather well but doesn't quite reach the virtual machine-level performance metrics we might be interested in observing and analysing as well. This is an area where Rails currently lacks the kind of tools some of us are accustomed to with dominant enterprise technologies and, as such, it is a matter we'll have to consider when deciding whether Rails is suitable for a given system. Fortunately, most enterprise systems can be analysed and monitored well-enough using conventional, operating system-level and external performance measurement tools.
Enterprise systems often deal with complex domain models with hundreds of entities and database schemas with hundreds of tables and the chosen technology for implementing such systems must provide some support for dealing with all that complex data. Let's see how Rails can help us in this regard.
Hardly any project I visit these days has not at least considered adopting an object-relational mapping tool for alleviating the pain of mapping objects to a relational database. The J2EE community has long been a pioneer in ORM tools with Hibernate quite probably being the number one Java ORM framework in terms of developer mindshare.
For the Rails developer, the Hibernate-equivalent is called ActiveRecord. Part of Rails, ActiveRecord provides a simple ORM framework which focuses on making the 80% of cases a breeze and leaves enough hooks for the developer to handle the remaining 20% in less of a breeze. In practice, ActiveRecord makes the live database schema part of the object model, generating the domain objects' persistence code at runtime based on what it finds from the database. The developer is free to alter the domain objects' persistence behavior with simple declarations, most of which are built into the framework itself, such as a host of validations and trivial mappings between database columns and field names on the domain object.
Over time, ActiveRecord has become more and more performant as the Rails development team has added optimizations found in other frameworks such as Hibernate. It is still, however, not as blazingly fast as Hibernate can be, for example. As already mentioned, ActiveRecord's primary goal is ease of use rather than raw performance and it really makes the simple things simple. A point we'll have to keep in mind when pondering when to use which.
In part because of Rails and ActiveRecord's goal of making life easy for the majority of cases and giving enough rope for the developer to deal with the tough cookies with proper force, ActiveRecord isn't the best framework for adapting to strange legacy database schemas.
While ActiveRecord can be made to work with a range of schemas from the simple to the complex, the sweet spot for ActiveRecord is clearly in providing unbelievable ease of use with the simple end and faring quite well in the majority of cases. If you want to kick ass in the complex end of legacy schemas, ActiveRecord should probably not be your first pick.
One topic that doesn't seem to have gotten much attention in terms of tooling in the enterprise has been data migration. For one reason or the other, we've just managed to bite our lips time and time again when dealing with that dreaded word. This is another domain where Rails really steps up to the plate with its recent addition of the migrations concept.
Rails' migrations are essentially a way to describe changes to the database schema with simple Ruby scripts--version controlled along with the rest of the sources--providing both upward and downward migration upon deployment/rollback of a new version of the application. The Rails developers haven't invented anything new in the sense that any kind of change would be supported but, as usual, the basic stuff (adding, dropping, or renaming columns and tables) seems to work amazingly smoothly.
For an enterprise developer, the question of integration with legacy systems is an important one. There's the ERP system, the CRM system, the two competing content management systems, the existing J2EE applications, the .NET applications, a couple of applications built on top of Microsoft Excel, and then some. Oh, and let's not forget the mainframe which does our monthly paychecks. Unfortunately, every now and then, we have to integrate with these legacy systems, implemented with a variety of different technologies. Does Ruby on Rails fit this world of heterogeneous systems?
While Ruby has only a fraction of the integration capabilities presented by platforms such as J2EE or .NET, that doesn't mean Ruby and Rails cannot integrate with legacy systems. It just means that it might not be as easy as it could be.
The number of networking protocols available for Ruby developers in the form of open source implementations is growing almost daily and the access to writing extensions to Ruby with C code makes a whole world of existing native libraries available to Ruby as well. Yet, I'd guess that most Ruby developers don't feel comfortable writing C code so if you're aware of an exotic integration you need to build into your system, you better check out the availability of a robust Ruby library before setting the sail towards Ruby and Rails.
There is, of course, always the possibility of wrapping the difficult systems with something more usable such as a standard web service interface, which Rails can cope with, although that's obviously more work to do for integrating your Rails application with the legacy systems.
Speaking of standard interfaces, is there something more to standards that we should discuss? I think there is.
Ruby on Rails is obviously not a standards-based framework such as J2EE is, for example. Instead, it could be classified in the "best-of-breed" category of frameworks, aiming for the best possible set of functionality without too much attention to backwards compatibility.
In short, there are both advantages and disadvantages posed by being or not being standard. Some of the common aspects of this is the associated learning curve with a non-standard technology and the overall availability of developers proficient in the technology. Let's talk a bit about those.
As an object-oriented language, Ruby doesn't pose a significant learning curve in terms of a new paradigm. Having said that, the Ruby syntax is quite different from what we're used to in languages like Java and C#. Ruby is also not taught in the vast number of universities and other academic institutions around the world like Java, for example, is. This does represent a slight disadvantage for Rails as an enterprise web development framework, in the form of a non-zero effort in learning the language itself before becoming truly productive with the framework as well as in the availability of skilled developers.
In practice, however, the learning effort is not a big one and one can get started very quickly with developing Rails applications without knowing all the magic that's possible with Ruby. Furthermore, Ruby being an easy language to learn makes the developer availability less of a showstopper.
Another aspect to consider when discussing the benefits of adopting a non-standard technology to the enterprise that's perhaps not so commonly thought of is the non-standard solution's ability to innovate and grow more effectively. Let's call it traveling without luggage.
Following a standard does have a lot of advantages but it's never all black and white. Standards are created by standards bodies. Standards bodies are composed of individuals and corporations with a variety of vested interests. Standard bodies also have--for very good reasons--processes that take a while to churn through. All of this means that change is slower in standards than it is with independent technologies driven by a single authority.
Rails is such an independent technology, driven by a small number of core developers based on informal feedback from the larger community and based on the core developers' personal views. In practice, this shows in how the independent technology can make rapid improvements, occasionally breaking backwards compatibility in exchange for something new and shiny that makes us more productive now rather than a year from now. The way I see it, that's a good thing. I like having options. I like being able to occasionally choose the best-of-breed solution instead of the tried-and-true(-but-not-so-good) solution that's standard.
I hope that I've managed to give you ammunition to help in making decisions about whether you should look into Rails or stick to your existing toolset for that upcoming web project in your specific enterprise and what such a decision might mean for your organization.
I'm actively using Rails as well as J2EE and I'm mostly happy with both, each having their sweet spots as well as the sour spots. The kind of systems I'm building with these technologies tends to be different, though. The Rails applications are strictly about web whereas the J2EE applications tend to be more in the realm of backend systems, along with the occasional web application. Recently, I've found Rails to be a very productive and satisfying platform for typical web development and I've heard collegues report similar experiences. It's certainly nice to have Rails as an option to choose from.
While it's certainly nothing to bet your house on, the chances are that Ruby and Rails is going to be around for a while and getting a lot of attention as well. Maybe there's going to be a fourth major platform for an enterprise developer to choose from in the future along with J2EE, .NET, and LAMP, based on a powerful dynamic programming language and a framework that's truly a breath of fresh air. I for one wouldn't mind seeing that happen.
Some useful resources and pointers to forthcoming books on the topic of Ruby and Ruby on Rails: