XP on Rails Extreme Programming Blog

4Mar/112

How to send email asynchronously using Devise and Rails3

ORIGINAL POST

Hello everyone.

I’d show a workaround to send email asynchronously using Devise and Rails3.

Suppose we have already up and running our application with Devise and delayed_job correctly installed.

A first attempt was to add in config/initializers the following file (devise_async.rb):

#devise_async.rb
module Devise
  module Models
    module Confirmable
      handle_asynchronously :send_confirmation_instructions
    end

    module Recoverable
      handle_asynchronously :send_reset_password_instructions
    end

    module Lockable
      handle_asynchronously :send_unlock_instructions
    end
  end
end

This workaround has worked in part: the send method has been properly enqueued in the database, but when delayed_job tries to fire the job, the following error is raised:

User#send_confirmation_instructions_without_delay failed with NoMethodError: undefined method 'send_confirmation_instructions_without_delay' for #<User:0x000000032f87c8> - 1 failed attempts
[Worker(host:stefano-desktop pid:13153)]

As you can see, the job is trying to call the wrong send method: send_confirmation_instructions_without_delay.

At this point, I’ve implemented an even more dirty hack, overriding Devise’e methods using the syntax specified by intridea to send emails in the background:

#devise_async.rb
module Devise
  module Models
    module Confirmable
      # Send confirmation instructions by email
      def send_confirmation_instructions
        generate_confirmation_token! if self.confirmation_token.nil?
        ::Devise.mailer.delay.confirmation_instructions(self)
      end
    end

    module Recoverable
      # Resets reset password token and send reset password instructions by email
      def send_reset_password_instructions
        generate_reset_password_token!
        ::Devise.mailer.delay.reset_password_instructions(self)
      end
    end

    module Lockable
      # Send unlock instructions by email
      def send_unlock_instructions
        ::Devise.mailer.delay.unlock_instructions(self)
      end
    end
  end
end

This solution, however, is too tied to the implementation of Devise and is therefore not a good one (besides being really really dirty).

The latest idea, which represents the solution I’ve used is implemented as follows: use the alias_method in this way:

#devise_async.rb
module Devise
  module Models
    module Confirmable
      alias_method :send_confirmation_instructions_without_delay, :send_confirmation_instructions
      handle_asynchronously :send_confirmation_instructions
    end

    module Recoverable
      alias_method :send_reset_password_instructions_without_delay, :send_reset_password_instructions
      handle_asynchronously :send_reset_password_instructions
    end

    module Lockable
      alias_method :send_unlock_instructions_without_delay, :send_unlock_instructions
      handle_asynchronously :send_unlock_instructions
    end
  end
end

This latest hack works a treat; is not the best but let you send mail with Devise asynchronously.

If you have any better solutions, do not hesitate to share!

25Feb/110

How to implement two dropdowns dependent on each other using Django and jQuery

ORIGINAL POST

Hello everyone.

With today’s article I want to show how to implement two dropdowns dependent on each other using Django and jQuery.

Suppose we have a 1-N relationship between car brands and car models: we want to show the list of brands in the first dropdown; then once you have selected a brand, the second dropdown will show a list of filtered models for that brand.

Suppose we have our models defined as follows:

#models.py
class VehicleBrand(models.Model):
    description = models.CharField(max_length=100)
    code = models.SlugField(primary_key=True)

class VehicleModel(models.Model):
    description = models.CharField(max_length=100)
    code = models.SlugField(primary_key=True)
    brand = models.ForeignKey(VehicleBrand)

Let’s write a templatetag that will be included in our templates:

#templatetags.py
from models import VehicleBrand

from django import template

register = template.Library()

@register.inclusion_tag("brand_model_select.html")
def brand_model_select():
    brand_list = VehicleBrand.objects.all()
    return {'brand_list' : brand_list}

As you can see, the templatetag requires a support html template, defined as follow:

<!-- brand_model_select.html -->
<form action="" method="get" accept-charset="utf-8">
    <select name="brand" id="brand">
        <option value="Z">Select a brand</option>
        {% for brand in brand_list %}
            <option value="{{ brand.code}}">{{ brand.description }}</option>
        {% endfor %}
    </select>
    <select name="model" id="model" disabled="true">
        <option>Select a model</option>
    </select>
</form>
<script>
    $(document).ready(
                     function() {
                         $("select#brand").change(function() {
                             if ($(this).val() == 'Z') {
                                 $("select#model").html("<option>Select a model</option>");
                                 $("select#model").attr('disabled', true);
                             }
                             else {
                                 var url = "/brand/" + $(this).val() + "/all_json_models";
                                 var brand = $(this).val();
                                 $.getJSON(url, function(models) {
                                     var options = '<option value="Z">Select a model</option>';
                                     for (var i = 0; i < models.length; i++) {
                                        options += '<option value="' + models[i].pk + '">' + models[i].fields['description'] + '</option>';
                                     }
                                     $("select#model").html(options);
                                     $("select#model option:first").attr('selected', 'selected');
                                     $("select#model").attr('disabled', false);
                                 });
                             }
                         });


                         $("select#model").change(function(vent) {
                             if ($(this).val() == -1) {
                                 return;
                             }
                             myAwesomeFunctionToCallWhenAModelIsSelected();
                         });
                     });
    }

</script>

Please note that once a brand is selected, the following url will be invoked via Ajax request:
/brand/”selected_brand_code”/all_json_models

then we need to define a view to handle this request:

#views.py
def all_json_models(request, brand):
    current_brand = VehicleBrand.objects.get(code=brand)
    models = VehicleModel.objects.all().filter(brand=current_brand)
    json_models = serializers.serialize("json", models)
    return HttpResponse(json_models, mimetype="application/javascript")

and in urls.py:

#urls.py
...
(r'^brand/(?P<brand>[-\w]+)/all_json_models/$', 'all_json_models'),

Finally, the javascript method myAwesomeFunctionToCallWhenAModelIsSelected() will be invoked when a model will be selected.

Filed under: Development No Comments
31Jan/110

How to create a custom feed in Django using the Syndication Feed Framework

ORIGINAL POST

Hello everyone.

In this article I will show you how to create a custom feed in Django, using the Django Syndication Feed Framework 1.2 or higher.

I’ve had to create an XML with some more tags for each item in the feed.
In particular, in addition to the usual tags present in an RSS feed, I’ve added the

<short_description/> 

and

<image/>

tags.

Reading the official documentation of the framework, it is recommended to create a custom feed generator, but the process is not very clear.

Let’s see step by step how to fix everything.

First we create a custom feed generator.

This generator must create the same XML that would produce the framework’s default generator and for each item in the list it will add the new tags.

class CustomFeedGenerator(Rss201rev2Feed):
    def add_item_elements(self, handler, item):
        super(CustomFeedGenerator, self).add_item_elements(handler, item)
        handler.addQuickElement(u"image", item['image'])
        handler.addQuickElement(u"short_description", item['short_description'])

We see that the generator calls the method add_item_elements(handler, item) of its superclass and then adds new XML tags for each item.
Note that the values that will be inserted in the image and short_description tags must be present in the item dictionary passed as argument.

So let’s create our CustomFeed class that inherits from Feed class and see how to tell it to use the CustomFeedGenerator and how to insert the new values in the item dictionary.

class CustomFeed(Feed):

    feed_type = CustomFeedGenerator

    def title(self, obj):
        return u"My amazing feed"

    def description(self, obj):
        return u"My feed description"

    def link(self, obj):
        return "http://%s" % obj.get_absolute_url()

    def item_extra_kwargs(self, obj):
        """
        Returns an extra keyword arguments dictionary that is used with
        the `add_item` call of the feed generator.
        Add the 'content' field of the 'Entry' item, to be used by the custom feed generator.
        """

        return { 'image': obj.get_picture().get_medium_url() if obj.get_picture() else "",
                 'short_description' : obj.get_preview(),}

CustomFeed is very similar to the various feeds that we are accustomed. The only difference is represented by the statement of the type of feed

feed_type = CustomFeedGenerator

and by the method

item_extra_kwargs

able to append any new values in the item dictionary, obtaining the desired result.

Tagged as: , No Comments
6Oct/100

How to install PostgreSQL and psycopg2 on Osx Snow Leopard

ORIGINAL POST

Hello everyone.

In my last post I showed how to install MySQL from source on Osx.
Among the many comments received, some of them suggested me to use homebrew

I recommend everyone to use this tool in order to easily install several unix packages on OSX.

Among the packages that can be installed there’s also PostgreSQL, the subject of today’s post.

If you install PostgreSQL via homebrew, maybe have a look at this post

This post is instead directed to those who are willing to install the database from source in /usr/local/postgresql-8.4.4

Step 1: Set the $PATH environment variable

Open a terminal and set the $PATH environment variable in order to link the correct folders in /usr/local/

mate ~/.profile

Add, if it does not exist, this line at the bottom of the .profile file:

export PATH="~/bin;/usr/local/bin:/usr/local/sbin:/usr/local/mysql/bin:/usr/local/pgsql/bin:$PATH"

and reload the $PATH in this way:

source ~/.profile

To verify that our $PATH contains the paths set above, type the following command:

echo $PATH

Step 2: Download PostgreSQL

Create a new folder to download the sources and compile them:

mkdir ~/src
cd ~/src

Download the latest version available at the time of writing this tutorial:

curl -O http://ftp2.it.postgresql.org/mirrors/postgres/source/v8.4.4/postgresql-8.4.4.tar.gz

Step 3: Compile and Install

Build and install PostgreSQL with the following commands:

tar -zvxf postgresql-8.4.4.tar.gz
rm postgresql-8.4.4.tar.gz
cd postgresql-8.4.4
./configure --prefix=/usr/local/postgresql-8.4.4
ARCH=x86_64 CFLAGS="-arch x86_64" LDFLAGS="-arch x86_64" make
make install

Create a symbilic link, used before in the $PATH

ln -s /usr/local/postgresql-8.4.4 /usr/local/pgsql
mkdir /usr/local/pgsql/data/

Create now a postgres user, owner of the server:

dscl localhost create /Local/Default/Users/postgres
dscl localhost create /Local/Default/Users/postgres PrimaryGroupID 0
dscl localhost create /Local/Default/Users/postgres UniqueID 75
dscl localhost create /Local/Default/Users/postgres UserShell /bin/bash
dscl localhost passwd /Local/Default/Users/postgres
dscl localhost create /Local/Default/Users/postgres NFSHomeDirectory /var/home/postgres
mkdir -p /var/home/postgres
chown -Rf postgres:postgres /var/home/postgres
dscl localhost create /Local/Default/Groups/postgres
dscl localhost create /Local/Default/Groups/postgres UniqueID 75
dscl localhost append /Local/Default/Groups/postgres GroupMembership postgres

And let’s give him read permissions over the installation directory:

chown -R postgres /usr/local/postgresql-8.4.4/

In a new console, log in as postgres and start the server:

su - postgres
/usr/local/pgsql/bin/initdb -E UTF8 -D /usr/local/pgsql/data/
/usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data/ -l /usr/local/pgsql/data/postgresql.log start

If the server is started correctly, we can create our test database:

createdb test
psql test

Now delete unnecessary folders created when creating the user:

sudo su
rm -rf /var/home
dscl localhost delete /Local/Default/Users/postgres NFSHomeDirectory
dscl localhost passwd /Local/Default/Users/postgres
exit

Then we can create scripts to start and stop the PostgreSQL server using the command line.

We create a bin folder in our home and the following file, also giving execute permissions:

mkdir bin
touch pgsqlscript
chmod +x pgsqlscript

Edit the file you’ve just created by inserting the following body:

#!/bin/bash

start()
{
        echo -n "Starting PostgreSQL server"
        sudo su postgres -c '/usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data/ -l /usr/local/pgsql/data/postgresql.log start'
       
        return
}

stop()
{
        echo -n "Stopping PostgreSQL server"
        sudo su postgres -c '/usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data/ stop'
        return
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    *)
        echo "Usage: {start|stop|restart}"
        exit 1
        ;;
esac
exit $?

At this point you can start the server by typing “pgsqlscript start” in the console. To stop the server just type “pgsqlscript stop”.

Step 4: Install Ruby PostgreSQL drivers

Just install the pg gem to have access to the database.

gem install pg

Step 5: Install Python drivers for PostgreSQL

Download the psycopg2 package

cd ~/src
curl -O http://initd.org/psycopg/tarballs/psycopg2-2.2.2.tar.gz
tar xzfv psycopg2-2.2.2.tar.gz
cd psycopg2-2.2.2

and modify the setup.cfg file with this one:

[build_ext]
define=PSYCOPG_EXTENSIONS,PSYCOPG_NEW_BOOLEAN,HAVE_PQFREEMEM,HAVE_PQPROTOCOL3

# PSYCOPG_EXTENSIONS enables extensions to PEP-249 (you really want this)
# PSYCOPG_DISPLAY_SIZE enable display size calculation (a little slower)
# HAVE_PQFREEMEM should be defined on PostgreSQL >= 7.4
# HAVE_PQPROTOCOL3 should be defined on PostgreSQL >= 7.4
# PSYCOPG_DEBUG can be added to enable verbose debug information
# PSYCOPG_OWN_QUOTING can be added, but it is deprecated (will go away in 2.1)
# PSYCOPG_NEW_BOOLEAN to format booleans as true/false vs 't'/'f'

# Set to 1 to use Python datatime objects for default date/time representation.
use_pydatetime=1

# If the build system does not find the mx.DateTime headers, try
# uncommenting the following line and setting its value to the right path.
#mx_include_dir=

# For Windows only:
# Set to 1 if the PostgreSQL library was built with OpenSSL.
# Required to link in OpenSSL libraries and dependencies.
have_ssl=0

# Statically link against the postgresql client library.
static_libpq=0

# "pg_config" is the preferred method to locate PostgreSQL headers and
# libraries needed to build psycopg2. If pg_config is not in the path or
# is installed under a different name uncomment the following option and
# set it to the pg_config full path.
pg_config=/usr/local/pgsql/bin/pg_config

# If "pg_config" is not available, "include_dirs" can be used to locate
# postgresql headers and libraries. Some extra checks on sys.platform will
# still be done in setup.py.
# The next line is the default as used on psycopg author Debian laptop:
#include_dirs=/usr/local/lib

# Uncomment next line on Mandrake 10.x (and comment previous ones):
#include_dirs=/usr/include/pgsql/8.0:/usr/include/pgsql/8.0/server

# Uncomment next line on SUSE 9.3 (and comment previous ones):
#include_dirs=/usr/include/pgsql:/usr/include/pgsql/server

# If postgresql is installed somewhere weird (i.e., not in your runtime library
# path like /usr/lib), just add the right path in "library_dirs" and any extra
# libraries required to link in "libraries".
library_dirs=/usr/local/pgsql/lib
libraries=/usr/lib

At this point we can compile and install the package:

python setup.py install
Tagged as: , No Comments
13Sep/101

How to install MySQL and Rails on Osx Snow Leopard

ORIGINAL POST

Hello everyone.

These days I’ve bought a MacBook Pro with Osx Snow Leopard 64-bit pre installed.

Having to develop mainly in Rails and Django on MySQL and PostgreSQL, I’ve found some difficulties to install and properly configure all packages.

The main problems were due to the presence of 32bit libraries and other at 64bit. For example, Python or Ruby (already installed by default) were compiled at 32bit. Everything seems to work best, however, until you try to install the gem “mysql” or the eggs “psycopg2″ or “MySQL_python”.

These database drivers, having to be “compiled”, generate many problems of incompatibility between different architectures.

In this first tutorial, we’ll see how to install MySQL and Rails 3.0. In the next we’ll see how to proceed with Django and PostgreSQL.

The approaches taken by me are simply the result of googling and other online tutorials. So I’ll link every resource I’ve used.

Regarding the installation of MySQL, I’ve mainly followed the Hivelogic tutorial.

See below the key points that allowed a successful installation.

Step 1: Set the $PATH environment variable

Open a terminal and set the $PATH environment variable in order to link the correct folders in /usr/local/

mate ~/.profile

Add, if it does not exist, this line at the bottom of the .profile file:

export PATH="~/bin;/usr/local/bin:/usr/local/sbin:/usr/local/mysql/bin:$PATH"

and reload the $PATH in this way:

source ~/.profile

To verify that our $PATH contains the paths set above, type the following command:

echo $PATH

Step 2: Download MySQL

Create a new folder to download the sources and compile them:

mkdir ~/src
cd ~/src

Download the latest version available at the time of writing this tutorial:

curl -O http://mysql.mirrors.pair.com/Downloads/MySQL-5.1/mysql-5.1.47.tar.gz

Step 3: Compile and Install

Build and install MySQL with the following commands:

tar xzvf mysql-5.1.47.tar.gz
cd mysql-5.1.47
./configure --prefix=/usr/local/mysql --with-extra-charsets=complex \
--enable-thread-safe-client --enable-local-infile --enable-shared \
--with-plugins=innobase

make
sudo make install

At this point we create a mysql user and a default database.

cd /usr/local/mysql
sudo ./bin/mysql_install_db --user=mysql
sudo chown -R mysql ./var
cd ..

Then we can create scripts to start and stop the MySQL server using the command line.

We create a bin folder in our home and the following file, also giving execute permissions:

mkdir bin
touch mysqlscript
chmod +x mysqlscript

Edit the file you’ve just created by inserting the following body:

#!/bin/bash

start()
{
        echo -n "Starting MysSQL server"
        cd /usr/local/mysql ; sudo /usr/local/mysql/bin/mysqld_safe        
        return
}

stop()
{
        echo -n "Stopping MySQL server"
        cd /usr/local/mysql ; sudo /usr/local/mysql/bin/mysqladmin -u root -p shutdown
        return
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    *)
        echo "Usage: {start|stop|restart}"
        exit 1
        ;;
esac
exit $?

At this point you can start the server by typing “mysqlsript start” in the console. To stop the server just type “mysqlscript stop”.

We are now able to install Ruby on Rails. As mentioned at the beginning of the article, system Ruby is compiled at 32bit.
If you want to compile from source at 64bit and place it in /usr/local/ ruby just follow this tutorial.

Since it is my intention to use instead rvm, I’ll settle for a system level Ruby at 32bit and I prefer to compile every new virtual environment at 64bit (from this tutorial)

Therefore proceed as follows:

Step 1: Install rvm

Launch in a console this command and follow the instructions:

bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )

Step 2: Install Ruby 1.9.2

Type the following commands and verify that you have version 1.9.2 installed.

rvm install 1.9.2 -C --with-readline-dir=/opt/local,--build=x86_64-apple-darwin10
rvm 1.9.2
ruby -v

Step 3: Create a Rails3 gemset

Create a Rails3 gemset and activate it as default:

rvm use --create 1.9.2@rails3
rvm 1.9.2@rails3 --default

Step 4: Install Rails3 and database drivers for SQLite and MySQL

gem install sqlite3-ruby
env ARCHFLAGS="-arch x86_64" gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
gem install rails

In this tutorial we’ve then installed MySQL and Ruby 1.9.2 from source. Now that all the packages have been compiled to 64bit we should not find errors while installing other application’s gems.

30Aug/100

How to create multiple Django environments using virtualenv

ORIGINAL POST

Often we must work on various Django applications, each one dependent on different set of libraries.

For examples, we are working on a Django 1.1 project and and we need to start a new one with the latest version of the framework.

The best solution is to keep the various environments separate, in order to ensure that each project accesses only the libraries which it depends.

Python offers us virtualenv, a tool to create multiple isolated environments. Each environment is completely independent from the others and from the installed packages in system’s site-packages folder.

Let’s then see how to create a virtualenv and install the latest version of Django (today 1.2.1).

1- Install python-setuptools

The first thing to do is to install python-setuptools in order to have access to the command easy_install and to easly download packages. Alternatively, you can get the same results using the package pip.

Let us open a console and type the following commands:

stefano@stefano-laptop:~$ sudo apt-get install python-setuptools
Reading package lists... Done
Building dependency tree      
Reading state information... Done
python-setuptools is already the newest version.
0 upgraded, 0 newly installed, 0 to remove and 132 not upgraded.
stefano@stefano-laptop:~$

2- Install virtualenv

The second step is to install the package virtualenv using easy_install:

stefano@stefano-laptop:~$ sudo easy_install virtualenv
[sudo] password for stefano:
Searching for virtualenv
Reading http://pypi.python.org/simple/virtualenv/
Reading http://virtualenv.openplans.org
Best match: virtualenv 1.4.9
Downloading http://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.4.9.tar.gz#md5=c49067cab242b5ff8c7b681a5a99533a
Processing virtualenv-1.4.9.tar.gz
Running virtualenv-1.4.9/setup.py -q bdist_egg --dist-dir /tmp/easy_install-3D0IWT/virtualenv-1.4.9/egg-dist-tmp-xe4LRm
warning: no previously-included files matching '*.*' found under directory 'docs/_templates'
Adding virtualenv 1.4.9 to easy-install.pth file
Installing virtualenv script to /usr/local/bin

Installed /usr/local/lib/python2.6/dist-packages/virtualenv-1.4.9-py2.6.egg
Processing dependencies for virtualenv
Finished processing dependencies for virtualenv

3- Create the virtual environment

Once installed the package virtualenv we will need to create a space to host multiple environments. In my case, I’ve chose to create a directory in my home rather than in another writable folder in the filesystem.

stefano@stefano-laptop:~$ cd Progetti/Python/
stefano@stefano-laptop:~/Progetti/Python$
stefano@stefano-laptop:~/Progetti/Python$ mkdir virtualenvs
stefano@stefano-laptop:~/Progetti/Python$ cd virtualenvs/
stefano@stefano-laptop:~/Progetti/Python/virtualenvs$

Now we create the real virtualenv, called “Django-1.2-env. Note the argument added to the command virtualenv, –no-site-packages: so our virtual environment will have only a minimal set of libraries in his site-packages folder. We also note that all next commands will not need access as super user via sudo.

stefano@stefano-laptop:~/Progetti/Python/virtualenvs$ virtualenv --no-site-packages django-1.2-env
New python executable in django-1.2-env/bin/python
Installing setuptools............done.

4- Download Django in /tmp

Open a new console and download the tarball with the latest version of the framework Django. For simplicity, I’ve downloaded the package to /tmp.

stefano@stefano-laptop:~$ cd /tmp/
stefano@stefano-laptop:/tmp$ wget http://www.djangoproject.com/download/1.2.1/tarball/
--2010-08-28 11:20:58--  http://www.djangoproject.com/download/1.2.1/tarball/
Resolving www.djangoproject.com... 64.207.133.18
Connecting to www.djangoproject.com|64.207.133.18|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://media.djangoproject.com/releases/1.2/Django-1.2.1.tar.gz [following]
--2010-08-28 11:20:59--  http://media.djangoproject.com/releases/1.2/Django-1.2.1.tar.gz
Resolving media.djangoproject.com... 64.207.133.30
Connecting to media.djangoproject.com|64.207.133.30|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 6248006 (6.0M) [application/octet-stream]
Saving to: `Django-1.2.1.tar.gz'

100%[======================================>] 6,248,006    590K/s   in 12s    

2010-08-28 11:21:11 (523 KB/s) - `Django-1.2.1.tar.gz'
saved [6248006/6248006]

5- Installing Django in virtualenv

At this point, unpack Django and activate the virtualenv (via the command “source virtualenvdir/bin/activate”). Once activated virtualenv, we’ll find his name in the shell: (django-1.2-env)stefano@stefano-laptop

stefano@stefano-laptop:/tmp$ tar xzfv Django-1.2.1.tar.gz
stefano@stefano-laptop:/tmp/Django-1.2.1$ source /home/stefano/Progetti/Python/virtualenvs/django-1.2-env/bin/activate
(django-1.2-env)stefano@stefano-laptop:/tmp/Django-1.2.1$
(django-1.2-env)stefano@stefano-laptop:/tmp/Django-1.2.1$ python setup.py install

We verify here that Django is installed properly in the virtual site-packages:

stefano@stefano-laptop:~/Progetti/Python/virtualenvs/django-1.2-env$ ls lib/python2.6/site-packages/
django           easy-install.pth   setuptools-0.6c11-py2.6.egg
Django-1.2.1-py2.6.egg-info  pip-0.7.2-py2.6.egg  setuptools.pth

6- Create a new project

At this point, we can create a new project using the command django-admin.py as required by the framework.

(django-1.2-env)stefano@stefano-laptop:/tmp/Django-1.2.1$ cd /home/stefano/Progetti/Python/
(django-1.2-env)stefano@stefano-laptop:~/Progetti/Python$
(django-1.2-env)stefano@stefano-laptop:~/Progetti/Python$ django-admin.py startproject newdjangoapp
(django-1.2-env)stefano@stefano-laptop:~/Progetti/Python$ cd newdjangoapp/
(django-1.2-env)stefano@stefano-laptop:~/Progetti/Python/newdjangoapp$ ls
__init__.py  manage.py  settings.py  urls.py

In conclusion, we can say that virtualenv is an excellent solution to create environments fully independent and designed to accommodate each individual project. In this way, we avoid conflicts of libraries and have the opportunity to try new configurations without creating problems for other applications.

30Jul/100

Design Patterns in Ruby: Chain of Responsibility

ORIGINAL POST

Today’s post discusses the first of the behavioral pattern shown by the GoF, the chain of responsibility.

This pattern expects a series of commands to be executed and a set of objects capable to handle them.
Each of these “handler” objects can send the command to the next handler in the chain if it is not able to carry it out.
A mechanism also exists for adding new handler objects to the end of this chain.

To show this pattern, we take as example a real situation very familiar to web developers.

Suppose that the manager must deliver a new web project.

To realize the entire project should be conducted several heterogeneous activities such as design the user interface, develop the application, write the user manual, deploy the application.

The manager doesn’t have all required skills but he can rely on a pool of developers.

When the activity reaches a developer, this can solve it or, if he is unable to, send it to a colleague.
In this way a chain of responsibility is formed, where each actor specializes in solving only certain types of requests.

Let’s see how to carry out this scenario in Ruby.

Is therefore necessary that every element in the chain has the ability to “forward” the request to the next if he is not able to manage it.

So we create a module that defines this common logic and removes code duplication.

#models.rb
module Chainable

  def next_in_chain(link)
    @next = link
  end

  def method_missing(method, *args, &block)
    if @next == nil
      puts "This request cannot be handled!"
      return
    end
    @next.__send__(method, *args, &block)
  end
end

As you can see, the next_in_chain method provides the next element in the chain.
To meet demands that can not be managed, I’ve used the method_missing “pattern” : when the request can not be managed by the actor (e.g. the invoked method is not defined in the class), it will be forwarded to the next.

Now define the players of our example:

#models.rb
class WebManager
  include Chainable

  def initialize(link = nil)
    next_in_chain(link)
  end
 
  def deliver_application
    design_interface
    build_application
    write_documentation
    deploy_application
    puts "#{self.class.to_s}: Application delivered"
  end

end

class WebDeveloper
  include Chainable

  def initialize(link = nil)
    next_in_chain(link)
  end

  def build_application
    puts "#{self.class.to_s}: I'm building the application"
  end

  def deploy_application
    puts "#{self.class.to_s}: I'm deploying the application"
  end

end

class WebDesigner
  include Chainable

  def initialize(link = nil)
    next_in_chain(link)
  end

  def design_interface
    puts "#{self.class.to_s}: I'm designing the interface"
  end

end

class TechnicalWriter
  include Chainable

  def initialize(link = nil)
    next_in_chain(link)
  end

  def write_documentation
    puts "#{self.class.to_s}: I'm writing the documentation"
  end

end

At this point we simulate our chain by running the following code:

#main.rb
require 'models.rb'

provider = WebManager.new(WebDeveloper.new(WebDesigner.new(TechnicalWriter.new)))
provider.deliver_application
provider.make_support

and the output will be:

WebDesigner: I’m designing the interface
WebDeveloper: I’m building the application
TechnicalWriter: I’m writing documentation
WebDeveloper: I’m deploying the application
WebManager: Application delivered
This request cannot be handled!

In conclusion, the use of this pattern is useful when we deal with heterogeneous requests and we want to make sure that these are best handled by a specific handler.
It can also be used when we run commands in sequence, where each element forwards the coming command to the next handler.

An alternative to this pattern could be a decorator, able to add capacity to a specific handler. In this case a single handler will completely manage all requests.

In these first three articles of the series we have analyzed the first pattern shown by the GoF for each category.

In the coming articles I will no more follow the order set by the GoF but I’ll analyze the most useful patterns to address the most common needs.

Source code here

Previous posts from this series:
Design Patterns in Ruby: Introduction
Design Patterns in Ruby: Abstract Factory
Design Patterns in Ruby: Adapter

Filed under: Development No Comments
7Jul/101

Design Patterns in Ruby: Adapter

ORIGINAL POST

This second post of the series leaves for a moment the creational patterns and speaks about one of the most important structural pattern: the Adapter.

The purpose of an adapter is “to convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.”

Suppose therefore to have two classes, PalGame and NtscGame, that extend a superclass Game. These subclasses respectively expose two methods: play and run.

#models.rb
class Game
  attr_accessor :title
  def initialize(title)
    @title = title
  end
end

class PalGame < Game
  def play
    puts "I am the Pal version of #{@title} and I am running!"  
  end
end

class NtscGame < Game  
  def run
    puts "I am the NTSC version of #{@title} and I am running!"  
  end
end

We then subclass a Console class with PalConsole and NtscConsole. These two classes are expected to talk with, respectively, games of kind PalGame and NtscGame.

#models.rb
class Console
end

class PalConsole < Console
  def play_game(game)
    game.play  
  end
end

class NtscConsole < Console
  def run_game(game)
    game.run  
  end
end

How can see, the method play_game of a PalConsole will call the play method of the game, the NtscConsole instead will invoke the run method.

Our goal is to let a PalConsole to run games of kind NtscGame.

Below we’ll follow the line traced by the GoF and we’ll build an Adapter class that provides the play method needed by the PalConsole’s interface:

#adapters.rb
class NtscToPalAdatper
  attr_accessor :game
  def initialize(game)
    @game = game
  end
 
  def play
    @game.run  
  end  
end

As you can see, the adapter exposes a simple play method that calls the run method of the NTSCGame.

The following code:

#main.rb
require 'models.rb'
require 'adapters.rb'

console = PalConsole.new

final_fantasy = NtscGame.new("Final Fantasy")

adapter = NtscToPalAdatper.new(final_fantasy)

console.play_game(adapter)

will produce this output:
I am the NTSC version of Final Fantasy and I am running!

We see at this point some alternatives to further exploit the potential of Ruby.

One possibility is to take advantage of the Ruby’s “open classes”. The language makes possible to add methods to an already loaded class in this way:

#main2.rb
require 'models.rb'

console = PalConsole.new

class NtscGame < Game  
  def play
    run
  end
 
  # alternatively for this simple example we can define an alias:
  # alias play run
end

final_fantasy = NtscGame.new("Final Fantasy")

double_dragon = NtscGame.new("Double Dragon")

console.play_game(final_fantasy)

console.play_game(double_dragon)

As we can see, we’ve added at runtime the method play for a NtscGame game.

The above code produces the following output:
I am the NTSC version of Final Fantasy and I am running!
I am the NTSC version of Double Dragon and I am running!

Note however that with this solution we added the play method to the entire class NtscGame. All instances that are created will be equipped with the play method.
This type of action is very risky because it could not guarantee compatibility with other libraries, for example because of name clash.

Another alternative would be to use the “singleton classes”.
Ruby makes it possible to change a single instance of a class, by creating an anonymous class as its superclass that implements the new defined method.

There are several possibilities to implement these singleton classes. Let’s see in the following snippet some implementations.

#main3.rb
require 'models.rb'

console = PalConsole.new

#1 - creating a singleton class
final_fantasy = NtscGame.new("Final Fantasy")

def final_fantasy.play
  run  
end

console.play_game(final_fantasy)


#2 - adding methods opening the singleton class directly
winning_eleven = NtscGame.new("Winning Eleven")

class << winning_eleven
  def play
    run
  end
end

console.play_game(winning_eleven)


#3 - adding methods from a module
thunderforce = NtscGame.new("Thunderforce")

module Foo
  def play
    run
  end
end

thunderforce.extend(Foo)

console.play_game(thunderforce)


#4 - adding methods inside an instance_eval call
dragons_lair = NtscGame.new("Dragons Lair")

dragons_lair.instance_eval <<EOT
  def play
    run
  end
EOT

console.play_game(dragons_lair)

All implementations will provide the same type of output:
I am the NTSC version of Final Fantasy and I am running!
I am the NTSC version of Winning Eleven and I am running!
I am the NTSC version of Thunderforce and I am running!
I am the NTSC version of Dragons Lair and I am running!

In this post we have therefore seen the usefulness of this design patterns and how Ruby allows the developer to “leave” the classic implementation suggested in order to better take advantage of the potentiality of the language.

source code here

Previous posts from this series:
Design Patterns in Ruby: Introduction
Design Patterns in Ruby: Abstract Factory

21Jun/100

Design Patterns in Ruby: Abstract Factory

ORIGINAL POST

An abstract Factory provides a common interface for creating families of related objects together.
The client object does not bother to build objects directly, but it calls the methods provided by this common interface.

Below is showed one possible implementation of an abstract Factory and its concrete Factories that implement it.

Suppose we have two categories of games as a model classes:

#models.rb
class Game
  attr_accessor :title
  def initialize(title)
    @title = title
  end
end

class Rpg < Game
  def description
    puts "I am a RPG named #{@title}"
  end
end

class Arcade < Game
  def description
    puts "I am an Arcade named #{@title}"
  end
end

How we can see, both models derive from a common superclass Game.

Let’s define the Factories delegate to build these objects:

#factories.rb
module MyAbstractGameFactory
  def create(title)
    raise NotImplementedError, "You should implement this method"
  end
end

class RpgFactory
  include MyAbstractGameFactory
  def create(title)
    Rpg.new title
  end
end

class ArcadeFactory
  include MyAbstractGameFactory
  def create(title)
    Arcade.new title
  end
end

Note that we have defined the abstract factory (MyAbstractGameFactory) as a module: it defines the abstract method that must be implemented by the class that includes it.
RpgFactory and ArcadeFactory represent the two concrete factories responsible to build, respectively, Arcade and RPG games.

The code of a GameStore, that can provide games basing on the needs of the customer, will be defined as follows:

class GameStore
  def initialize(number_of_games, game_type)  
    if game_type == :rpg
      title = 'Final Fantasy'
      game_factory = RpgFactory.new
    elsif game_type== :arcade
      title = 'Double Dragon'
      game_factory = ArcadeFactory.new
    end
       
    @games = []
    number_of_games.times do |i|
      @games << game_factory.create("#{title} #{i+1}")
    end
  end
 
  def show_games
    @games.each {|game| game.description}
  end
end

At this point, launching the following file main.rb

#main.rb
require 'models.rb'
require 'factories.rb'
game_store = GameStore.new(2, :rpg)
game_store.show_games
game_store = GameStore.new(5, :arcade)
game_store.show_games

we’ll get the following output in console:

I am a RPG named Final Fantasy 1
I am a RPG named Final Fantasy 2
I am an Arcade named Double Dragon 1
I am an Arcade named Double Dragon 2
I am an Arcade named Double Dragon 3
I am an Arcade named Double Dragon 4
I am an Arcade named Double Dragon 5

At this point we can optimize our Factories in order to take advantage of the potential offered by Ruby:

#factories2.rb
class GameFactory
  include MyAbstractGameFactory
 
  def initialize(game_class)
    @game_class = game_class
  end
 
  def create(title)
    @game_class.new title
  end
end

class GameStore
  def initialize(number_of_games, game_type)
    c = Object.const_get(game_type.to_s.capitalize)

    game_factory = GameFactory.new(c)
   
    if game_type == :rpg
      title = 'Final Fantasy'
    elsif game_type == :arcade
      title = 'Double Dragon'
    end
   
    @games = []
    number_of_games.times do |i|
      @games << game_factory.create("#{title} #{i}")
    end
  end
 
  def show_games
    @games.each {|game| game.description}
  end
end

As we can see, now a single concrete factory GameFactory continues to build Arcade and RPG basing on the need of the moment.
This will allow a system to be independent from the implementation of concrete objects and that the client, through the interface, to use the different product families.
Note that in both examples the definition of MyAbstractGameFactory was made only for educational purposes and was used to “simulate” in Ruby an abstract method of an abstract class.

The output generated by invoking this new GameStore is the same as seen in the previous example.

All code available in this repository on GitHub: design_patterns_in_ruby

Previous posts from this serie:
Design Patterns in Ruby: Introduction

21Jun/101

Design Patterns in Ruby: Introduction

ORIGINAL POST

Hello everyone.

With this post I would like to start a serie of articles concerning the description of the most common design patterns and how these can be applied with the Ruby language.

In the world of software engineering you don’t need to reinvent the wheel to face daily problems: these problems are often very common and in most cases they require a similar resolution.

Christopher Alexander says that “each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such way that you can use this solution a million times over, without ever doing it the same way twice“.

In 1995, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, starting from the work of Christopher Alexander and Kent Beck, have published “Design Patterns: Elements of Reusable Object-Oriented Software.” With this book, the four authors (from then knowned as GoF, Gang of Four) have proposed solutions to the 23 most common and recurring problems in software engineering.

The GoF have analyzed and divided the 23 patterns into 3 categories:

Creational patterns

* Abstract Factory
* Builder
* Factory Method
* Prototype
* Singleton

Structural patterns
* Adapter
* Bridge
* Composite
* Decorator
* Facade
* Flyweight
* Proxy

Behavioral patterns
* Chain
* Command
* Interpreter
* Iterator
* Mediator
* Memento
* Observer
* State
* Strategy
* Template
* Visitor

We will see during this series all the most common patterns: we’ll analyze the problem and define a solution if possible using the potential provided by the Ruby language.

All showed code will be freely accessible in an out repository on GitHub at this address: design_patterns_in_ruby.