switch



Choosing a MVC Framework

August 23, 2010 at 1:45 pm, Category: Reviews, Web Development, by admin

If you have built a website of any decent size, you will at some point have needed to separate content, data and logic; this is achieved by using a framework that uses tiered development model which is sometimes coined as MVC (Model/View/Controller).

In this article I will look into the differences between CakePHP (our PHP based MVC framework of choice) and Ruby On Rails.

Ruby on Rails is one of the precursors, if not the precursor to the new trendy development terms, and is still on the edge of innovation. With important features such as migrations, lazy loading, and a plethora of plugins; (called Gems in the Ruby) which save rewrites of commonly requested website features.

Creating a weblog in 15 minutes with Rails 2 from Matthew Schultz on Vimeo.

CakePHP started as a bit of a copy of Ruby on Rails for PHP rather than Ruby, but has come into its own with “cake baking”, helpers and prolific availability of web hosting services and PHP developers in the field.

Creating a blog in CakePHP

Django is a bit of an underdog, but it has very powerful features. It inherits these from the Python language it’s based on. This makes it a very robust middleware system, with virtually automatic admin panelling backend, that has pre-existing knowledge of user roles. It also has a templating system separate to the Python language itself which is easy for designers to understand.

Django Beginner Tutorial Part I from programmersbook.com on Vimeo.

What I will do now is compare how the code looks in the Models, Views and Controllers (in Django they are called Models, Views and Templates).

All three have different approaches to pushing changes to a database.

CakePHP has a pull system which means you need to create the database first then create an app around it (however schemas are now available, since version 1.3). The tool to do this is called “cake bake” which is a command-line program which guides you through the process through easy menus and prompts.

Rails has Generators which are scripts designed to create code for you. For example “script/generate scaffold” will generate a very basic application based on the parameters that you supply it. This can take a while to used to, but will be a benefit to the advanced designer. “script/generate model” will take parameters to a new database model and will create migration files to be shared across multiple developers and “script/generate migration” will manage changes to a database within files called migration files. This is very handy for coding in teams when working on multiple test environments.

Django has the ability to design models directly in a Python file, so there is no need for migrations. The model files can be split into different files with a simple “import filename” command, the whole database structure is defined within django itself as opposed to the other two. Which is then synchronised with the database with a simple “sync” command.

Managing the Databases

In Ruby on Rails you will have an overall schema that is a modified using migrate files, eg.

ActiveRecord::Schema.define(:version => 20100721214414) do

  create_table "comments", :force => true do |t|
    t.string   "comment"
    t.integer  "task_id"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "user_id"
  end
end

and a migration file will look like so:

class AddUserIds < ActiveRecord::Migration
  def self.up
  add_column "projects", "user_id", :integer
  add_column "tasks", "user_id", :integer
  add_column "comments", "user_id", :integer
  end

  def self.down
  end
end

In CakePHP, it pull from the database so you will have to create tables and fields using your favourite SQL editor, then bake the models around it. As previously mentioned, schema’s are available to use from version 1.3 onwards.

Now in Django, there is just one type of file; they are standard python scripts. You can make any changes to those files, and then sync the files into the database. This is a basic Django model:

class Contact(models.Model):
  forename = models.CharField(max_length=50)
  surname = models.CharField(max_length=50)
  date_added = models.DateTimeField(default=datetime.now)

  def __unicode__(self):
    return u'%s %s' % (self.forename, self.surname)

How the Models look

In Ruby on Rails:

class Comment < ActiveRecord::Base
  belongs_to :task
  belongs_to :user
end

In CakePHP:


class Category extends AppModel {
	var $name = 'Category';
	var $displayField = 'category';

	var $hasMany = array(
        'Tool' => array(
            'className' => 'Tool',
            'foreignKey' => 'category_id',
            'conditions' => '',
            'fields' => '',
            'order' => ''
        )
	);
}

In Django the database definitions and models are the same thing.

How the Controllers look

In Ruby on Rails:

class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def create
    @user = User.new(params[:user])
    if @user.save
      flash[:notice] = "Registration successful"
      redirect_to root_url
    else
      render :action => 'new'
    end
  end

  def edit
    @user = current_user
  end

  def update
    @user = current_user
    if @user.update_attributes(params[:user])
      flash[:notice] = "Successfully updated profile."
      redirect_to root_url
    else
      render :action => 'edit'
    end
  end
end

In CakePHP:

class CategoriesController extends AppController {

	var $name = 'Categories';

	function index() {
		$this->Category->recursive = 0;
		$this->set('categories', $this->paginate());
	}

	function view($id = null) {
		if (!$id) {
			$this->Session->setFlash(__('Invalid category', true));
			$this->redirect(array('action' => 'index'));
		}
		$this->set('category', $this->Category->read(null, $id));
		$this->set('children', $this->Category->children($id));
	}

	function add() {
		if (!empty($this->data)) {
			$this->Category->create();
			if ($this->Category->save($this->data)) {
				$this->Session->setFlash(__('The category has been saved', true));
				$this->redirect(array('action' => 'index'));
			} else {
				$this->Session->setFlash(__('The category could not be saved. Please, try again.', true));
			}
		}
		$this->set('parents', $this->Category->find('list'));
	}

	function edit($id = null) {
		if (!$id && empty($this->data)) {
			$this->Session->setFlash(__('Invalid category', true));
			$this->redirect(array('action' => 'index'));
		}
		if (!empty($this->data)) {
			if ($this->Category->save($this->data)) {
				$this->Session->setFlash(__('The category has been saved', true));
				$this->redirect(array('action' => 'index'));
			} else {
				$this->Session->setFlash(__('The category could not be saved. Please, try again.', true));
			}
		}
		if (empty($this->data)) {
			$this->data = $this->Category->read(null, $id);
		}
		$this->set('parents', $this->Category->find('list'));
	}

	function delete($id = null) {
		if (!$id) {
			$this->Session->setFlash(__('Invalid id for category', true));
			$this->redirect(array('action'=>'index'));
		}
		if ($this->Category->delete($id)) {
			$this->Session->setFlash(__('Category deleted', true));
			$this->redirect(array('action'=>'index'));
		}
		$this->Session->setFlash(__('Category was not deleted', true));
		$this->redirect(array('action' => 'index'));
	}
}

In Django:

It is called a “view” in Django but is essentially the same as a CakePHP and Rails controller.

from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.http import Http404
from nublue.servaliste.models import Domain, Machine
from django.core import serializers

# Create your views here.

def index(request):
  domains = Domain.objects.all()

  return render_to_response("domains/index.html", {'domains':domains})

def detail(request, domain_id):
  try:
    dom = Domain.objects.get(pk=domain_id)
  except Domain.DoesNotExist:
    raise Http404
  return render_to_response("domains/detail.html", {'domain': dom})

How the Views look

In Ruby on Rails:

<h1>New todo</h1>

<% form_for(@todo) do |f| %>
  <%= f.error_messages %>
	<%= f.text_field :name %>
  <p>
    <%= f.submit 'Create' %>
  </p>
<% end %>

<%= link_to 'Back', todos_path %>

In CakePHP:

<div class="login">
<h2>Login</h2>
    create('User', array('action' => 'login'));?>
        input('username');?>
        input('password');?>
        submit('Login');?>
    end(); ?>
</div>

In Django:

{% if latest_poll_list %}
    <ul>
    {% for poll in latest_poll_list %}
        <li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

As you can see from the view examples, Ruby fits in nicely into its view templates without detracting from the presentation code, but still allowing for the underlying power of the Ruby language.

CakePHP, is back to the normal way of encoding PHP into HTML which is pretty ugly when you need more complexity. Also, because the views support PHP it can become tempting to put too much logic into views themselves, rather than putting it in the controllers.

If you have a look at Django’s templating language, you will notice that it isn’t in fact python at all. This was needed, as Python is a very strict language as even indentation matters when you are writing code. If you are a PHP coder you will soon realise that mixing HTML and PHP together can lead to very messed up indentation. It is also a pretty powerful templating language, but does what it says on the tin; it presents the information that was passed from the view/controller logic.

Where to find out more?

For CakePHP go to CakePHP Book, CakePHP Questions and also cake benefits from being a better way of organising PHP and isn’t completely different language from the underlying framework. Therefore php.net is still the definitive guide on how to code with PHP.

Django has great documentation and plenty of video tutorials on Vimeo and on YouTube.

Ruby on Rails has RailsGuides, a rails specific screencast site called RailsCasts where everthing is covered with video tutorials and code snippets.

Who can I chat to if I need help?

Well all three frameworks have IRC channels where people will be willing to help you out if you ask the right questions, as always try and Google it before you ask. Some channels can be found on freenode.net. There is #cakephp (currently 175 people online), #rubyonrails (currently 492 currently online) and #django (440 people currently online).

We are always interested in your suggestions, and comments. Let us know what you think of the frameworks and which one(s) you’d recommend.

Choosing an MVC framework
  • Allan

    Probably would have been more useful to have compared the same code in each framework rather than thee different applications …

  • Seppo

    What’s the editor/IDE? Looks nice..

  • NuBlue

    Hi Seppo, it is actually a plugin we use in WordPress called SyntaxHighlighter Evolved.

Our Client Line Up

Terms and Policies: Privacy Policy | Terms and Conditions | Environmental Policy | Equal Opportunities Policy | Sitemap
© NuFuture Ltd 2005-2010. Company No: 05523340  |  VAT No: 865 6930 80  |  InfoLab21, Lancaster, Lancashire, UK