25

This is not an opening gambit for RoR bashing - honest!

I'm learning Ruby and the Rails framework. Prima facie it appears to be pretty cool, and a wonderful experience compared to PHP. (In fact, it's reminding me of happier days with C# and .NET.)

However, going into this, I have no experience with this framework or language, and I'm curious - what are the current downsides or things you'd wish you'd known when you were beginning?

(Maybe this should be made a community wiki?)

4
  • I tried rails once and stopped when I realized that database-first entity design is not easily possible.
    – Falcon
    Commented Aug 29, 2011 at 12:46
  • 5
    avdi.org/devblog/2011/08/22/your-code-is-my-hell is worth reading. I would add that with any dynamically typed language it is extremely important to have 80% or more test coverage, or refactoring will be nearly impossible. Commented Aug 29, 2011 at 13:11
  • Making your question more specific and balanced (i.e. "Switching from PHP to Ruby on Rails - Pros and Cons) would remove the need to disavow yourself of bashing and the desire for community wiki. Commented Aug 29, 2011 at 14:13
  • 2
    @Thomas But that's not my question! The pros and cons of PHP are really well known. RoR's pros are quite easy to find. However, RoR's downsides aren't easy to discover as a newcomer and I suspect they would only be discovered with many years of experience. Learning from others' well-earned experience is the objective of this. Many of the CW's I've read are quite specific in their nature.
    – Matty
    Commented Aug 29, 2011 at 14:27

8 Answers 8

32

This is from experience learning, continuing to learn, and writing a relatively simple application in Rails.

1) Learning Curve

Rails is deceptively simple. The tutorials, videos, and books all demonstrate how quick you can get a working (if ugly) application, but these really just scratch the surface. They tend to heavily rely on code generation and "scaffolding" which admittedly is a good tool when learning but quickly outlives its usefulness.

Make no mistake, Rails is hard to master. Once you get past the very basics (more on this later) you will run headlong into a wall if you need to do more than the extremely simplistic "demo app" functionality that you see touted. You can get by with a basic knowledge of Ruby while learning, but you quickly need to pick up Ruby or you'll be left high and dry (and not the good kind of DRY) if you need to go outside the Rails constraints.

Rails is, as I like to call it in a loving way, paint by numbers programming. If you stick 100% to the conventions (i.e. stay within the lines and use the colors you're told to use) you can make decent applications quickly and easily. If and when you have to deviate though, Rails can go from your best friend to your worst enemy.

2) When All You Have Is a Hammer...

Rails does simplistic CRUD applications very well. The problem comes when your app has to do more than just read/write from a database. Now, for the record the last Rails version I used was 2.3.4 so things may have changed since then, but I ran into major issues when business requirements changed so the application had to have a small workflow system built into it, and integrate with a legacy PHP application. The Rails convention of "one form, one model" works fine for trivial apps and data entry applications, but not so much when you need to do processing logic, or have workflows, or anything that isn't the typical "User enters data into a few text fields, hits Submit" type of thing. It can be done, but it's by no means "easy", or rather it wasn't when I last used Rails.

Also, Rails does not like to play well with other applications that aren't using it's preferred methods of data access; if you have to interface with an application that doesn't have a "Web 2.0" style API, you have to work around Rails instead of with it; again I speak from experience here as this is what happened to me.

3) It's New

Finally, Rails is still the "new kid on the block" in many areas. This doesn't matter for personal use or "I think it's cool and want to learn it" type of scenarios, but speaking as someone who would prefer to use Rails at my day job, if you aren't in a location where Rails is widespread, it can be very difficult to find fulltime work as a Rails developer. It's still largely the domain of "hip, new startups" and not a major player in most metropolitan areas. Your mileage may vary in this regard, but I know my area (Tampa) Rails is essentially nonexistent.

4) Fire and Motion

Rails is ever-changing. This is both a good and a bad thing; it's good because the community evolves and embraces new concepts. It's bad because the community evolves and embraces new concepts. It can be very overwhelming for a Rails newbie because typically when you run into an issue, and look around, you'll see either people recommending such-and-such gem to fix it, or saying that way is bad anyways and you shouldn't use it, here's a better way... and you end up having a laundry list of additional tools to learn along with Rails to keep up with the Rails cognoscenti. Things like Git, BDD/RSpec, Cucumber, Haml/Sass, and a cornucopia of other things all float around and get pushed as the "right way to do things" in Rails-land, and speaking from experience you may end up being swamped trying to learn a dozen or more technologies in addition to Rails, because using the standard Rails toolkit feels "wrong".

This is now compounded even more by Rails 3.1 making Sass and CoffeeScript of all things the default, so a total Rails newbie not only has to learn Ruby and Rails but Sass (arguably simple if you know CSS) and CoffeeScript (not crazy difficult but certainly different enough from raw JavaScript) at a bare minimum to get started, plus it can be assumed Git. Even without factoring in RSpec and friends, and the dozen or more gems that you'll typically end up with, that's 4 different things you have to learn before you can seriously begin to write Rails applications. Compare this to a language like C#, or Java, or even PHP where your HTML/CSS/JavaScript/SQL knowledge isn't going to change and you just have to learn the language itself and perhaps the framework nuances.

4
  • 3
    W.R.T Rails 3.1 Sass & CoffeeScript are defaults that can easily be turned off. In fact "normal" CSS will just work since Rails 3.1 uses the SCSS syntax of SASS. You could use them but you aren't under any compulsion. W.R.T Git I think Linus explains it better why you should really be using a DVCS like Git, regardless of what framework you use. youtube.com/watch?v=4XpnKHJAok8 Commented Sep 2, 2011 at 19:18
  • Oh I agree, just saying that the Rails default is usually hyped a lot so a newbie will feel pressured to use it (I know I felt that way) Commented Sep 2, 2011 at 19:48
  • 3
    +1 for #4... if you leave Rails for a year, when you come back everybody will be flying around in spaceships and you'll be in your rowboat thinking wtf? Rails 2 syntax felt old before Rails 3 was released.
    – jimworm
    Commented Sep 30, 2011 at 13:53
  • -1 Good rails bashing post but you don't even suggest an alternative. "Nested forms" is a tough problem and Rails probably solves it better than anyone. Commented Mar 4, 2012 at 19:55
13

Documentation.

While Rails Guides are great learning resource, Rails (and Ruby, generally) library reference is not easy to navigate. Say, you want to learn more about belongs_to method. Although it is used on ActiveRecord::Base subclasses (one's models), it's not documented in ActiveRecord::Base docs, but in a mixin that the class imports. Essentially, you can not see a comprehensive list of all methods that you can use on an object in one place (except when you fire up irb and check the object itself).

With a highly dynamic language as Ruby, it is not straightforward to tell where a method you are using comes from. It can be a problem, especially for learning programmers trying to get a grasp on a new technology stack.

1
  • This is a killer for me; whenever I need to debug some of our Ruby/Rails code, I always spent way too much time trying to figure out where a given method was defined; and even then, always have to keep the idea in the back of my head that just because I can see the method definition, it may have been redefined elsewhere.
    – joev
    Commented Aug 29, 2011 at 19:03
9

Ruby on Rails has a significant learning curve. First you have to learn the oddities of the language, then learn the framework, then learn the Rails Way of doing things, then learn about the many commonly used Gems.

However, when you have learned those things, it does come incredibly naturally. In fact other frameworks start to feel like a burden.

Rails is very TDD/BDD-oriented, so if you are not then that's two more things you'll have to learn before you become a competent Rails programmer. You don't have a compiler and IDEs to back you up, so test coverage is very much your fallback.

Many TDD advocates, myself included, would consider this one of the strengths of RoR, as well as its curse. Once you start to write TDD, you find that the security offered by test coverage is better than the security offered by a compiler. Then having to write code JUST to please a compiler becomes burdening.

TDD doesn't feel like an additional task in RoR, it feels like the only way to work.

Rails has one serious performance problem: each request is queued up behind the currently active one, as opposed to threading them as most frameworks do or allowing blocking events to free other requests as the like of Node.js and Twister do. This means you have to code to make response times fast, but that's quite easy to do in most cases.

Rails is also very much designed to handle content systems very well, which in fairness is a lot of the internet. Doing something a little more complicated, such as a web game or an ecommerce system, means learning new gems. You quickly learn that all the gems are out there, but the more obscure the thing you want to do, the harder it will be to find good documentation.

2
  • Re the performance issues - I seem to recall reading that a lot of those had been largely solved with v1.9 of the interpreter, but I could be completely wrong. Are there any ways to overcome this performance limitation?
    – Matty
    Commented Aug 29, 2011 at 14:19
  • 1
    @Matty: As I added, code to make response times as fast as possible. Anything that can be left to a backend process, do so. But then you should do that with any framework -- it's just easy not to. Also, jRuby is threaded differently, but it does come with its own problems and my answer was long enough already.
    – pdr
    Commented Aug 29, 2011 at 14:22
7

In my personal experience, the major headache is around compatibility.

When:

  • there are x rails projects deployed,
  • each project uses y gems.
  • while there are n versions of rails,
  • plus m versions of gems installed,
  • with several versions of ruby,
  • on a single Linux box as production machine.
  • the programmer works on another OS X development notebook.

As a freelancer, who does not have the luxury to update/upgrade most of the things, will face a lot of compatibility issues from above variables... while rails, gems, and ruby keep changing/evolving.

2
  • 7
    Everything you mentioned is fixed by using RVM (or rbenv) and Bundler. You can have specific versions of Ruby and isolated sets of gems for each project then. Commented Sep 5, 2011 at 21:36
  • This answer is (now) totally irrelevant. RVM to manage Ruby versioning, Bundler to handle gem versioning; Capistrano to handle deployments to the production server and Figaro takes care of application secrets/environment variables. I develop my application on [Cloud9](c9.io) (a web IDE), and my deployment process is literally bundle exec cap production deploy. Capistrano takes care of versioning the application on the server. Like any other framework that comes out (e.g. Node.js), tools are written to solve your problems. Commented Jan 23, 2016 at 18:48
5

Speed definitely is an issue. Ruby's extreme flexibility comes with a significant performance hit.

Scaling horizontally is a non-obvious task, except for technologies specifically designed for that task, which usually trade off simplicity to scale well.
If you can handle 100 times as many requests per machine with technology A than with technology B, using technology A is worth consideration if you have reason to believe that you can serve your data from a single server for a time frame that allows you to add parallelization afterward.
In 2009 stackoverflow was still served from one web server. Of course this is no longer an option. But I suppose it was good they started with a technology, that could scale up to a lot of users on a single instance, before they had to worry about scaling out.

Compared to that, RoR is really slow. The time to handle simple requests is significant and therefore it's a problem to handle many clients (this is all to be seen in relation to faster alternatives).

For the sake of vague orientation, here are some numbers, comparing various other languages suitable for web development to Ruby:

Note that this doesn't mean, that if you use framework X for Java that it will be exactly 200 times faster than RoR. But the speed difference measured in these benchmarks has an important impact on the overall performance of your app.

11
  • 4
    This answer only talks about "speed" at runtime. Ruby (and Rails) is optimized for development speed. Commented Aug 29, 2011 at 13:51
  • 5
    This is not a good comparison. The majority of the time spent in a web request is doing I/O from the database. Linking to cpu-intensive benchmarks is misleading.
    – ryeguy
    Commented Aug 29, 2011 at 13:52
  • 3
    @pdr: A lot of twitter's problem was they were using ruby for everything, even their backend processes which were cpu intensive. Areas like that are were statically typed languages shine. They use Scala for that now. I honestly, truly, believe that using RoR is much faster in terms of development time than C# or Java. I would use it for most of the web app, and then use C# or Scala for any cpu intensive background jobs.
    – ryeguy
    Commented Aug 29, 2011 at 13:57
  • 3
    +1, for valid points. That being said, you can do a lot to optimize Rails applications. Rack lends its self to being a rather extensible system that allows for a lot of flexibility in how everything gets called. Not to mention, Ruby 1.9 is faster, JRuby is faster. I personally am a big fan of JRuby, being able to mix in the power of the JVM is a wonderful win (just be careful of gems which use exceptions for flow control -> huge overhead)
    – Xorlev
    Commented Aug 29, 2011 at 14:15
  • 2
    @Nicolai Reuschling: What value lies in Ruby or RoR being "optimized for development speed"? Can you provide verifiable, quantitative data how Ruby actually provides higher development speed than alternatives (Lift for example)? Anything else is just a void claim. Also, this question was about RoR downsides. High development speed is an advantage and thus out of the scope of this question. Poor runtime performance is within the scope of this question, because it is a downside.
    – back2dos
    Commented Aug 29, 2011 at 14:46
3

Rails has one serious performance problem: each request is queued up behind the currently active one, as opposed to threading them as most frameworks do or allowing blocking events to free other requests as the like of Node.js and Twister do. This means you have to code to make response times fast, but that's quite easy to do in most cases.

I think this is very misguided. You can run Rails in multithreaded mode. When running in multithreaded mode, you should only use IO libraries that release the GIL ( for example, 'mysql2' gem ) else it becomes sort of pointless.

If you are using jRuby, then you can just run a single rails process in multithreaded mode and fully utilize all the available CPU power. However, if you're on MRI ( Ruby 1.8.x or 1.9.x ), you must run multiple processes in order to fully utilize the CPUs, which is the case with node.js too.

4
  • A clarification question here - is there an easy to way to find which IO libraries release the GIL?
    – Matty
    Commented Aug 29, 2011 at 15:54
  • I think the best way to figure that out is to benchmark it gist.github.com/35d4769d8c8c0dfafc56 Commented Aug 29, 2011 at 16:08
  • Another example github.com/brianmario/mysql2/blob/master/benchmark/… Commented Aug 29, 2011 at 16:09
  • Good to hear from one of the core devs! This information's not listed in any of the documentation is it? It's a little tedious (although an interesting activity) to start testing libraries to find this out.
    – Matty
    Commented Aug 29, 2011 at 16:12
3
  • Rails has a lot of niceties that hide complexity from you. (ActiveRecord associations, the whole validation / saving lifecycle, the interpretation of request data based on provided headers) When you're just starting, this is awesome. As you grow, you will find that you begin to fit your app to "the Rails way" of handling things - sometimes this is good, sometimes this is harmless, and sometimes it's actually counter-intuitive to the thing you are trying to do. Not all database tables should be modelled as objects, a validation step may need to happen elsewhere, etc. A lot of Rails programmers eschew not fighting the framework (which usually is wise), but the long term effect of this is...you will carry the habits of Rails with you to places where they are not necessarily called for.

  • The community has a habit of writing software that is billed as "magic" - caching libs that magically work! Evented I/O that magically makes you faster! Magic magic! What usually is the case here is that a very attractive API is provided for a technical solution which is lacking, and you are fooled by the very pretty examples that the thing does what you intend, and only later find that it covers an incomplete solution. The cycle of this is pretty constant, and you learn to roll with it, but you should definitely get familiar with the idea of reading lots and lots of the code you depend on (a good thing!). Rails community magic solutions are not nearly as magic as the README may suggest, I'm saying.

  • Corollary to above: The more you use Rails, the more you should be reading its source. The better you understand the framework internals, the happier you will be long term. Not really Rails specific in this, but I'm just telling you from experience here. Method names sometimes promise something you're not actually getting.

  • Cargo cultism is an issue w/ Rails, but that is probably true w/ all framework / lang communities. It seems more pronounced (to me) in Rails, and as such tends to give a weird generational look to Rails code - as you work on different Rails projects, you will notice certain tendencies that tend to betray the time period in which they were created. As you can guess from that statement, the community tends to move pretty fast in adopting new solutions and deprecating old ones. You should really be on top of your Ruby news, just to understand some of the code that you'll experience on a daily basis.

  • Generally speaking, I think the issue of data concurrency is usually not well addressed by the community - as you grow an app, when you hit the point where you need to shard data, rollback physically remote changes and lock access to data, the solutions become a bit more hand tuned, which makes some of the nice looking Rails things you do get all muddied up w/ the technical necessities of accuracy. Rails doesn't solve every problem you'll have with a web app, I guess I'm saying, and while the creators certainly don't preach that message it's easy to be fooled into thinking that it's implied.

2

Depending on how you look at it, the speed with which Rails changes may or may not be a caveat for you. Things change somewhat radically from year to year as more is grokked out of what sucks and needs solutions.

If you're in active development, you'll have your finger on the pulse of this however.

Not the answer you're looking for? Browse other questions tagged or ask your own question.