magpiebrain

Sam Newman's site, a Consultant at ThoughtWorks

Posts from the ‘Ruby’ category

On a Wednesday instead this week, just for kicks, but once again at the “Olde Bank of England”:http://www.pubs.com/pub_details.cfm?ID=214 from 7pm. No agenda as yet, but I want demos! Leave a comment if you’ll be coming so I can get an idea of numbers.

Though the magic of Google Calendar (I’m so Web 20 it _hurts_) I now have publically available “ical(London 2.0 meet-up events – iCal)”:http://www.google.com/calendar/ical/c7ilcesmkkn0e3bkirk4kgf5cc@group.calendar.google.com/public/basic and “rss(London 2.0 meet-up events – rss)”:http://www.google.com/calendar/feeds/c7ilcesmkkn0e3bkirk4kgf5cc@group.calendar.google.com/public/basic feeds. Once I get home it’ll be on upcoming too (damn corporate firewall tagging it as a dating site…), although unless upcoming starts letting me splice in my Google events soon I’ll probably stop using the service.

p(update). _Update_: I’ve added a simple block on the bottom of this site listing the upcoming London 2.0 events using dwc’s “iCal WordPress plugin”:http://dev.webadmin.ufl.edu/~dwc/2005/03/10/ical-events-plugin/. There is also a specific “category”:http://www.magpiebrain.com/blog/category/web-20/london-20-meet-ups/ and “rss feed”:http://www.magpiebrain.com/blog/category/web-20/london-20-meet-ups//feed for all London 2.0 meet-up information.

Thanks to everyone who attended London 2.0 RC 4 last night (in rather cramped conditions). The “usual(Simon Willison’s weblog)”:http://simon.incutio.com/ “suspects”:http://www.brunningonline.net/simon/blog/ were in attendance, as well as Adrian Holovaty who was in for a few days.

“Phil Dawes”:http://www.phildawes.net/blog/ demonstrated both “Bicycle Repair Man(Bicycle Repair Man – Python Refactoring Tool)”:http://bicyclerepair.sourceforge.net/ and the Python testing tool “Protest”:http://www.phildawes.net/blog/2006/03/17/protest-rocks-generate-documentation-from-tests/ (we need screencasts of both!), and I pointed numerous people towards the impressive “DabbleDB”:http://dabbledb.com/utr/ screencast. Demo of the night probably had to be Remi Delon showing off “Python Hosting”:http://www.python-hosting.com/. They offer a very slick, one-click install of a variety of different webapp frameworks (everything from TurboGears to Zope to Django) for a very “reasonable price(Python Hosting shared hosting plans)”:http://www.python-hosting.com/shared_hosting. His screencast is out soon – but put it this way, TextDrive’s TextPanel is going to have a lot to live up to, not to mention their forthcoming Rails-dedicated hosting (note: I’m a TextDrive user myself). Despite their name, Python-Hosting do also provide Rails hosting, however it’s not yet integrated with their slick user interface.

Details on next month’s London 2.0 RC5 coming up soon.

Yes, I know what you’re thinking – “So soon after the announcement of the “March meeting(magpiebrain – London RC3 March Meetup)”:http://www.magpiebrain.com/archives/2006/02/25/london20_rc3? Has Sam started getting organised?”. Well, kind of – actually I heard from Harry Pot “Simon W(Simon Willison’s Weblog)”:http://simon.incutio.com/ that one of the Django devs, “Adrian Holovaty(Adrian Holovaty’s Weblog)”:http://www.holovaty.com/, was going to be in town.

Given that it’s so far in advance, I’m sure many of you won’t know if you can make it, but once again it’ll be the same cross-language cross-technology meetup, broadly aligned along Web 2.0 lines – all are welcome, whether or not you think Web 2.0 is great, or just a crock of poo.
Continue reading…

Another Django/Rails/Catalyst/Java/web2.0 love in to be held at “The Old Bank of England”:http://www.beerintheevening.com/pubs/s/66/660/ onFleet Street. Web 2.0 advocates and detractors are welcome, as are any enthusiasts of Lisp, Python, Ruby, Java, Haskell or whatever other dirty commie language you lot use.

Once again I’ll be (badly) organising this with the aid of Simon Brunning, his “jury service permitting(Small Values of Cool – London 2.0rc3)”:http://www.brunningonline.net/simon/blog/archives/002009.html.

If you’re coming along either leave a comment or register your interest on “Upcoming(Upcoming.org – London 2.0 RC3)”:http://upcoming.org/event/59719/ – we have to book a room so it’d be good to get an idea of numbers.

As I assume many of you (including myself) will be attending the “The Future of Web Apps”:http://carsonworkshops.com/summit/, I’m not going to run a specific Web 2.0 RCX meeting this month. To be honest I can only stand to hang around you new-media over-enthusiastic hand-wavers once a month (you know “who you are”:http://simon.incutio.com/!), and what with the lineup for the summit it looks like I’m going to get about 4 months worth of Web 2.0 hypness. I’m planning to run an unofficial meetup in the evening after the summit proper, venue tbc.

Just a quick note after a long absence (no doubt a flood of posts will now follow, preceding another too long gap). Anyway, “London 2.0rc2(London 2.0rc1 on Upcoming.org)”:http://upcoming.org/event/47958/ is on for this Tuesday. Once again it’ll be combining the Python meetup, and will be open to all Ruby, Django, Rails, Python, RSS, Catalyst, web.py, TurboGears, Java, RDF and Struts enthusiasts, and interested observers. After missing the last two (which is bad form as an organiser) I’ll be making a concerted effort to put in a prolonged apperance.

If you’re coming, you could either signup on “Upcoming.org”:http://upcoming.org/event/47958/, or leave a comment here. As normal, it’s from 6pm til late at the “Old Bank of England(Upcoming’s entry for the Old Bank of England)”:http://upcoming.org/venue/16413.

*We need a snappier name…

As the calendar gets a little crowded in December, myself, Simon and Jez have decided to combine the Java, Django/Rails and Python nights together in one big bash at the Old Bank Of England, on the 12th of December, from 7pm onwards. As normal there is no particular agenda, although people wanting to do demos are more than welcome (just let me know first so we can publicise it).

Oh, and as Jez has had to stick a deposit down for the reserved space, please leave a comment to let us know you’re coming!

At the last meetup, the majority of the people there were ‘thinking’ about using either Rails or Django on a real world project. So by way of some blatant agenda setting for the meetup on the 10th (don’t forget to go and leave a comment if you’re coming) what is stopping you from using either?

Is it concerns about maturity? Scalability? Deployment options? Does the lack of (development) tools put you off? The lack of a workforce, or simply the fact it is in a new language? Is there some killer feature that either one needs to make you use it? Perhaps if enthusiasts of both communities start addressing these concerns and start engaging in some (balanced) advocacy and honest discourse, the adoption of both can be sped up.

Since lambasting someone for a less than fair Django and Rails comparison, I’d planned to do my own. To start with, my comparison is based on several days worth of Rails development and about a weekend’s worth of playing with Django, using the (currently four part) tutorial.

I’ve had this reviewed by both Rails and Django developers, but if you think I’ve misrepresented anything or left anything out then feel free to leave a comment and I’ll make sure to put it right.

Background

Rails is framework which emerged from the development of a web application, Basecamp. Django was emerged from the development of the highly successful Lawrence Journal World. Both applications were written in situations and organisations that historically would have ended up being written in Perl or PHP – but ended up being written in Ruby and Python respectively.

The fact that both frameworks were the result of development of specific applications means that both frameworks are focused on supporting those specific types of application. As a framework Rails has been around for little over a year, whereas as a framework in its own right django has only been public for around two months. Neither has yet made it to version 1.0.

Languages

On the face of it, the biggest difference between the two has been the choice of development language. Outside of Japan Ruby has made little impact despite having been around as long as Python – a colleague of mine once said that the number of Python programmers in London probably outnumbered the number of Ruby programmers in Europe and the US and he’s probably not wrong. Anyone having to consider which of the two frameworks is right for them is inevitably going to have to think about the task of hiring people and this may have an impact on their choice.

Ruby does seem to have some more powerful language features – it has slightly better closure support than Python (although perhaps not enough to be a differentiating factor) and the extremely useful mixins. Ruby’s OO support also feels much cleaner. Both support inheritance (Python supports multiple inheritance, which Ruby’s mixins more than make up for). But the requirement that self be passed in to all python instance methods drives me potty.

On the other hand Python has a much cleaner syntax (which given its background is no surprise) – more than once I’ve found myself using a third type of parenthesis in the same Ruby method quite validly, only for me to look back at what I’ve done and feel that I’d regressed to the bad old days of Perl. It would be nice to think that one day a language will come along which manages to add powerful features without making the code look like it’s been rendered with the wrong character encoding.

Ultimately comparing two languages that are so close (they’re certainly more similar to each other than Java or .NET) is going to come down to personal choice or a specific requirement. But for more indepth comparisons you’ll no doubt find many out there on the web.

Requirements and installation

Installing both Rails and Django is fairly easy once you’ve got the relevant interpreter installed. Ruby can make use of the excellent Gems system, which is something Python (and to be fair most other languages including Java) would do well to mimic.

Both also come with their own webserver for development purposes, which is great from a developer’s point of view. There should be anything stopping you from getting both up and running fairly quickly

Deployment options

Both Python and Ruby suffer from a similar global interpreter lock problem – basically neither the Ruby nor Python interpreters are completely thread safe. When running multi-threaded applications a lock has to be acquired by a thread before it can access any objects. That means that both Ruby and Python scale by using multiple instances of the interpreters rather than the Java approach of using multiple threads – as a result the deployment options are fairly similar.

Django’s current recommended deployment is using Apache and mod_python, although there is no reason why fastcgi couldn’t be used, or even an alternate server such as lighttpd (which is TextDrive’s current approach to hosting Rails).

One important point is that Django currently only supports Sqlite, MySql and Postgres (although support for Oracle has already been submitted to the project), whereas Rails supports virtually all the major relational databases.

Caching

Django’s heritage as a framework supporting large, high-volume websites shows through clearly in the built-in support for a variety of caching options. Rails’ own caching doesn’t seem as flexible. With Django multiple caching backends are supported (in memory, memcached, or DB) coupled with supporting caching at multiple levels – either for a whole site, a specific page or fragment (like Rails), or even a specific object.

Setting up a project

Both frameworks generate your project structure for you. Django actually has separate concepts of Project and Application (of which more later). Rails goes a little further – it also generates a build file and stub tests (I won’t call them Unit tests as Rails does, because they’re not). There is nothing to stop you testing Django of course – it’s just as testable as Rails – however it would be nice to get some guidance on how to do it. My feeling is many people new to testing are more likely to do it with Rails because it’s built right in and it’s well documented.

Adding models

In Rails, you define a table that represents your model, and then generate the stub code to create a Rails model that binds to the table. You are then free to build upon the stubs. With Django, you define your model in Python code, and have Django generate (and even execute) the schema for your model.

The fact that your Python code can be the canonical reference for your models means understanding can be simplified. It can seem odd to be adding code to a Rails model and not know exactly what attributes your model has without referring to the database schema. The fact that Django can generate the SQL from you model also leads to flexibility in development – for example a developer can use Sqlite which is fast use and trivial to setup, but deploying onto MySql or Postgres is easy as you can regenerate the SQL for your target database from the Python code – that the SQL for both databases might need to be different is hidden from you.

Early on your model will be constantly changing – I’ll often find myself writing some Rails code, need to add a new attribute to a model, have to change my (DB-specific) schema. With Django I change my model and regenerate the SQL. The only minor annoyance is that there is no equivalent of a model-specific SQL refresh – something that could drop a specific model’s tables and regenerate the needed SQL automatically. Instead you have to have the admin script dump out the SQL to the command prompt and run it in yourself.

Django’s generation of schema also extends to creating lookup tables for many-to-many relationships.

The downside to having Django generate the SQL schema is that there is more work involved in supporting databases – currently only MySQL, Postgres and Sqlite are supported, although I’d be highly surprised if support for other databases wasn’t on the way.

Django does seem to offer the ability to reverse-engineer models from an existing schema, although I don’t have information as to how sophisticated this is (for example to what extent it can determine inter-model relationships).

Another thing to note is that unlike Rails Django doesn’t allow you to manage your own transactions (although it is going to be added). I’ve not found myself needing it in my Rails or Django work to date, although as a J2EE programmer not having the ability to control this if I need to is a minor concern for me.

Interaction with the Database

Both Django and Rails have taken the decision to bind models to the database. Methods to save, delete or lookup objects are called on the models themselves. Neither specifically stops you from providing proper separation, but if you do you’re on your own. Going forward it will be interesting to see if either Rails or Django start providing the ability to have a clean repository layer as nicely as they do the current DB access, although it will probably require both of these frameworks to be used in more complex situations than they are currently.

One nice thing Django offers is the ability to write your own SQL in the model to access attributes. Rails does nothing to stop you calling SQL directly, but the fact that with Django you are doing this custom lookup in the same place as the definition of the other attributes (whereas with Rails it would be split between the schema and Rails model) results in something much cleaner.

Projects and Applications

A nice touch with Django, and another example of the environment in which it was developed, is that there is a project in which you can have pluggable applications. This should hopefully lead to smaller (Rails-style) apps being created, reused and integrated easily into a larger Django projects. This was something that was demonstrated wit LJWorld, with new parts being added incrementally without a need to deploy the whole site.

Controllers and URLs

With both Rails and Django URLs are mapped directly to code. Rails automatically generates stub controllers to map to the scaffolding (of which more later), whereas with Django you have to create them yourself.

With Django you use regular expressions to define URL’s that bind to your python code. That makes it much easier to create RESTful URLs – in fact all of the tutorials reinforce this. The fact that you have RESTful URLs happens to make controlling code simpler is just an added bonus.

By default Rails gives you URL’s in the form controller/method – but these can be edited using the routes.rb file to give you proper RESTful (or not) URL’s. Unlike Django’s pseudo mod_rewrite approach, Rails uses Ruby code to handle routing, which depending on your point of view could be considered more readable.

The URL to code mapping can be specified either for a whole project or (more likely) for a single application.

Templating options

Both Django and Rails template using embedded Python or Rails code (like using Java scriptlets in JSP pages). Much more work has been put into Rails’ helper code – Ruby code you can use to generate HTML constructs – its excellent Ajax support being one example. Django does make it fairly easy to swap in other templating options if required (such as Zope’s Template Attribute Language, or perhaps Clearsilver). I’m less savvy on alternate templating options available for Rails – although obviously if you used something else you’d have to do without many of the helper methods available.

Administration and User management

Django’s administration interface is simply excellent. Unlike Rails’ scaffolding views, it is not designed to be viewed by everyone (being an Admin console), but unlike the scaffolding it is perfectly functional and you could imagine making use of it without alteration in a production application.

The administration console is password protected – you can generate a superuser account using the command line admin script. Once you’ve logged in you can add more users and even groups – Django automatically generates permissions for both the admin functions and your models which can be assigned to a group.

You can also add new model instances in the same way as Rails scafolding, but the view is much better. You have nice popups and shortcuts for date and time fields, dropdown lists for one-to-many relationships, and multi-select lists for many-to-many relationships all provided without any developer interaction.

Rails does have a measure of user administration in the form of the add-on salted login hash generator, but despite some hard work by the developers it does seem problematic and nowhere near as slick as Django.

So which is right for you?

I said at the start that the two frameworks were developed as a result of two very different applications – and most of the differences between the two are a result of this. If you are developing a simple (in a domain model sense) application where you want to use Ajax to deliver a great UI, Rails is probably for you. If however you want to develop an entire site with different types of applications within it – then Django’s plugable applications and general approach might be what you’re after. Equally, the better user and administration side of Django favours portal style applications – this is something you’ll have to do yourself if you want to use Rails.

There is scope for both frameworks to learn from each other, and I still have a question around how well Rails will scale (in terms of the size of the site, not number of hits) – Django has already proved it is capable of this with LjWorld.com. Likewise it will be interesting to see if Django can or even wants to make the use of Ajax as simple as it is with Rails (although work is already progressing along these lines), or if the more powerful language features of Ruby will prove the deciding factor.

Personally, given my own current projects I’ll be spending some more time with Django – but all that means is that it is one more tool that will sit alongside Ruby, Rails and J2EE in my particular toolbox. And just like Java web frameworks before, I fully expect to see more and more web frameworks based on dynamic languages (such as Nitro or SeaSide) start to gain more visibility and yet more options. It seems we’re going to be spoilt for choice.

I’m taking a break from my recent series of articles on Ruby (see Parts one, two and three of Ruby for Java (and C#) programmers) to revisit the subject of mocking in Ruby. My recent overview of the currently available mocking tools lead me to discuss a better syntax for the next mocking API.

One of my aims when talking about a new syntax for a mocking API was in order to make expectations more readable – and more usable as a living document detailing how the code being tested actually works. As has already been discussed, Ruby’s flexible syntax makes it particularly suitable for the creation of Domain Specific Languages – and I think we can do much better than the existing API’s (or even the more mature JMock) in moving towards a DSL for mocking.

My original idea was to steal from the structure of JMock:

mockObject = Mock.new(ClazzToMock)
mockObject.expects(:someOperation).
  with(arg1, arg2).
  willReturn(someReturn)

To which Carlos (correctly) pointed out that I should make use of Ruby’s built-in language constructs – he proposed using hashes to avoid chaining calls together:

mock_obj = Mock.new(ClassToMock)
mock_obj.expects(
:do_stuff,
:with => [arg1, arg2],
:returns => someReturn
)

The obvious difference here is that the API cannot enforce the expectation to be written in a way that makes sense, as I could just as easily write:

mock_obj = Mock.new(ClassToMock)
mock_obj.expects(
:do_stuff,
:returns => someReturn,
:with => [arg1, arg2]
)

Also of note is that (when we get a decent one) IDE’s won’t be able to help you construct your expectations – this was part of the aims behind JMock’s structure.

Nat countered with the use of a mocking mixin, and using blocks as the expectations:

mock = Mock.new “exampleMock”
expect 1 { mock.do_something(eq(10), !null) }
expect 3..4 { mock.something_else(eq(“hello”) }

In EasyMock terminology, when you define the expectation in a block, it is in a record state – that is you are registering the calls that you expect to be made. In EasyMock, you then have to call replay before the mock can be used. This really doesn’t help readability (JMock gets around this by having a different object for recording expectations to the one used as the mock). With Nat’s approach, the mock is only in replay mode within an expect.

Taking this further, I cannot see why multiple expectations on multiple mocks couldn’t be defined inside a single expect call:

expect {
  mock1.halve(eq(10)).returns(5)
  mock1.double(eq(5)).returns(10)
  mock2.insult.returns("Boogers!")
}

Before (more importantly if) I decide work on this, I want to try and get some consensus of opinion as to what would make a sensible syntax, so feedback on Nat’s approach is appreciated!