rails vs django study presentation
DESCRIPTION
Ruby on Rails ("Rails") is the dominant web programming framework for Ruby and, even outside the Ruby community, is considered the epitome of the latest generation of high-productivity, open source web development tools. Django is one of many competing web development frameworks for Python. It is notable, first, for being highly regarded amongst Python programmers, and second, for being one of the few of the new generation of frameworks that does not ape Ruby on Rails. Both Rails and Django claim greatly enhanced productivity, compared with more traditional web development frameworks.In this paper, we compare the two frameworks from the point of view of a developer attempting to choose one of the two frameworks for a new project.TRANSCRIPT
A Rails/Django Comparisonby Ben Askins and Alan Green
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License. To view a copy of this license, visit
http://creativecommons.org/licenses/by-nc-sa/2.5/or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.
The original version of this presentation is available at http://3columns.net/habitual/docs/Pres2.odp
Django Rails vs.
We wrote the same application twice
TagBook
Reading
Reader n m
nn
11
Developer skill level:● Not identical● Too advanced to be called ‘beginners’● Insufficiently advanced to be ‘typical’
Development environments different:● New Mac vs Old Windows laptop● Central Coast vs Cityrail
Part-time development – start-stop effect and gaps between sessions
Didn’t consider:● Performance● Deployment● Maintainability● Enterprise-friendliness
Unrepresentative example application:● Too few pages● No Atom/RSS feeds● No public data entry
Development practices:● Didn’t do it the “best way”● Older versions of Rails and Django● Didn’t use this or that helpful third party feature
This was just a single trial. Really need:● Multiple developers● Multiple applications● Multiple environments
“Multiple” means “statistically significant”
LOC and time-to-implement measurements are stupid:
● Not transferable to other developers● Only rough indicator of complexity
Some Data
Plan
$1 000 000
US$1 000 000
Time to Implement
Initial Expectations
“This’ll be easy I’ll whip it up in a weekend.”
“You don’t understand the power of the built-in
admin application.”
Rails Django 0.00
5.00
10.00
15.00
20.00
25.00
30.00
Hours to Implement
HTML Prototype
Rails Django 0.00
5.00
10.00
15.00
20.00
25.00
30.00
Hours to Implement
Develop Test data HTML Prototype
Rails Django 0.00
5.00
10.00
15.00
20.00
25.00
30.00
Hours to Implement
Project set up Develop Test data HTML Prototype
Rails Django 0.00
5.00
10.00
15.00
20.00
25.00
30.00
Hours to Implement
Models Project set up Develop Test data HTML Prototype
TagBook
Reading
Reader n m
nn
11
Rails Django 0.00
5.00
10.00
15.00
20.00
25.00
30.00
Hours to Implement
Models Project set up Develop Test data HTML Prototype
Rails Django 0.00
5.00
10.00
15.00
20.00
25.00
30.00
Hours to Implement
Home page Models Project set up Develop Test data HTML Prototype
Rails Django 0.00
5.00
10.00
15.00
20.00
25.00
30.00
Hours to Implement
Basic pages Home page Models Project set up Develop Test data HTML Prototype
Rails Django 0.00
5.00
10.00
15.00
20.00
25.00
30.00
Hours to Implement
Admin pages Basic pages Home page Models Project set up Develop Test data HTML Prototype
Rails Django 0.00
5.00
10.00
15.00
20.00
25.00
30.00
Hours to Implement
Amazon interface Admin pages Basic pages Home page Models Project set up Develop Test data HTML Prototype
Rails Django 0.00
5.00
10.00
15.00
20.00
25.00
30.00
Hours to Implement
Data loading code Amazon interface Admin pages Basic pages Home page Models Project set up Develop Test data HTML Prototype
Rails Django 0.00
5.00
10.00
15.00
20.00
25.00
30.00
Hours to Implement
Test, tidy Data loading code Amazon interface Admin pages Basic pages Home page Models Project set up Develop Test data HTML Prototype
Rails Django 0.00
5.00
10.00
15.00
20.00
25.00
30.00
Hours to Implement
Test, tidy Data loading code Amazon interface Admin pages Basic pages Home page Models Project set up Develop Test data HTML Prototype
26:46
16:36
Rails Django 0.00
5.00
10.00
15.00
20.00
25.00
30.00
Hours to Implement
Test, tidy Data loading code Amazon interface Admin pages Basic pages Home page Models Project set up Develop Test data HTML Prototype
Admin PagesAdmin Pages26:46
16:36
Rails Django 0.00
5.00
10.00
15.00
20.00
25.00
30.00
Hours to Implement - without Admin
Test, tidy Data loading code Amazon interface Basic pages Home page Models Project set up Develop Test data HTML Prototype
18:21
15:39
Lines of Code
Rails Django0
100
200
300
400
500
600
700
800
Lines of Code
Model
Rails Django0
100
200
300
400
500
600
700
800
Lines of Code
View/ControllerModel
Rails Django0
100
200
300
400
500
600
700
800
Lines of Code
YAML data loading View/ControllerModel
readers.yml
# Reader test dataBen: id: 1 username: benj72 fullname: Ben Askins bio: Eats books for breakfastAlan: id: 2 username: agreen fullname: Alan Green bio: Fond of snakesFred: id: 3 username: fred fullname: Fred Wilkins bio: Loves a good romantic thriller
Rails Django0
100
200
300
400
500
600
700
800
Lines of Code
YAML data loading View/ControllerModel
Rails Django0
100
200
300
400
500
600
700
800
Lines of Code
Authentication YAML data loading View/ControllerModel
Rails Django0
100
200
300
400
500
600
700
800
Lines of Code
Schema Migration Authentication YAML data loading View/ControllerModel
Rails Django0
100
200
300
400
500
600
700
800
Lines of Code
HTML Helpers/ Template tags Schema Migration Authentication YAML data loading View/ControllerModel
Rails Django0
100
200
300
400
500
600
700
800
Lines of Code
Templates HTML Helpers/ Template tags Schema Migration Authentication YAML data loading View/ControllerModel
● Hand-coded admin application
● Concise
● Quicker● Slightly less code
Database
Web Server
Routes View
Controller
Model
Browser
Database
Web Server
urls.py Template
View
Model
Browser
Rails Django
Database
Web Server
Routes View
Controller
Model
Browser
Database
Web Server
urls.py Template
View
Model
Browser
Rails Django
ActionController::Routing::Routes.draw do |map|
map.connect '', :controller => "home"
# restful resources map.resources :books do |books| books.resources :readings end map.resources :readers do |readers| readers.resources :reader_images end map.resources :tagsend
# Some imports herefrom hrproj.hr import views
urlpatterns = patterns('',
(r'^$', views.index),
(r'^readers/$', views.reader_list), (r'^tags/$', views.tag_list), (r'^books/$', views.book_list),
(r'^readers/(?P<username>.*)/$', views.reader_detail), (r'^tags/(?P<slug>.*)/$', views.tag_detail), (r'^books/(?P<slug>.*)/$', views.book_detail),)
URL Configuration
/books/hitchhikers-guide-to-the-galaxy
Database
Web Server
Routes View
Controller
Model
Browser
Database
Web Server
urls.py Template
View
Model
Browser
Rails Django
Controller / View Function
class BooksController < ApplicationController before_filter :find_book
def show @reading_paginator, @readings = paginate :readings, :conditions => ["book_id = ?", @book.id] end
private def find_book @book = Book.find_by_title(params[:id]) end
end
def book_detail(request, slug): book = get_object_or_404(Book, slug=slug) queryset = ReadingOccasion.objects \ .filter(book=book) \ .order_by('finished') return standard_view( request, queryset, 'book_detail.html', 'readingoccasion', book=book)
Database
Web Server
Routes View
Controller
Model
Browser
Database
Web Server
urls.py Template
View
Model
Browser
Rails Django
class ReadingOccasion(models.Model): reader = models.ForeignKey(Reader) book = models.ForeignKey(Book, edit_inline=models.STACKED,
num_in_admin=1) finished = models.DateField( core=True) reading_time = models.FloatField(
max_digits=5,decimal_places=2,
core=True, blank=True) notes = models.TextField(
maxlength=2000, blank=True)
class Reading < ActiveRecord::Base belongs_to :book belongs_to :readerend
class ReadingOccasion(models.Model): reader = models.ForeignKey(Reader) book = models.ForeignKey(Book, edit_inline=models.STACKED,
num_in_admin=1) finished = models.DateField( core=True) reading_time = models.FloatField(
max_digits=5,decimal_places=2,
core=True, blank=True) notes = models.TextField(
maxlength=2000, blank=True)
class Reading < ActiveRecord::Base belongs_to :book belongs_to :readerend
Schema evolution
class CreateReadings < ActiveRecord::Migration def self.up create_table :readings do |t| t.column "book_id", :integer t.column "reader_id", :integer t.column "date_read", :datetime t.column "reading_time", :integer t.column "notes", :text end end
def self.down drop_table :readings endend
Schema is Versioned
Django DB evolution
● Drop database tables● Re-create tables
manage.py syncdbpython yaml/load_data.py
● In production, you write migration DDL by hand
Database
Web Server
Routes View
Controller
Model
Browser
Database
Web Server
urls.py Template
View
Model
Browser
Rails Django
books/show.rhtml:<%= render :partial => 'readings/list', :locals => {:key_field => "Reader"} %>
readings/_list.rhtml:<tbody> <%= render :partial => 'readings/reading', :collection => @readings, :locals => {:key_field => key_field} %></tbody>
readings/_reading.rhtml:<tr> <td class="name_col"> <% if key_field == "Book" %> <%= link_to reading.book.title, book_url(reading.book) %> <% else %> <%= link_to reading.reader.fullname, reader_url(reading.reader) %> <% end %> </td> <td class="date_col"> <%= reading.date_read_for_display %> </td> <td class="num_col"> <%= reading.reading_time %> </td> <td><%= reading.notes %></td></tr>
book_detail.html:<tbody>{% for ro in readingoccasion_list %} <tr> <td class="name_col"> <a href="{{ ro.reader.get_absolute_url }}"> {{ ro.reader.name }} </a> </td> <td class="date_col"> {{ ro.finished|date:"j M Y" }} </td> <td class="num_col"> {{ ro.reading_time }} </td> <td>{% firstof ro.notes "-" %}</td> </tr>{% endfor %}</tbody>
View / Template
readers/show.rhtml:<%= render :partial => 'readings/list', :locals => { :key_field => "Book" } %>
reader_detail.html:<tbody>{% for ro in readingoccasion_list %} <tr> <td class="name_col"> <a href="{{ ro.book.get_absolute_url }}"> {{ ro.book.title }} </a> </td> <td class="date_col"> {{ ro.finished|date:"j M Y" }} </td> <td class="num_col"> {{ ro.reading_time }} </td> <td>{% firstof ro.notes "-" %}</td> </tr>{% endfor %}</tbody>
View / Template
And the other bits
Django Admin application
● Can save a lot of time● Good looking result● Does simple CRUD quite wellbut...● Only does simple CRUD● Only does simple relationships ● Security not fine-grained ● Not intended for public-facing pages
AJAX
page.visual_effect :fade, dom_id(@tag)page.replace_html “feedback”, “Tag Deleted”page.visual_effect :appear, “feedback”, :queue => :endpage.visual_effect :fade, “feedback”, :queue => :end
Rails Django
0123456789
1011
Books on Amazon
Ruby Ruby on Rails Python Django0
10
20
30
40
50
60
70
80
90
100
110
120
Jobs on seek.com.au
History
● Began Oct 2003● DHH
– in reaction to PHP● Extracted from
Basecamp● Released: July 2004● 1.0 shipped Dec 2005
– Latest is 1.1.6
● Began Fall 2003● Adrian and Simon
– “ditched” PHP● Extracted from
ljworld.com● Released: July 2005● 1.0 not yet shipped
– Latest is 0.95
Conclusion
Already using Rails?
Already using Rails?
Already using Django?
Already using Django?
Already know Ruby?
Already know Ruby?
Already know Python?
Already know Python?
Private admin pages?
Private admin pages?
Simple AJAX?
Simple AJAX?
Non-programming web designers?
Non-programming web designers?
Evolving Schema?
Evolving Schema?
Maturity
Maturity – product,community, and market
Maturity – product,community, and market
Concise or Explict?
Concise Explicit
Still can’t choose?
Thanks!
With thanks to
● Photos– Sad puppy:
http://www.flickr.com/photos/sookie/108356632/● Software
– David A. Wheeler’s Sloccount● http://www.dwheeler.com/sloccount/
– HTML Template by Andreas Viklund● All of the paper reviewers● Our bosses:
– Cirrus Technologies– Karen Askins
● “The Builders of Basecamp”– http://www.oreillynet.com/pub/a/network/2005/03/10/basecamp.html
● Snakes and Rubies presentation– http://video.google.com/videoplay?docid=2939556954580527226
● Django FAQ– http://www.djangoproject.com/documentation/faq/
Why Comparing?
Lots of interest in these two frameworks
Similar in some ways
Different in others
How to choose between them?
This is some Ruby code This is some Python code
Bonus Material
def standard_view(request, queryset, template_name, template_object_name, **extra_context): """ Wrapper around the object_list generic view. """ return object_list(request, queryset=queryset, allow_empty=True, template_name=template_name, template_object_name=template_object_name, page=get_page(request), paginate_by=PAGE_SIZE, extra_context=extra_context)
def get_page(request): """ Determines the current page number. """ return int(request.GET.get('page', 1))
standard_view
Rails Django 0.00
5.00
10.00
15.00
20.00
25.00
30.00
Hours to Implement
Test, tidy Data loading code Amazon interface Admin pages Basic pages Home page Models Project set up Develop Test data HTML Prototype
20:40
10:30