A Django Developer’s Views on Rails

Introduction

I’ve recently started work on a Rails project after working on many Django apps in the past couple of years and I’d like to share my experiences and gripes from my transition. Rather than attempting to analyze all the pros and cons of each framework, I’m going to try to focus on the transition pain points.

Python vs. Ruby (Perl’s Ugly Sister)

Python and Ruby are quite similar languages and I’m not going to compare them in any serious depth. Both have their relative merits and I find both languages easy to work in. The one complaint I have about Ruby is that it borrows far too much from Perl. I’ve done a fair bit of scripting in Perl, and most people agree with me that Perl scripts of any substantial size quickly become very difficult to maintain.

Ruby is a great language but it tries to provide similar syntax and constructs to Perl, while duct taping all of Ruby’s own powerful features on too. This makes the Ruby syntax look like someone emptied all the symbols from the keyboard into a shotgun and shot them into your face.

Another irritating habit Ruby borrowed from Perl is having multiple ways of doing the same thing when simple having one way would be fine.

Say what you will about Python’s whitespace rules, but Python code is easy to read and consistent, and generally there is a single correct way of doing things.

As I mentioned earlier though, I do like Ruby, and one of the awesome features is Ruby’s blocks. Blocks are basically Ruby’s way of implementing closures and they are extremely flexible and powerful. In Python, to do something similar you’d use lambdas or list comprehensions.

Views Versus Templates

In the Rails world, the layer which generates the final markup sent to the browser is called the View layer. In a Rails View, you can chuck as much rails code as you like in amongst your markup.

Some of the early sites I worked on many years ago were written in PHP, which had the same idea. Rails views and PHP both allow the developer to mix markup and code together in the same file. When making PHP sites, you quickly learn that this is a terrible idea and quickly becomes a maintenance nightmare. One of the best things I ever did in my PHP days was to start using a PHP templating library, such as Smarty.

By restricting the template layer to simple constructs, like Smarty and Django both do, the developer is forced to keep business logic and complex constructs separate from the markup, which makes maintaining and changing the markup in future a piece of cake.

When it comes to markup reuse, the two frameworks are quite evenly matched. Django has template inheritance, which I think is a very elegant solution to the age old problem of sharing common markup, whereas Rails solves this problem using “Layouts”. Both frameworks also support template inclusion and “partials”.

Multiple Apps in a Project

When developing web projects, there are many situations where you need to have 2 very different applications which may need to access some of the same data. In the django world, you create a project and a project may contain multiple applications. Application B can use the ORM classes defined in application A’s model layer if it so chooses.

In rails, there is no such distinction between project and application. If you want to share model layer objects between code, your best bet is to have all the code in the same application. If you wish to logically seperate your applications, you can do so by creating 2 seperate rails projects, but it is not easy (or recommended) to share the models between the 2 projects. Another option is to have a controller per logical application, but this quickly leads to huge amounts of code in each controller.

URL Routing

In Django, you design the URLs for your application using regular expressions, a skill in every programmer’s toolbox (or at least it should be). In Rails you do these mappings using Ruby. Anyone who knows how to write regular expressions can instantly write url matching/capture expressions in Django.

Schema Migration

One thing Rails used to be much better at than Django was database schema migration. This is a feature built into Rails, but Django developers used to have to write manual schema migration scripts to transition their databases. These days though, there are numerous choices for easy schema migration for Django projects, my favourite being South. This is an area where Django really had to play catch-up though, and the various stable projects which have emerged to supporting migration are indicative of the maturity of Django as a whole.

Conclusion

Django and Rails both have their strong points and are similar in many ways, but certain fundamental philosophies differ, especially the Convention vs Configuration side. They are both great frameworks, and transition issues aside I look forward to working more with Rails in the future. Let me know what you think in the comments section below!

  • pass4sure5
    I really like this site.Thanks for sharing this.Thanks for giving good information.mcse practice exams
  • ochronus
    Well, for one bit, I don't think "using regexp for routing" is a plus for Django... using the full language palette is much more flexible - and who else will write/config routes than a developer? Django developers could use python to write routers, rails developers use ruby to do so. Why is a more limited regexp-based solution superior?
  • Great article, I am both a ruby and python developer use django and rails all the time. To me the biggest thing missing from django is a default migration system.
  • B.Keyes
    There's a few other differences that I found extremely important but no one else has commented on yet.

    1) Python documentation is significantly better than the equivalent Ruby documentation. If you want to learn Python or look up a function, you go to the Python website and you're done. For Ruby, you can find a large number of third party tutorials and published books... The same comments apply for Django compared to Rails.

    2) Based on relatively little experience but I get the distinct impression that Rails is willing to make seriously backwards incompatible changes for relatively minor reasons. The few Rails developers I've had a chance to talk to personally also aren't too thrilled about this aspect.

    3) Ruby makes much heavier use of magical function names. If you know what they are, that's all fine and good. If you need to consult documentation or are trying to link it back to how it was created however...
  • @Aron, I don't mean to appear argumentative but regarding your last point you should check Justin George's comment, a few comments above the comment you made. Loose coupling is on the way for Rails in a very big way. It's going to be an awesome improvement.
  • Argumentative? This has to be THE most rational discussion I've ever seen of Rails vs. Django. Usually, these things devolve into a Southparkian mess of namecalling...

    Anyway, I'm not sure what he's talking about exactly when he says "rack apps." Whether he literally means microframeworks like Sinatra, or Rails own internal microframework, Metal. Both are very cool, but have sort of niche appeal.

    If he's talking about Engines, then let me say +1. It doesn't quite get us to Djangoland, but it comes close.

    The bottom line is it's good to see these frameworks growing and learning from one another... migrations to Django; engines to Rails.
  • Hey,

    I'm a Ruby/Rails guy with some Django experience, and I think you did a good job of hitting some of the bigger differences. I think you're absolutely right that these are more preferences than game-changing differences. I happen to like Ruby, but I come from a Perl background. So there you go.

    Anyway, a few points, and corrections:

    1) You can use regular expressions in Rails routes in just the way you can in Django. It's just not particularly common or well-documented. But you can do it.

    2) I totally, totally agree with you on the view code. It is a very bad practice to throw app logic into the view, but people do it, and Rails allows it. As with all things Rails, however, there are options: Liquid, for example, is a port of the Django templatting language to Rails. We are looking at starting to use it for our projects as a "safe" alternative to erb -- so we can allow view code to be changed without worrying about exposing the full power of ruby in a view.

    3) I'm surprised you didn't mention with Django admin, which almost all Django folks do. It is a big plus over Rails. There are plugins that kind of do the same thing, but (at least the last time I looked) nothing is anywhere near as good.

    4) I'm equally surprised you didn't mention Django's seriously underwhelming ORM. I know it's getting (or maybe has gotten? The last version I touched was .96) a major re-write, but it was nowhere near as complete as AR for Rails.

    4a) Of course, most Django folks don't see AR as a plus, given all the behind-the-scenes magic. They have a point, and at least right now we're sort of stuck with it. But there is hope: Rails 3 will make swapping in datamapper or sequel or another ORM easy as pie (we hope).

    5) Loose coupling within Django apps is a HUGE win for Django, and I've wished there were something like it for Rails. Rails Engines are close, but the idea that you can just drop one app into another and off you go is pretty slick indeed.

    Anyway. Nice piece.
  • carlitus
    nice comment, you should write a blogpost :)

    By The Way, Streamlined and Hobo are pretty cool for admin UIs
  • I checked out Streamlined a long time ago, and it wasn't bad. Have not looked at Hobo, but will do so. Maybe I should have looked again before making such a blanket statement, but the Django Admin is so freakin' elegant, and gives you so much right out of the box, it would shock me if either one were close.
  • andrew
    Python: Ugly's ruby cousin
  • Moe
    For the purpose of sharing my models among other projects I simply make a symlink to my model folder.
  • OtengiM
    Python and Django all the way for me!, I can't stand Rails community. They think they are the master of the universe or some shit as that.
  • Jason
    I can't stand people that speak in absolutes when they know nothing about what they are speaking about.
  • @OtengiM
    I think you'd be surprised with how awesome the Rails community is. Don't let a few people skew your view of the Rails community as a whole. Please check out http://railsbridge.org/ as an example.
  • Daniel
    I don't know perl. I tried many times python before ruby however when I saw ruby first time I learned it in two hours it seems a lot more readable than python (and perl) to me.

    "having multiple ways of doing the same thing" is not a problem for me, I like that, I like to have options and *choose*

    "Multiple Apps in a Project" -> what about the engines? perhaps rails3' mountable apps will solve this issue.
  • len() is just a built-in, consistent alias to call instance.__len__, the same way type() calls instance.__class__.

    What's wrong in that?
  • tjstankus
    Nice article James. Having done a fair amount of programming in Python and Ruby I have been through some of the transition pain you describe. For example, should I use 'and' or '&&' in Ruby? (Answer: use &&. It's got a higher precedence and is more canonical Ruby code.) Most of that kind of confusion goes away after a while. I've come to really love Ruby. IMO it's a beautiful and flexible language. If TMTOWTDI bothers you though, Ruby may not be a good fit for you.

    You make a good point with the multiple apps in a project concern. But that's being addressed in Rails 3. There's also an interesting trend in the Ruby community (well, maybe not a trend just yet) of building several small, limited responsibility apps that talk via HTTP/REST. The Sinatra guys gave a talk about this at RubyConf 2008 (http://rubyconf2008.confreaks.com/lightweight-w...) That approach definitely keeps your logic separate and contained, but makes your data available between apps. It's probably not the best approach in all situations but it works well for some.
  • You have to be careful in saying things like "views allow business logic in them" as a con for Rails. The rails philosophy certainly doesn't support that approach and that is more of an issue with bad programming of the developer and not of rails itself.

    I see arguments like this all the time where someone says, "Ruby/Rails lets you do this....so it's a bad language/framework to use". What a language or framework allows isn't necessarily the issue, but rather how the programmer uses it.
  • I completely agree Robert. I wasn't saying it makes for a bad framework,
    more that it was more open to developer abuse.
    Thanks for the comment.
  • Jason
    A door on an airplane will let you open it and jump out. Should we get rid of the door? It still serves an important purpose. Just because someone may abuse something does not mean it should not exist. I hate frameworks that act as though I am not intelligent enough to take care not to do things incorrectly.
  • It's an opinion piece Jason. I'm not saying rails/ruby is bad I'm saying
    they are different and talking about pain points in transition.
    If you've ever worked on a project with crazy developers you can probably
    appreciate what I'm saying.
  • dude
    Very interesting how different view points can be. Ruby's perl-ish ancestry is causing me to start being envious of perl -- to the point of fantasizing about using it instead of ruby. In other words, ruby's perlisms are a _good thing_ in my book.

    Also, can't help but point out that Python has lots of inconsistencies. For example, in something as simple as a method call:

    Want to split a string on spaces into a list?

    "some string".split()

    Want to get the length of a string?

    "some string".length()

    oops! Sorry:

    len( "some string" )

    I mean, wtf.
  • Yea, this is true. The "older" string methods have been kept around for historical reasons http://www.diveintopython.org/native_data_types...
  • Totally fair point, there's a few crazy things like that in Python too.
  • Interesting post James. I didn't realise that Rails doesn't separate out business logic from the template markup, that definitely helps from a frontend point of veiw
  • tjstankus
    Actually Rails *does* separate business and template/view logic. James's complaint that "you can chuck as much rails code as you like in amongst your markup" is about what you could do, not about what you should do, or what Rails encourages you to do. I've looked at a lot of Rails code, some of it downright bad, but I've never seen gross and consistent abuse of model/view logic separation. It's just not a problem in the real world.
  • John
    My big pet peeve in web development is the idea of a templating language. I just don't get it and try to steer away from frameworks that use them. A good developer knows what level of code belongs in a view. And on top of it, MVC by its nature already removes 2/3 of the possible code that could go into a view via model & controller. So to add a templating language, which is programming logic anyway, to a view is pointless. The whole argument about making it easier on the designer is pointless too. I mean compare looping logic that iterates through a list in python and in the template language. Not that much different. It would be easier to just have to deal with the programming language 100%.
  • I agree, but you often have to work with _bad_ developers too! :)
  • In practical experience, only the 'project vs app' distinction is a practical problem. Most apps that I have worked on ended up becoming huge hairballs of code, with 'add another controller' being the method of expansion. Pretty soon the code starts collapsing under it's own weight and everything is factored into seperate applications.

    Right now, a major part of the next version of rails is the addition of sub-app structure in the form of Rack apps (stolen from WSGI in python) which manage distinct parts of the app on their own. They're independently testable, but can share libraries and model definitions.

    Most people do not use the perl-legacy conventions (such as $! for most recent exception). I very rarely see them, and when I do, they are strictly in command-line experimentation or hackery scripts not meant for long-term use.

    'TIMTOWTDI' is practically not a problem for most people because the 'right' way to do it is the only one commonly used.

    Ditto views, which are theoretically unlimited in what you can include, but practically used in a way nearly identical to smarty. Any substantial code is put into a helper, which works like Smarty's definitions for adding new template functions.

    One problem you don't discuss is the excessive level of metaprogramming used in the Rails core, which is both slow and confusing. This is one of the major problems I run into on a routine basis (stack traces ~30 layers deep routinely) Luckily they're remedying some of that for the next version, which will use more sensible modularity in code design and fewer layers of stack to accomplish the same tasks.
  • Indu
    A nice post, gives some insight into how a Django developer would feel about Rails. I share your feelings about Ruby being a Perl cousin. I am trying out Ruby and Python and I feel Python to be slightly comfortable (personal taste playing a big role). But both are much better, simpler and more elegant than Java that I am used to since 5 years.
  • bob hoskins
    ctfo
blog comments powered by Disqus