<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Thomas&#039; Blog</title>
	<atom:link href="http://www.dallagnese.fr/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dallagnese.fr</link>
	<description>Tales of a geek globetrotter</description>
	<lastBuildDate>Sat, 04 Feb 2012 03:16:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Run Django from a VM and access it from the host</title>
		<link>http://www.dallagnese.fr/computers-it/run-django-from-a-vm-and-access-it-from-the-host/</link>
		<comments>http://www.dallagnese.fr/computers-it/run-django-from-a-vm-and-access-it-from-the-host/#comments</comments>
		<pubDate>Sat, 04 Feb 2012 03:16:53 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[machine.server.host]]></category>
		<category><![CDATA[virtual]]></category>
		<category><![CDATA[virtual machine]]></category>
		<category><![CDATA[vm]]></category>

		<guid isPermaLink="false">http://www.dallagnese.fr/?p=846</guid>
		<description><![CDATA[Quick tutorial about how to run a Django server from a Virtual Machine and access it from the host machine.]]></description>
			<content:encoded><![CDATA[<p>If you try to run Django development mode from a Virtual Machine and access the website from the host, you need to specify the global IP address in the "runserver" command.</p>
<p>For example if your VM IP address is 192.168.31.128 (in NAT mode):<br />
<a  target="_blank" href="http://www.dallagnese.fr/wp-content/uploads/2012/02/IP_address_of_the_VM2.png"><img src="http://www.dallagnese.fr/wp-content/uploads/2012/02/IP_address_of_the_VM2.png" width="300" alt="IP_address_of_the_VM" title="IP_address_of_the_VM" class="aligncenter size-full wp-image-856" /></a></p>
<p>You should run the server by calling (you can change the port):</p>
<pre class="brush:bash">python manage.py runserver 192.168.31.128:8000</pre>
<p><a target="_blank" href="http://www.dallagnese.fr/wp-content/uploads/2012/02/Run_server_from_VM.png"><img src="http://www.dallagnese.fr/wp-content/uploads/2012/02/Run_server_from_VM-300x73.png" alt="Run_server_from_VM" title="Run_server_from_VM" width="300" height="73" class="aligncenter size-medium wp-image-854" /></a></p>
<p>Now you need to connect to the website specifying the IP address like that: http://192.168.31.128:8000.</p>
<p>Both from the VM:<br />
<a target="_blank" href="http://www.dallagnese.fr/wp-content/uploads/2012/02/Access_server_in_VM.png"><img src="http://www.dallagnese.fr/wp-content/uploads/2012/02/Access_server_in_VM-300x122.png" alt="Access_server_in_VM" title="Access_server_in_VM" width="300" height="122" class="aligncenter size-medium wp-image-852" /></a></p>
<p>And the Host:<br />
<a target="_blank" href="http://www.dallagnese.fr/wp-content/uploads/2012/02/Access_server_from_host.png"><img src="http://www.dallagnese.fr/wp-content/uploads/2012/02/Access_server_from_host-300x123.png" alt="Access_server_from_host" title="Access_server_from_host" width="300" height="123" class="aligncenter size-medium wp-image-851" /></a></p>
<div class="info">The server running on Linux is much faster than the one running on Windows <img src='http://www.dallagnese.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </div>
				<div id="gallery-ba108115" class="flickr-gallery photoset">
													<div class="flickr-thumb">
									<a href="http://flickr.com/photo.gne?id=6814869407"><img class="photo" title="IP_address_of_the_VM" src="http://farm8.static.flickr.com/7011/6814869407_1a50dae350_s.jpg" alt="IP_address_of_the_VM" /></a>
								</div>
															<div class="flickr-thumb">
									<a href="http://flickr.com/photo.gne?id=6814869515"><img class="photo" title="Run_server_from_VM" src="http://farm8.static.flickr.com/7142/6814869515_f4bc5fe8be_s.jpg" alt="Run_server_from_VM" /></a>
								</div>
															<div class="flickr-thumb">
									<a href="http://flickr.com/photo.gne?id=6814869467"><img class="photo" title="Access_server_in_VM" src="http://farm8.static.flickr.com/7161/6814869467_8a593f1749_s.jpg" alt="Access_server_in_VM" /></a>
								</div>
															<div class="flickr-thumb">
									<a href="http://flickr.com/photo.gne?id=6814869289"><img class="photo" title="Access_server_from_host" src="http://farm8.static.flickr.com/7030/6814869289_20b9b50dd5_s.jpg" alt="Access_server_from_host" /></a>
								</div>
												<div class="fg-clear"></div>
				</div>
												<div class="fg-clear"></div>
							<script type="text/javascript">
											jQuery(document).ready(function(){
							jQuery("#gallery-ba108115 .flickr-thumb img").flightbox({size_callback: get_sizes});
						});
										
										//-->
				</script>
			
]]></content:encoded>
			<wfw:commentRss>http://www.dallagnese.fr/computers-it/run-django-from-a-vm-and-access-it-from-the-host/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Package a Python Qt (PySide) application for Windows (.exe)</title>
		<link>http://www.dallagnese.fr/computers-it/empaqueter-un-programme-python-qt-pyside-sous-windows-exe/</link>
		<comments>http://www.dallagnese.fr/computers-it/empaqueter-un-programme-python-qt-pyside-sous-windows-exe/#comments</comments>
		<pubDate>Thu, 01 Dec 2011 13:43:57 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[binary]]></category>
		<category><![CDATA[package]]></category>
		<category><![CDATA[py2exe]]></category>
		<category><![CDATA[PyInstaller]]></category>
		<category><![CDATA[pyside]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[qt]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.dallagnese.fr/?p=824</guid>
		<description><![CDATA[Setup sample to package a python application using the Qt framework to create a GUI (PySide) using PyInstaller and py2exe.]]></description>
			<content:encoded><![CDATA[<p>That's fairly easy to package a Python Qt (PySide) application for Windows (and even easier on Linux with cxfreeze).</p>
<p>Let see two different ways of doing so.</p>
<p><span id="more-824"></span></p>
<div id="toc_container" class="no_bullets"><p class="toc_title">Contents</p><ul class="toc_list"><li><a href="#1_py2exe">1 1. py2exe</a><ul><li><a href="#Pros">1.1 Pros</a></li><li><a href="#Cons">1.2 Cons</a></li><li><a href="#Download">1.3 Download</a></li><li><a href="#Basic_setup">1.4 Basic setup</a></li><li><a href="#Compile">1.5 Compile</a></li></ul></li><li><a href="#2_PyInstaller">2 2. PyInstaller</a><ul><li><a href="#Pros-2">2.1 Pros</a></li><li><a href="#Cons-2">2.2 Cons</a></li><li><a href="#Download-2">2.3 Download</a></li><li><a href="#PySide_setup">2.4 PySide setup</a></li><li><a href="#Compile-2">2.5 Compile</a></li></ul></li><li><a href="#Postface">3 Postface</a></li></ul></div>
<h2><span id="1_py2exe">1. py2exe</span></h2>
<h3><span id="Pros">Pros</span></h3>
<ul>
<li>Easy</li>
</ul>
<ul>
<li>Support multiple binaries</li>
</ul>
<h3><span id="Cons">Cons</span></h3>
<ul>
<li>Might miss some dependencies</li>
</ul>
<h3><span id="Download">Download</span></h3>
<p style="padding-left: 30px;"><a href="http://www.py2exe.org/" target="_blank">Py2Exe Website</a><br />
There are binaries for both win32 and win64.</p>
<h3><span id="Basic_setup">Basic setup</span></h3>
<p>basic_setup.py</p>
<pre class="brush:python">from distutils.core import setup
import py2exe

setup(
    windows = ['pysideApp1.py','pysideApp2.py'],
    options = {
        "py2exe" : {
            "includes" : ['sys', 'tempfile', 'zipfile', 'mmap', 'encodings',
                          'json', 'hashlib', 'datetime', 'struct',
                          'os', 'time', 'random', 'math', 'xmlrpclib', 'Crypto']
        }
    }
)</pre>
<h3><span id="Compile">Compile</span></h3>
<p><strong>$ python basic_setup.py py2exe</strong></p>
<p>That's it!<br />
Look in your "dist" folder and you should have your application <img src='http://www.dallagnese.fr/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h2><span id="2_PyInstaller">2. PyInstaller</span></h2>
<h3><span id="Pros-2">Pros</span></h3>
<ul>
<li>Seems to detect the required libraries much better</li>
</ul>
<h3><span id="Cons-2">Cons</span></h3>
<ul>
<li>Last stable version (1.5.1 as today) does not support multiple binaries</li>
<li>Need a little more config</li>
</ul>
<h3><span id="Download-2">Download</span></h3>
<p style="padding-left: 30px;"><a href="http://www.pyinstaller.org/" target="_blank">PyInstaller Website</a><br />
No need to install, just extract somewhere.</p>
<h3><span id="PySide_setup">PySide setup</span></h3>
<p>pyside.spec</p>
<pre class="brush:python">import os

a = Analysis(
    [os.path.join(HOMEPATH,'support\\_mountzlib.py')
        , os.path.join(HOMEPATH,'support\\useUnicode.py')
        , os.path.normpath(os.path.join(currentDir, 'main.py'))
        , os.path.normpath(os.path.join(currentDir, 'importantLib.py'))
        # add the files you want PyInstaller to analyse the "import" statements
        # to detect the libraries to include
    ],
     pathex=['C:\\Python27\\pyinstaller-1.5.1']
)
pyz = PYZ(a.pure)
exe = EXE(pyz,
          a.scripts,
          exclude_binaries=1,
          name=os.path.join('build\\pyi.win32\\build_output', 'your_application.exe'),
          debug=False,
          strip=False,
          upx=True,
          console=False )
coll = COLLECT( exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               name=os.path.join('dist', 'dist_output'))</pre>
<h3><span id="Compile-2">Compile</span></h3>
<p>Move to your pyinstaller.py location and run:<br />
<strong>$ python pyinstaller.py "C:\path\to\pyside.spec"</strong></p>
<p>That's it!<br />
Look in your "dist_output" folder and you should have your application <img src='http://www.dallagnese.fr/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h2><span id="Postface">Postface</span></h2>
<p>Both methods work fine.<br />
The output folder with PyInstaller is a little bigger (~10MB, whereas the one with py2exe is ~8MB).<br />
However, it seems to include more libraries, even though I didn't manually specified any specific library, I just gave the 2 main py files of my program, so maybe more reliable.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dallagnese.fr/computers-it/empaqueter-un-programme-python-qt-pyside-sous-windows-exe/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Install Google Chrome Web Browser in Ubuntu 11.10 Oneiric Ocelot</title>
		<link>http://www.dallagnese.fr/computers-it/english-install-google-chrome-web-browser-in-ubuntu-11-10-oneiric-ocelot/</link>
		<comments>http://www.dallagnese.fr/computers-it/english-install-google-chrome-web-browser-in-ubuntu-11-10-oneiric-ocelot/#comments</comments>
		<pubDate>Fri, 14 Oct 2011 12:29:43 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.dallagnese.fr/?p=816</guid>
		<description><![CDATA[Ubuntu 11.10 final is here! But some of you might be having troubles to install the nonfree google chrome web browser. To install it, just follow the following steps: 1. Download the deb package on http://www.google.com/chrome 2. Open a command prompt and try to install it: sudo dpkg -i google-chrome-stable_current_amd64.deb You will have the following [...]]]></description>
			<content:encoded><![CDATA[<p>Ubuntu 11.10 final is here!</p>
<p>But some of you might be having troubles to install the nonfree google chrome web browser.<br />
To install it, just follow the following steps:</p>
<p><strong>1. Download the deb package on http://www.google.com/chrome<br />
2. Open a command prompt and try to install it: sudo dpkg -i google-chrome-stable_current_amd64.deb</strong></p>
<p>You will have the following <i>normal</i> errors:<br />
<code>Selecting previously deselected package google-chrome-stable.<br />
(Reading database ... 127754 files and directories currently installed.)<br />
Unpacking google-chrome-stable (from .../google-chrome-stable_current_amd64.deb) ...<br />
dpkg: dependency problems prevent configuration of google-chrome-stable:<br />
google-chrome-stable depends on libnspr4-0d (&gt;= 4.7.3-0ubuntu1~); however:<br />
Package libnspr4-0d is not installed.<br />
google-chrome-stable depends on libxss1; however:<br />
Package libxss1 is not installed.<br />
google-chrome-stable depends on libcurl3; however:<br />
Package libcurl3 is not installed.<br />
dpkg: error processing google-chrome-stable (--install):<br />
dependency problems - leaving unconfigured<br />
Processing triggers for gnome-menus ...<br />
Processing triggers for desktop-file-utils ...<br />
Processing triggers for bamfdaemon ...<br />
Rebuilding /usr/share/applications/bamf.index...<br />
Processing triggers for man-db ...<br />
Errors were encountered while processing:<br />
google-chrome-stable</code></p>
<p><strong>3. Now just type the following command: sudo apt-get install -f</strong></p>
<p>And Google Chrome will install!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dallagnese.fr/computers-it/english-install-google-chrome-web-browser-in-ubuntu-11-10-oneiric-ocelot/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Python Qt4 recipe: QSingleApplication (PySide)</title>
		<link>http://www.dallagnese.fr/computers-it/recette-python-qt4-qsingleapplication-pyside/</link>
		<comments>http://www.dallagnese.fr/computers-it/recette-python-qt4-qsingleapplication-pyside/#comments</comments>
		<pubDate>Tue, 10 May 2011 02:02:35 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[pyside recipe qt]]></category>

		<guid isPermaLink="false">http://www.dallagnese.fr/?p=792</guid>
		<description><![CDATA[(Français) Simple QSingleApplication class for PySide that allows you to be sure your program will be started only once.
In addition to start the application only once, we can send the arguments of the later calls of your program to the first (and only remaining) instance.]]></description>
			<content:encoded><![CDATA[<p>Thanks to Renato Filho who helped me in <a href="http://developer.qt.nokia.com/forums/viewthread/5733/" target="_blank">this thread on the Qt Forums</a>, I made a simple QSingleApplication class for PySide that allows you to be sure your program will be started only once.</p>
<p>In addition to start the application only once, we can send the arguments of the later calls of your program to the first (and only remaining) instance.</p>
<p>The following video summarizes the features:<br />
<iframe width="425" height="349" src="http://www.youtube.com/embed/pSFEAbNU_hw?rel=0" frameborder="0" allowfullscreen></iframe><br />
<span id="more-792"></span></p>
<p>The idea is to use the QLocalServer / QLocalSocket classes to perform the check and communication between the instances.</p>
<p>First, we create a socket and try to connect to the server, registered with the application name.</p>
<pre class="brush:python">
        self.m_socket = QLocalSocket()
        self.m_socket.connected.connect(self.connectToExistingApp)
        self.m_socket.error.connect(self.startApplication)
        self.m_socket.connectToServer(self.applicationName(), QIODevice.WriteOnly)</pre>
<p>If the connection works, it means a server has already been registered, so the application has already been started and we try to connect to that existing application.<br />
If we the new call has been made with arguments, we send them to the already running application (the first one only in this example, adapt to your needs for all).<br />
If the new call has been made without any arguments, we notice the user that the program is already running and we quit.</p>
<pre class="brush:python">
    def connectToExistingApp(self):
        if len(sys.argv)>1 and sys.argv[1] is not None:
            self.m_socket.write(sys.argv[1])
            self.m_socket.bytesWritten.connect(self.quit)
        else:
            QMessageBox.warning(None, self.tr("Already running"), self.tr("The program is already running."))
            # Quit application in 250 ms
            QTimer.singleShot(250, self.quit)</pre>
<p>If the connection fails, then it means this is the first instance of the application so we start the application and register a server listening to future applications.</p>
<pre class="brush:python">
    def startApplication(self):
        self.m_server = QLocalServer()
        if self.m_server.listen(self.applicationName()):
            self.m_server.newConnection.connect(self.getNewConnection)
            self.mainWindow.show()
        else:
            QMessageBox.critical(None, self.tr("Error"), self.tr("Error listening the socket."))
</pre>
<p>You can retrieve the complete source code at Gitorious: <a target="_blank" href="https://gitorious.org/qsingleapplication/qsingleapplication/blobs/master/qSingleApplication.py">qSingleApplication.py</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dallagnese.fr/computers-it/recette-python-qt4-qsingleapplication-pyside/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>20 years of Linux</title>
		<link>http://www.dallagnese.fr/computers-it/les-20-ans-de-linux/</link>
		<comments>http://www.dallagnese.fr/computers-it/les-20-ans-de-linux/#comments</comments>
		<pubDate>Tue, 12 Apr 2011 02:37:38 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[anniversary]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://www.dallagnese.fr/?p=781</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.linuxfoundation.org/"><img alt="Let celebrate the 20 years of Linux!" src="http://www.linuxfoundation.org/20th/images/lf_linux20_webbadge.png" title="Linux 20 years" class="alignnone" width="300" height="250" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dallagnese.fr/computers-it/les-20-ans-de-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python VS Ruby through a concrete GUI example (Qt)</title>
		<link>http://www.dallagnese.fr/computers-it/python-vs-ruby-through-a-concrete-example/</link>
		<comments>http://www.dallagnese.fr/computers-it/python-vs-ruby-through-a-concrete-example/#comments</comments>
		<pubDate>Mon, 04 Apr 2011 00:17:00 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[comparaison]]></category>
		<category><![CDATA[comparison]]></category>
		<category><![CDATA[pyqt]]></category>
		<category><![CDATA[pyside]]></category>
		<category><![CDATA[rubyqt]]></category>
		<category><![CDATA[vs]]></category>

		<guid isPermaLink="false">http://www.dallagnese.fr/?p=765</guid>
		<description><![CDATA[Python VS Ruby through a concrete GUI example (Qt)]]></description>
			<content:encoded><![CDATA[<p>In a <a href="http://www.dallagnese.fr/computers-it/programming/python-pyqt4-ou-ruby-rubyqt/">previous post</a>, I was justifying my choice to start learning Ruby instead of Python, and in <a href="http://www.dallagnese.fr/en/computers-it/programming/qtruby-creez-rapidement-des-applications-graphiques-puissantes/">another previous post</a> I was praising QtRuby.</p>
<p>Now it's time to challenge QtRuby (and Ruby in general) with PyQt/PySide (and Python in general).</p>
<p>Due to some reasons, I had to write the same program in both languages.    <br />Thanks to that, I better understood myself the pros and cons of both languages and will try to share my thoughts with you.</p>
<p>A very brief summary would be: Ruby is the winner for programming pleasure and private applications while Python is the winner when it gets serious.    <br />For more information, read the whole post!</p>
</p>
<p><span id="more-765"></span><br />
<div id="toc_container" class="no_bullets"><p class="toc_title">Contents</p><ul class="toc_list"><li><a href="#Background">1 Background</a></li><li><a href="#Switching_to_Python">2 Switching to Python</a></li><li><a href="#Similarities_between_Python_and_Ruby">3 Similarities between Python and Ruby</a><ul><li><a href="#Indentation">3.1 Indentation</a></li><li><a href="#Object_Programming">3.2 Object Programming</a></li><li><a href="#Libraries">3.3 Libraries</a></li></ul></li><li><a href="#Differences_between_Python_and_Ruby">4 Differences between Python and Ruby</a><ul><li><a href="#Pleasure_of_programming">4.1 Pleasure of programming</a></li><li><a href="#The_Blocks_Power_of_Ruby">4.2 The Blocks Power of Ruby</a></li><li><a href="#Definition_of_the_slotssignals">4.3 Definition of the slots/signals</a></li><li><a href="#Easiness_of_distribution">4.4 Easiness of distribution</a></li><li><a href="#Performance">4.5 Performance</a></li></ul></li><li><a href="#Conclusion">5 Conclusion</a></li></ul></div>
<h2><span id="Background">Background</span></h2>
<p>I wanted to write a new GUI program, basically uploading pictures to Twitpic (the real goal is beyond that but let's make it easy).    <br />Being a Ruby fan, I started to write my code in Ruby 1.9 with the &quot;qtbindings&quot; gems.     <br />For my application, I also needed other gems like the &quot;zip/zipfilesystem&quot;, &quot;digest/md5&quot; or &quot;json&quot;.     <br />As always with Ruby, everything went fine and after about 16 hours I had my application working.</p>
</p>
<p><a href="http://www.dallagnese.fr/wp-content/uploads/2011/04/ddl-ruby-settings1.png" target="_blank"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="ddl-ruby-settings" border="0" alt="ddl-ruby-settings" src="http://www.dallagnese.fr/wp-content/uploads/2011/04/ddl-ruby-settings_thumb.png" width="192" height="244" /></a></p>
<p>Came the moment to send the program to beta testers.    <br />To make it simple for them, as not all of them are familiar with programming, I <strong>wanted to bundle the program in an executable</strong> with all the required DLLs, as I used to do in C++ with Qt.</p>
<p>Lucky me, there is something called “<strong>RubyScript2Exe</strong>” (or “AllInOneRuby”) that can do it for you!     <br />Unlucky me, it’s not working at all! It always raises a fatal error, even with the simplest QtRuby script…     <br />A “<em>can’t modify frozen string (RunTimeError)</em>” that many people seem to have and no fix available yet…</p>
<p>Well, there is another one called <strong>OCRA</strong> (One-Click Ruby Application Builder) that looks more serious.     <br />It works with basic QtRuby scripts, but unfortunately not when we require some dependencies, like “zip/zipfilesystem”. It <a href="https://groups.google.com/d/topic/ruby-ocra/q2tGVQYCgU8/discussion" target="_blank">posted</a> on their Google Groups and hopefully a solution will be found, but so far… nothing!</p>
<div class="info"><u>Update:</u> <a href="http://groups.google.com/group/ruby-ocra/browse_thread/thread/ab6b46550602814f" target="_blank">Thanks to Lars</a>, a simple --no-autoload made OCRA work perfectly!<br />
So now I can easily bundle my QtRuby applications too!</div>
<p>That’s good to be able to quickly write programs that do their job, but it’s <strong>very frustrating when you cannot distribute them to others</strong>!     <br />For beta testers, I could tell them to install Ruby 1.9, the required gems, Qt 4.7, and send them directly the source code, but it’s not convenient at all for them, especially if they don’t really have time to waste…</p>
<p>Another solution was to switch to Ruby 1.8 instead of Ruby 1.9 that I was using and hope that it works.    <br />However, I am simply unable to run my code under Ruby 1.8 as the qtbindings are not recognized by Ruby 1.8 (even if of course I install the gem… :s).     <br />I <a href="http://stackoverflow.com/questions/5533233/qtbindings-for-ruby-1-8" target="_blank">posted the problem on stack overflow</a>, and, hopefully I will be able to edit this post and write that I managed to make it work on Ruby 1.8, and, with even a lot of luck, to bundle the QtRuby package with Ruby 1.8!     <br />But for now, trying to bundle my QtRuby application just fails enormously…</p>
<p>So I decided to <strong>re-write the program in Python</strong>, as Python and Ruby are often compared; Python being more accepted among professionals.</p>
<h2><span id="Switching_to_Python">Switching to Python</span></h2>
<p>In Python, there are two different Qt4 bindings: PyQt4 and PySide.    <br />They are very similar, except the licence.     <br />PySide being supported by Nokia (which now owns Qt), I chose <strong>PySide</strong>.</p>
<p>Before anything else, I first tried to compile a very basic PySide program into a binary (an .exe for Windows).    <br />There is a tool called <strong>py2exe</strong> so I tried that one and… it works very well! (Unlike RubyScript2Exe…)     <br />I added some “import” and made some basic calls and… py2exe just worked well.</p>
<p>Accepted! I was ready to write my program again, but in Python!    <br />The good thing is that I already had the “brain” of my program and new how to do it.     <br />I just had to change the syntax from Ruby to Python, which was done quite smoothly.</p>
<p>It took me again about 16 hours to re-write it and add some extra features and error control.</p>
<p>The result is looking just exactly the same:</p>
<p><a href="http://www.dallagnese.fr/wp-content/uploads/2011/04/ddl-python-settings1.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="ddl-python-settings" border="0" alt="ddl-python-settings" src="http://www.dallagnese.fr/wp-content/uploads/2011/04/ddl-python-settings_thumb.png" width="186" height="244" /></a></p>
<p>The only differences are because I did not copy <em>exactly</em> the position and size of all the elements…</p>
<p>But the code is very different so let see the differences between Ruby and Python!</p>
<h2><span id="Similarities_between_Python_and_Ruby">Similarities between Python and Ruby</span></h2>
<p>First let’s talk about the similarities.</p>
<h3><span id="Indentation">Indentation</span></h3>
<p>A lot of people talk about the “whitespaces” in Python, that force you to indent your code otherwise Python does not understand it… Honestly, it is so transparent that you just forget it after a while!    <br />I mean, when you write code in C++ or Java or whatever, you indent your code (or your IDE does it for you). It is just so natural that there is just nothing to say about it.     <br />My Ruby code had an indentation of 4 whitespaces, and my Python code too.     <br />I didn’t feel any difference between the two languages as for the indentation…</p>
<h3><span id="Object_Programming">Object Programming</span></h3>
<p>Ruby is 100% object programming, Python… is?    <br />It seems that recent Python is also fully object oriented and I did not feel any problem with “int” or “str” that are well handled in both languages.</p>
<h3><span id="Libraries">Libraries</span></h3>
<p>For the needs of my project, both languages had the required libraries, built-in or through easy to install libraries or gems.    <br />It is said that Python has more libraries, and I am sure it is true, but Ruby is very likely to have enough libraries to meet your needs.</p>
<h2><span id="Differences_between_Python_and_Ruby">Differences between Python and Ruby</span></h2>
<h3><span id="Pleasure_of_programming">Pleasure of programming</span></h3>
<p>The first difference is very subjective.    <br />I enjoy much more writing some Ruby code than Python code.     <br />First of all, I hate the<strong> &quot;:&quot; in Python</strong>… I just find it too ugly (ok, very subjective…).</p>
<p>I also don’t like the fact that you always <strong>need to add the parentheses to the method calls</strong> to really call the method. This is also very subjective again and many people won’t agree and say it’s better to differentiate the <strong>method call and reference</strong>, but I prefer a clean code without parentheses like in Ruby (you still can add the parentheses in Ruby if you want though…).</p>
<p>Then, the keyword <strong>self</strong> in Python: you just have it everywhere!     <br />All the method calls first argument are always “self”, and you always repeat “self” when you call a local class instance variable… Among 391 lines of code, I have <strong>286 times the word “self”</strong> (more than one “self” in some lines of course), that’s too many!     <br />I definitely prefer the <strong>@var</strong> in Ruby that some Pythonists laugh at.</p>
<p>Finally, the Python <strong>__init__, __str__</strong> and other underscored methods/functions…     <br />What the…! No, seriously, someone has to to something for that!     <br />OK, the __str__ function that can change any object (anything?) into a string is very useful.     <br />But please find another name…     <br />For example <em>__init__</em> and <em>__del__</em> are respectively called <em>initialize</em> and <em>define_finalizer</em> in Ruby.     <br />It’s less ugly, isn’t it?</p>
<p>To conclude, it’s just nicer to read and write some Ruby code than Python code (for me!).</p>
<h3><span id="The_Blocks_Power_of_Ruby">The Blocks Power of Ruby</span></h3>
<p>Here we are. The Ruby Blocks ( { } ).    <br />They are just so convenient that once you code with it, you’re addicted!     <br />It is possible to achieve such features in Python too, but it’s definitely better implemented in Ruby where it’s very very easy to use.</p>
<p>Let’s take a concrete example of a Qt signal connection.    <br />In Python you have to pass a function as parameter of the call, even if you only have one action to do when the signal is received.</p>
<p>In Python, you need to define the receiving slot separately (note the “…”):    </p>
<pre class="brush:python">        saveSettingsButton = QtGui.QPushButton('Save Settings')
        saveSettingsButton.clicked.connect(self.saveSettings)
        ...
    @QtCore.Slot()
    def saveSettings(self):
        self.settings.setValue('author',self.author())
        QtGui.QMessageBox.information(self, 'Settings', 'Settings saved!') </pre>
<p>In Ruby, you can just use the blocks to write the action on-click right after: </p>
<p></p>
<pre class="brush:ruby">    # Save settings
    saveSettingsButton = Qt::PushButton.new(tr('Save settings'))
    saveSettingsButton.connect(SIGNAL :clicked) {
        @settings.setValue(&quot;author&quot;, Qt::Variant.new(@author))
        Qt::MessageBox.new(Qt::MessageBox::Information, 'Settings', 'Settings saved!').exec
    }</pre>
<p>When you will perform the action only once, or for very short actions, it is definitely better to write it directly after the connection inside the blocks, like in Ruby.<br />
  <br />It is easier to read and maintain. </p>
<p>For actions to perform that can be use somewhere else in the code by another object, of course it is better to separate it, and Ruby can also do that. But for very short call, this Ruby shortcut using blocks is very convenient! </p>
<h3><span id="Definition_of_the_slotssignals">Definition of the slots/signals</span></h3>
<p>In Python, you need to add a <strong>@QtCore.Slot(type1, type2,…)</strong> before the functions that you want to declare as a slot, like the previous &quot;saveSettings(self)&quot; method. </p>
<p>In Ruby, you can just add one line at the top of your class listing all the slots, like you would do in Qt/C++: slots :saveSettings, :mySlot2, :mySlot3 </p>
<p>Same for the signals with the keyword &quot;signals&quot;, whereas in Python you need to declare the signals at the top of your class, outside __init__</p>
<p>Python:<br />
  </p>
<pre class="brush:python">class myClass(QtCore.QObject):
    errorSignal         = QtCore.Signal(str)
    infoSignal          = QtCore.Signal(str)
    def __init__(self):
        ...
    @QtCore.Slot()
    def saveSettings(self):
        ...
    </pre>
<p>Ruby:<br />
  </p>
<pre class="brush:ruby">class myClass &lt; Qt::Object
  slots :saveSettings
  signals :errorSignal, :infoSignal</pre>
<p>And finally, you can just have no slot at all in Ruby if you add your code when a signal is received inside blocks, like shown in the previous code example!</p>
<h3><span id="Easiness_of_distribution">Easiness of distribution</span></h3>
<p>Yes, both of them are multi-platform, and it is possible to run the same code on Windows, Linux and Mac.<br />
  <br />However, not all the clients want to install Ruby or Python and the required libraries to run the program.</p>
<p>So you need to bundle the application for them, and Python is far better on this point!</p>
<p>I have talked about it in more details in the background introduction as it was the reason why I wrote the same program in both languages.<br />
  <br />Refer to the first part for more details.</p>
<h3><span id="Performance">Performance</span></h3>
<p>I was surprised reading on Internet that Ruby was performing better than Python.<br />
  <br />I don’t know if it’s my computer or not, but for me PySide is performing far better than QtRuby…</p>
<p>The PySide GUI is almost immediately displayed when the program is started whereas the QtRuby GUI takes about 10 seconds to display!</p>
<p>The difference is even bigger when I run the debugger… Python debugger runs very smoothly whereas Ruby debugger is very slow, so slow I can’t use it… (and I used the ruby “fastdebug” :s)</p>
<p>My computer is not recent (an almost 3 years old AMD X2 laptop that rediscovered life when it met an SSD) so I tried on a Quad Core running Windows XP and of course the difference was smaller…<br />
  <br />But on old machines, I beleive the PySide GUI is starting faster than the QtRuby one (and the performance of the program once launched is similar).</p>
<h2><span id="Conclusion">Conclusion</span></h2>
<p>In this article, I have shown the pros and cons of Ruby and Python on my concrete example, with my subjective point of view.<br />
  <br />Yes, I prefer Ruby as a language itself and as I already said, I enjoy much more programming in Ruby than Python.</p>
<p>However, in the real world, for real projects and real clients that want a bundled application that just runs smoothly, I’m afraid Python is better.</p>
<p>It is even far better that after justifying Ruby during all this post, I will continue further development of this program in Python… Because yes, the easiness of distribution is a crucial point in the real world and the differences between Ruby and Python are more about self-pleasure than language features.</p>
<p>I hope Ruby will soon become easier to bundle so I can switch back to my lovely functional blocks!</p>
<div class="notice"><u>Update:</u> <a href="http://groups.google.com/group/ruby-ocra/browse_thread/thread/ab6b46550602814f" target="_blank">Thanks to Lars</a>, a simple --no-autoload made OCRA work perfectly!<br />
So now I can easily bundle my QtRuby applications too!</div>
]]></content:encoded>
			<wfw:commentRss>http://www.dallagnese.fr/computers-it/python-vs-ruby-through-a-concrete-example/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Reasonable people</title>
		<link>http://www.dallagnese.fr/japan/les-gens-raisonnables/</link>
		<comments>http://www.dallagnese.fr/japan/les-gens-raisonnables/#comments</comments>
		<pubDate>Tue, 25 Jan 2011 15:07:56 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[Japan]]></category>
		<category><![CDATA[chanson]]></category>
		<category><![CDATA[gens]]></category>
		<category><![CDATA[mickey 3d]]></category>
		<category><![CDATA[people]]></category>
		<category><![CDATA[raisonnables]]></category>
		<category><![CDATA[reasonable]]></category>

		<guid isPermaLink="false">http://www.dallagnese.fr/?p=745</guid>
		<description><![CDATA[Japanese people aren't they "reasonable people"?]]></description>
			<content:encoded><![CDATA[<p>"Reasonable people<br />
Never do as they see fit<br />
They don't call anybody wretched<br />
Never get on their nerve in their car<br />
And if ever someone blame them<br />
Even if they know they are right<br />
To avoid the misdemeanour<br />
They apologize or leave"</p>
<p><object width="250" height="150"><param name="movie" value="http://listen.grooveshark.com/widget.swf" /><param name="wmode" value="window" /><param name="allowScriptAccess" value="always" /><param name="flashvars" value="hostname=cowbell.grooveshark.com&#038;songIDs=24339554&#038;style=metal&#038;p=0" /><embed src="http://listen.grooveshark.com/widget.swf" type="application/x-shockwave-flash" width="250" height="150" flashvars="hostname=cowbell.grooveshark.com&#038;songIDs=24339554&#038;style=metal&#038;p=0" allowScriptAccess="always" wmode="window" /><br />
</object></p>
<p>Mickey 3D was in Japan when he wrote this song...?</p>
<p>Listen entirely to appreciate <img src='http://www.dallagnese.fr/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /><br />
(in French though...)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dallagnese.fr/japan/les-gens-raisonnables/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quickly build smartphone applications (iPhone, Android, WP7, BB, Symbian) with Rhomobile Rhodes</title>
		<link>http://www.dallagnese.fr/computers-it/programming/developpez-rapidement-des-applications-pour-les-mobiles-iphone-android-wp7-bb-symbian-avec-rhomobile-rhodes/</link>
		<comments>http://www.dallagnese.fr/computers-it/programming/developpez-rapidement-des-applications-pour-les-mobiles-iphone-android-wp7-bb-symbian-avec-rhomobile-rhodes/#comments</comments>
		<pubDate>Sat, 22 Jan 2011 02:50:43 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[appcelerator]]></category>
		<category><![CDATA[blackberry]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[phone]]></category>
		<category><![CDATA[rhodes]]></category>
		<category><![CDATA[rhomobile]]></category>
		<category><![CDATA[smartphone]]></category>
		<category><![CDATA[titanium]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.dallagnese.fr/?p=713</guid>
		<description><![CDATA[HOWTO: Quickly build mobile applications for iPhone, Android, BlackBerry, Windows Phone and Symbian using the Rhomobile Rhodes framework (Ruby).]]></description>
			<content:encoded><![CDATA[<p>Yesterday, I had no idea about how to write programs for smartphones such as iPhone, Android, Windows Phone or BlackBerry.<br />
Today, my first application is already running on my Android phone...</p>
<p>As a first attempt to write a mobile application, I just tried to build an application that retrieves the latest news from my school's atom feed and displays it in a native way on a smartphone (Keio University, Graduate School of SDM).<br />
Yesterday, I had absolutely no knowledge about mobile development, except "iPhone is using the ugly Objective-C and Android is using the heavy Java".<br />
Today, the application looks like that...</p>
<p><a href="http://www.dallagnese.fr/wp-content/uploads/2011/01/Android_SDM_News_04.png" target="_blank"><img class="aligncenter size-thumbnail wp-image-720" title="Android_SDM_News_04" src="http://www.dallagnese.fr/wp-content/uploads/2011/01/Android_SDM_News_04-e1295604370231-104x150.png" alt="" width="104" height="150" /></a></p>
<p>...is written in pure Ruby and is 100% native on iPhone, Android, Windows Mobile and BlackBerry!<br />
How come?! Thanks to a powerful, light, easy and intuitive mobile framework: Rhodes (from <a href="http://rhomobile.com/" target="_blank">Rhomobile</a>).<br />
Let see in this post how to do that.</p>
<p><span id="more-713"></span></p>
<div id="toc_container" class="no_bullets"><p class="toc_title">Contents</p><ul class="toc_list"><li><a href="#Introduction">1 Introduction</a></li><li><a href="#Appcelerator_Titanium">2 Appcelerator Titanium</a></li><li><a href="#Rhomobile_Rhodes">3 Rhomobile Rhodes</a><ul><li><a href="#Install_the_Java_SDK">3.1 Install the Java SDK</a></li><li><a href="#Install_Android_SDK">3.2 Install Android SDK</a></li><li><a href="#Install_Ruby_and_Rhodes">3.3 Install Ruby and Rhodes</a></li><li><a href="#Hello_World">3.4 Hello World</a></li><li><a href="#Building_your_own_application">3.5 Building your own application</a><ul><li><a href="#Model">3.5.1 Model</a></li><li><a href="#XML">3.5.2 XML</a></li><li><a href="#Startup_application">3.5.3 Startup application</a></li><li><a href="#def_index">3.5.4 def index</a></li><li><a href="#def_update">3.5.5 def update</a></li><li><a href="#def_refresh">3.5.6 def refresh</a></li><li><a href="#The_Views_index_show">3.5.7 The Views (index, show)</a></li></ul></li></ul></li><li><a href="#Conclusion">4 Conclusion</a></li></ul></div>
<h2><span id="Introduction">Introduction</span></h2>
<p>When you face a new issue, the first thing you often do is... to Google it!<br />
Well that's what I did, and it quickly appeared that if I want to build native applications for smartphones, I will have to write the application in different languages using different libraries; one for each OS (for example Objective-C for iOS or Java for Android) unless I use some frameworks that do the ugly conversion to native code for you!</p>
<h2><span id="Appcelerator_Titanium">Appcelerator Titanium</span></h2>
<p>And among the frameworks, the most popular one seems to be <a href="http://www.appcelerator.com/products/titanium-mobile-application-development/" target="_blank">Appcelerator Titanium</a>.<br />
According to their websites, it allows you to use "web technologies" (JavaScript, Python, Ruby) to develop native applications for iPhone and Android.<br />
Sounds exciting right!</p>
<p>So I installed the free Titanium Plateform, downloaded an example from their website, and tried to run the example.<br />
That's the last thing I did with that software... The software never succeed to connect to the Android SDK and I was stuck on the "loading..." (of the Android SDK) that never ran... (even after moving "adb" to the right folder and setting up the path with all the correct values...)<br />
Then I tried the Sandbox where you can run some code snippets.<br />
I took one of the list, the Python Hello World example and clicked "Launch".<br />
Nothing happened...<br />
I'm sure the problem is me because the soft is pretty popular and many people manage to use it well!<br />
But it did not really persuade me to investigate further in the software...</p>
<h2><span id="Rhomobile_Rhodes">Rhomobile Rhodes</span></h2>
<p>I gave a try to another one, apparently less popular.<br />
Its name is "Rhodes" from the Rhomobile family.<br />
Unlike Appcelerator Titanium, Rhodes is really "cross-platform". Where Titanium supports only iPhone and Android, Rhodes offers you also Windows Mobile, RIM and Symbian!<br />
However, you won't have choice for programming language: you will have to program in Ruby.<br />
A single Ruby code can be deployed into a native application on all OS supported by Rhomobile.</p>
<p>But is it a drawback to use Ruby? After using it for two days... clearly not!<br />
Rhodes is highly inspired by Rails and takes good ideas from the Rails web framework: Database Abstraction (not as complete as Rails), MVC (Model-View-Controller), auto model generation (similar to Rails scaffolding, also through rake) and many things I still did not see yet.</p>
<p>Let see how I ended up in 2 days with my first application running on my smartphone starting from 0.<br />
First, we need a mobile OS SDK (Development Kit). The easiest to get and available on all platforms (unlike a very close one that you can only use from Macs... &gt;&lt;) is the Android SDK.</p>
<p>You can get the one you want but I'll explain briefly how to set up the Android one here.</p>
<h3><span id="Install_the_Java_SDK">Install the Java SDK</span></h3>
<p>To use the Android SDK, you need the Java SDK (as native Android apps are Java apps).<br />
So first if you don't have it, let's install it.<br />
Go to the <a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java website</a> and download the latest SDK for your system.</p>
<div class="notice"><strong>Note:</strong> On Windows, install the 32 bits version of the SDK even if you have a 64 bits OS. Android SDK only works with the 32 bits version (for the moment?).<br />
On Linux, remember to switch your default SDK to the Sun proprietary one (using "alternatives").<br />
It may also work with the OpenSDK but I never tried.</div>
<h3><span id="Install_Android_SDK">Install Android SDK</span></h3>
<p>Go to the <a href="http://developer.android.com/sdk/index.html" target="_blank">Android Developers</a> website and install the SDK. Start the SDK Manager (asked after installed on Windows or under tools/android on Linux) and install the packages you want (probably the SDK for Android 2.3 and the updates).<br />
On the same webpage, download the <a href="http://developer.android.com/sdk/ndk/index.html" target="_blank">Android NDK</a> that helps us with "performance-critical native applications". You just need to extract the archive somewhere (probably along with the SDK).</p>
<div class="notice"><strong>Note:</strong> Do not install the SDK in a folder that contains spaces (Not in the "Program Files" folder for example!), it may not work (use for example 'C:\android-sdk-windows' and 'C:\android-ndk-r5' instead).</div>
<h3><span id="Install_Ruby_and_Rhodes">Install Ruby and Rhodes</span></h3>
<p>Then you need to install Ruby, RubyGems, Rake and Rhodes.</p>
<p>On Linux, you just need to install the packages "ruby", "rubygems", then the rake and rhodes gems ("sudo gem install rake rhodes").<br />
On Windows, if you already have Ruby and Rubygems you need to "Start command prompt with Ruby" (search from the windows menu) and "gem install rake rhodes".<br />
If you don't have Ruby, you can install Ruby, RubyGems and Rhodes with a all-in-one installer: <a href="http://rhomobile.com/instant-rhodes" target="_blank">Instant Rhodes</a>.</p>
<p>That's all you need to use the Rhodes framework.<br />
Let set it up. Start a command prompt with Ruby and type "rhodes-setup".<br />
Follow the instructions to set up Rhodes.<br />
For example for me:</p>
<pre>ruby 1.9.2p136 (2010-12-25) [i386-mingw32]

C:\Users\Thomas&gt;rhodes-setup
We will ask you a few questions below about your dev environment.

JDK path (required) (C:/Program Files/Java/jdk1.6.0_23):
Android SDK path (blank to skip) (): C:\android-sdk-windows
Android NDK path (blank to skip) (C://android-ndk-r5):
Windows Mobile 6 SDK CabWiz (blank to skip) ():
BlackBerry JDE 4.6 (blank to skip) ():
BlackBerry JDE 4.6 MDS (blank to skip) ():
BlackBerry JDE 4.2 (blank to skip) ():
BlackBerry JDE 4.2 MDS (blank to skip) ():

If you want to build with other BlackBerry SDK versions edit: C:/Ruby192/lib/ruby/gems/1.9.1/gems/rhodes-2.2.6/rhobuild.yml

C:\Users\Thomas&gt;</pre>
<p>And Rhodes is set up!</p>
<div class="notice"><strong>Note:</strong> If you have troubles with rake and its 'bin_path', just remove the rake.gemspec and rake-0.8.7.gemspec files in the \lib\ruby\gems\1.9.x\specifications folder and run "gem install rake" again</div>
<h3><span id="Hello_World">Hello World</span></h3>
<p>To make a new application, the only thing we need to do is to extend the rhodes framework.<br />
So first we can generate a simple "hello world" like application with one line.<br />
From the command prompt, enter "rhodes app myapp" (changing "myapp" by whatever you want).</p>
<p>It will create the application template :</p>
<pre>[thomas@myhost rhodes]$ rhodes app myapp
Generating with app generator:
     [ADDED]  myapp/rhoconfig.txt
     [ADDED]  myapp/build.yml
     [ADDED]  myapp/app/application.rb
     [ADDED]  myapp/app/index.erb
     [ADDED]  myapp/app/index.bb.erb
     [ADDED]  myapp/app/layout.erb
     [ADDED]  myapp/app/loading.html
     [ADDED]  myapp/Rakefile
     [ADDED]  myapp/app/loading.png
     [ADDED]  myapp/app/helpers
     [ADDED]  myapp/icon
     [ADDED]  myapp/app/Settings
     [ADDED]  myapp/public</pre>
<p>Move to that folder (cd myapp) and you can directly try the application by typing "rake run:android"<br />
The first time you run "rake run:android" you will have to choose a virtual device.<br />
Just press enter to let rhodes create a new one and set it up.</p>
<p>Once you've done that, your first application will start in an Android Emulated window.</p>
<p style="text-align: center;"><a target="_blank" title="2011-01-21-214416_1280x705_scrot by Sp00ky31, on Flickr" href="http://farm6.static.flickr.com/5281/5376181859_4ddcf64191_b.jpg"><img src="http://farm6.static.flickr.com/5281/5376181859_4ddcf64191.jpg" alt="2011-01-21-214416_1280x705_scrot" width="500" height="276" /></a></p>
<div class="notice"><strong>Note:</strong> The Android Emulator is pretty slow! It can take up to 3 minutes to boot and start the application</div>
<h3><span id="Building_your_own_application">Building your own application</span></h3>
<p>Hello World is nice, but we want a real application.</p>
<p>As I said in the introduction, we will write a simple Atom feed parser that can display all the entries of an Atom feed in a list and allow the user to click (well, tap!) on an entry title to see its content.<br />
The Atom feed I am taking as example is the following one: <a href="http://www.sdm.keio.ac.jp/en/atom.xml" target="_blank">http://www.sdm.keio.ac.jp/en/atom.xml<br />
</a></p>
<h4><span id="Model">Model</span></h4>
<p>First, we need to create the model of our application.</p>
<p>We will store the entries in a “Feed” model, and each “feed” will have a title, a date, a link, a content and a language.<br />
So we just generate the model automatically with rhodes:</p>
<pre>[thomas@myhost myapp]$ rhodes model Feed title,date,link,content,lang
Generating with model generator:
     [ADDED]  app/Feed/index.erb
     [ADDED]  app/Feed/edit.erb
     [ADDED]  app/Feed/new.erb
     [ADDED]  app/Feed/show.erb
     [ADDED]  app/Feed/index.bb.erb
     [ADDED]  app/Feed/edit.bb.erb
     [ADDED]  app/Feed/new.bb.erb
     [ADDED]  app/Feed/show.bb.erb
     [ADDED]  app/Feed/feed_controller.rb
     [ADDED]  app/Feed/feed.rb
     [ADDED]  app/test/feed_spec.rb</pre>
<p>It generated automatically some files for you.</p>
<p>It basically allows you to create new feeds, edit them, and delete them from the application.<br />
You can have a look to the generated files to understand how Rhodes works.<br />
In our case, we do not need to be able to add, edit et delete manually the entries so I deleted the “edit” and “new” templates (.erb) and removed the edit/update/create/delete methodes from the controller (feed_controller.erb).</p>
<h4><span id="XML">XML</span></h4>
<p>What we want is to populate the database from the entries in the XML file.<br />
So we need a Ruby XML parser. And of course there are plenty of them!<br />
Rhodes supports the popular ReXML and also has its own implementation based on ReXML (but lighter) named RhoXML. Unfortunately RhoXML doesn’t support CDATA and there are CDATA in my feed so we will have to use ReXML.</p>
<p>To add ReXML support, simply add the “rexml” and “set” extensions to the build.yml file at the root of your application:</p>
<pre class="brush:xml">extensions: ["json", "rexml", "set"]</pre>
<p>When we start the application, we want to list all the entries of the feed.<br />
So we want to call the “index” of the “Feed”.</p>
<h4><span id="Startup_application">Startup application</span></h4>
<p>To do so, we just change the rhoconfig.txt file (root of the app) as follows:</p>
<pre># Startup page for your application
start_path = '/app/Feed'</pre>
<h4><span id="def_index">def index</span></h4>
<p>And what we want to do when we start the application is to list the feeds, so let’s do so by editing the index method in the <strong>feed_controller.rb</strong> as follows:</p>
<pre class="brush:ruby">  def index
    @feeds = Feed.find(:all)
    if @feeds.empty? then
      self.update
    else
      render :action => :index, :back => :exit
    end
  end</pre>
<p>If we already loaded the feeds, we just display the list.<br />
If there are no feeds, we update them.</p>
<h4><span id="def_update">def update</span></h4>
<p>You can see the full "update" method at the end of this post.<br />
I just show you the most important part here, the part that loads the elements of the Atom feed into our @feeds variable:</p>
<pre class="brush:ruby">require 'rexml/document'
#@@get_result contains the XML text (as a string)
doc = REXML::Document.new(@@get_result)
REXML::XPath.each(doc,"//feed/entry/") do |e|
  Feed.create(:title => e.elements['title'].text,
              :link => e.elements['link'].attributes['href'],
              :date => e.elements['published'],
              :content => e.elements['content'].texts().at(1),
              :lang => e.elements['content'].attributes['xml:lang'])
end</pre>
<h4><span id="def_refresh">def refresh</span></h4>
<p>We also want to be able to "refresh" the entries because when we restart the application, if you noticed the beginning of the index method, if there are some entries in the database, we just display them directly.<br />
However the database is not destroyed when we stop the application so the entries will be directly displayed without connecting to the internet.<br />
We can add a simple "refresh" method that empty the database and update the entries from the Atom feed:</p>
<pre class="brush:ruby">def refresh
  Feed.delete_all
  redirect :action => :update
end</pre>
<p>Then, when the user tap on a title form the index list, we want to display the content of the feed.<br />
The "show" method has already been implemented for us and we don't need to change it:</p>
<pre class="brush:ruby">def show
  @feed= Feed.find(@params['id'])
  if @feed
    render :action => :show
  else
    redirect :action => :index
  end
end</pre>
<h4><span id="The_Views_index_show">The Views (index, show)</span></h4>
<p>Finally, we only need to change the automatically generated views to display the information we want!<br />
Let see the two most important views: index and show.</p>
<p>The index.erb has a button on the top to manually refresh the entries and a list of all the entries (showing their title):</p>
<pre class="brush:html">
<div class="pageTitle">
  &lt;h1&gt;SDM News&lt;/h1&gt;
</div>
<div class="toolbar">
<div class="regularButton">
    <a class="button" href="<%= url_for :action => :refresh %>">Reload the news</a>
  </div>
</div>
<div class="content">
<ul>
    <% @feeds.each do |feed| %>
<li>
          <a href="<%= url_for :action => :show, :id => feed.object %>">
            <span class="title"><%= feed.title %></span><span class="disclosure_indicator"></span>
          </a>
        </li>

    <% end %>
  </ul>
</div>
</pre>
<p>Result:<br />
<a target="_blank" href="http://www.flickr.com/photos/57795140@N08/5375132714/" title="Android_SDM_News_01 by Sp00ky31, on Flickr"><img src="http://farm6.static.flickr.com/5010/5375132714_f7fd107a5e.jpg" width="500" height="354" alt="Android_SDM_News_01" /></a></p>
<p>The show.erb shows the title, the date, and the content:</p>
<pre class="brush:html">
<div class="pageTitle">
    &lt;h1&gt;<%= @feed.title %>&lt;/h1&gt;
</div>
<div class="content">
<ul>
<li>
          <span class="title"><%= @feed.title %></span>
        </li>
<li>
          <span class="title"><%= @feed.date %></span>
        </li>

        <%= @feed.content %>
  </ul>
</div>
</pre>
<p>Result:<br />
<a target="_blank" href="http://www.flickr.com/photos/57795140@N08/5374534179/" title="Android_SDM_News_04 by Sp00ky31, on Flickr"><img src="http://farm6.static.flickr.com/5007/5374534179_669b9a5ef0.jpg" width="500" height="354" alt="Android_SDM_News_04" /></a></p>
<p>And... that's it!<br />
I added some controls, the multi-language feature and the final application was done!</p>
<h2><span id="Conclusion">Conclusion</span></h2>
<p>In addition to allow you to quickly build mobile applications, Rhodes also supports native powerful APIs of the smartphones.<br />
It is also really cross-platform as you can deploy your application to the 5 top mobile devices (iPhone, Android, Windows Phone, BlackBerry and Symbian).<br />
Ruby is a very user-friendly programming language that is pleasant to use.<br />
The MVC and Database Abstraction layers inherited from Rails make the code easier to maintain.</p>
<p>IDEs that work with Ruby/Rails also work has a charm with Rhodes.<br />
<center><a href="http://farm6.static.flickr.com/5282/5376400789_ea5cbd17d5_b.jpg" target="_blank" title="RubyMine_Screenshot by Sp00ky31, on Flickr"><img src="http://farm6.static.flickr.com/5282/5376400789_ea5cbd17d5.jpg" width="500" height="343" alt="RubyMine_Screenshot" /></a></center></p>
<p>You can find some screenshots of the quickly built application here:<br />
<center><br />
<table>
<tr>
<td>				<div id="gallery-3eb1740c" class="flickr-gallery photoset">
													<div class="flickr-thumb">
									<a href="http://flickr.com/photo.gne?id=5375132714"><img class="photo" title="Android_SDM_News_01" src="http://farm6.static.flickr.com/5010/5375132714_f7fd107a5e_s.jpg" alt="Android_SDM_News_01" /></a>
								</div>
															<div class="flickr-thumb">
									<a href="http://flickr.com/photo.gne?id=5374534045"><img class="photo" title="Android_SDM_News_02" src="http://farm6.static.flickr.com/5208/5374534045_922d564bbb_s.jpg" alt="Android_SDM_News_02" /></a>
								</div>
															<div class="flickr-thumb">
									<a href="http://flickr.com/photo.gne?id=5375132834"><img class="photo" title="Android_SDM_News_03" src="http://farm6.static.flickr.com/5045/5375132834_dcae864617_s.jpg" alt="Android_SDM_News_03" /></a>
								</div>
															<div class="flickr-thumb">
									<a href="http://flickr.com/photo.gne?id=5374534179"><img class="photo" title="Android_SDM_News_04" src="http://farm6.static.flickr.com/5007/5374534179_669b9a5ef0_s.jpg" alt="Android_SDM_News_04" /></a>
								</div>
															<div class="flickr-thumb">
									<a href="http://flickr.com/photo.gne?id=5376782502"><img class="photo" title="2011-01-21-214024_1280x705_scrot" src="http://farm6.static.flickr.com/5169/5376782502_63f29d460d_s.jpg" alt="2011-01-21-214024_1280x705_scrot" /></a>
								</div>
															<div class="flickr-thumb">
									<a href="http://flickr.com/photo.gne?id=5376782608"><img class="photo" title="2011-01-21-214102_1280x705_scrot" src="http://farm6.static.flickr.com/5249/5376782608_ccf6177faa_s.jpg" alt="2011-01-21-214102_1280x705_scrot" /></a>
								</div>
															<div class="flickr-thumb">
									<a href="http://flickr.com/photo.gne?id=5376181733"><img class="photo" title="2011-01-21-214119_1280x705_scrot" src="http://farm6.static.flickr.com/5124/5376181733_c73d4e2bf0_s.jpg" alt="2011-01-21-214119_1280x705_scrot" /></a>
								</div>
															<div class="flickr-thumb">
									<a href="http://flickr.com/photo.gne?id=5376782798"><img class="photo" title="2011-01-21-214319_1280x705_scrot" src="http://farm6.static.flickr.com/5003/5376782798_5b8ec19ac2_s.jpg" alt="2011-01-21-214319_1280x705_scrot" /></a>
								</div>
															<div class="flickr-thumb">
									<a href="http://flickr.com/photo.gne?id=5376181859"><img class="photo" title="2011-01-21-214416_1280x705_scrot" src="http://farm6.static.flickr.com/5281/5376181859_4ddcf64191_s.jpg" alt="2011-01-21-214416_1280x705_scrot" /></a>
								</div>
															<div class="flickr-thumb">
									<a href="http://flickr.com/photo.gne?id=5376400789"><img class="photo" title="RubyMine_Screenshot" src="http://farm6.static.flickr.com/5282/5376400789_ea5cbd17d5_s.jpg" alt="RubyMine_Screenshot" /></a>
								</div>
												<div class="fg-clear"></div>
				</div>
												<div class="fg-clear"></div>
							<script type="text/javascript">
											jQuery(document).ready(function(){
							jQuery("#gallery-3eb1740c .flickr-thumb img").flightbox({size_callback: get_sizes});
						});
										
										//-->
				</script>
			</td>
</tr>
</table>
<p></center></p>
<p>You can download the complete code of the application used as an example in this tutorial here: <a href="http://www.dallagnese.fr/sdm/sdmnews.zip">sdmnews.zip</a>.<br />
From your Android device, you can install the application by clicking on the following APK link: <a href="http://www.dallagnese.fr/sdm/sdmnews.apk">sdmnews.apk</a><br />
You need to allow unknown sources to install this quickly built application (Settings > Applications > Unknown sources) as I do not publish it to the market (yet?).</p>
<p>If you have any comment or question about mobile software development, feel free to comment this post!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dallagnese.fr/computers-it/programming/developpez-rapidement-des-applications-pour-les-mobiles-iphone-android-wp7-bb-symbian-avec-rhomobile-rhodes/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Could not find /etc/localtime, unable to determine host timezone</title>
		<link>http://www.dallagnese.fr/computers-it/unix-linux/could-not-find-etclocaltime-unable-to-determine-host-timezone/</link>
		<comments>http://www.dallagnese.fr/computers-it/unix-linux/could-not-find-etclocaltime-unable-to-determine-host-timezone/#comments</comments>
		<pubDate>Tue, 18 Jan 2011 18:38:35 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[arch]]></category>
		<category><![CDATA[localtime]]></category>
		<category><![CDATA[sdk]]></category>

		<guid isPermaLink="false">http://www.dallagnese.fr/?p=705</guid>
		<description><![CDATA[WARNING: could not find /etc/localtime or /usr/share/zoneinfo/localtime. unable to determine host timezone FIXED SOLVED]]></description>
			<content:encoded><![CDATA[<p>If you ever had a "localtime" problem such as:</p>
<p><code>### WARNING: could not find /etc/localtime or /usr/share/zoneinfo/localtime. unable to determine host timezone</code></p>
<p>It can be fixed simply by copying your timezone localtime file into /etc/localtime.</p>
<p>For example in my case, my timezone is Asia/Tokyo, so I copy the /usr/share/zoneinfo/Asia/Tokyo file into /etc/localtime:</p>
<p><code>sudo cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime</code></p>
<p>And that's it!</p>
<p><span style="text-decoration: underline;">PS:</span> In my case, it was preventing me to start the Android Device Emulator from Rhodes (Rhomobile) on ArchLinux i686. Works as a charm after the previous command!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dallagnese.fr/computers-it/unix-linux/could-not-find-etclocaltime-unable-to-determine-host-timezone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby on Rails: the best web programming framework?</title>
		<link>http://www.dallagnese.fr/computers-it/programming/ruby-on-rails-best-web-programming-framework-review/</link>
		<comments>http://www.dallagnese.fr/computers-it/programming/ruby-on-rails-best-web-programming-framework-review/#comments</comments>
		<pubDate>Sat, 08 Jan 2011 10:12:00 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ror]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.dallagnese.fr/?p=688</guid>
		<description><![CDATA[Overview of Ruby on Rails (RoR) web framework strengths.]]></description>
			<content:encoded><![CDATA[<p>I’ve been programming for some websites mainly in PHP/MySQL for many years now and decided to have a look to what is new in this field.</p>
<p>And there is a very promising one that should have lights on it: Ruby on Rails (or simply “RoR”).<br />
Let’s have an overview on RoR in this post.<br />
<span id="more-688"></span></p>
<div id="toc_container" class="no_bullets"><p class="toc_title">Contents</p><ul class="toc_list"><li><a href="#Introduction">1 Introduction</a></li><li><a href="#Power_of_Rails_through_an_example">2 Power of Rails through an example</a><ul><li><a href="#Retrieving_a_table">2.1 Retrieving a table</a></li><li><a href="#Retrieving_only_one_line_of_the_table">2.2 Retrieving only one line of the table</a></li><li><a href="#Accessing_the_elements_of_this_line">2.3 Accessing the elements of this line</a></li><li><a href="#Validation">2.4 Validation</a></li><li><a href="#References_to_another_table">2.5 References to another table</a></li><li><a href="#More_complex_relation_with_other_tables">2.6 More complex relation with other tables</a></li><li><a href="#Search_and_Find_in_a_table">2.7 Search and Find in a table</a></li><li><a href="#Additional_Information">2.8 Additional Information</a></li></ul></li></ul></div>
<h2><span id="Introduction">Introduction</span></h2>
<p>First, if you’re new to Ruby, don’t worry!<br />
Ruby has been made to be pleasant and easy to program with.<br />
I advise you to read the very nice Ruby introduction <a href="http://www.ruby-lang.org/en/documentation/quickstart/" target="_blank">Ruby in 20 minutes</a> (available in many languages).</p>
<p>In Ruby, the main thing to remind is that everything is object. Even an integer!<br />
So you can have methods and attributes for all your variables (through the classes).</p>
<p>In Rails, we have a MVC architecture, which means we separate the Model, the Controller and the View.<br />
When it goes to web programming, the model can for example define a database table, the view defines what is shown to the visitors (html-based) and the controller is the “glue” between the models and the views.<br />
The obvious advantage of doing so it that your code is not messed up. You don’t have SQL statements messed up with HTML rendering and so on.<br />
It is far easier to maintain than some PHP programming!</p>
<p>But after using Rails for a while, the real reason why I don't want to go back to PHP is <strong>the simplicity of Rails to deal with databases through its "ActiveRecord" class</strong>.<br />
We can create, use and update a database without entering a single SQL statement!<br />
Rails is mapping Ruby Classes to Database Tables.</p>
<h2><span id="Power_of_Rails_through_an_example">Power of Rails through an example</span></h2>
<h3><span id="Retrieving_a_table">Retrieving a table</span></h3>
<p>So let say I have a ruby class "Product" that belongs to ActiveRecord.<br />
This model is mapped to a table called "products" in the database. And the columns of the table are attributes in the model.<br />
So if I have a table "products", I can get its content with a single instruction exempt of any ugly SQL code:</p>
<pre class="brush:ruby">products = Product.all</pre>
<p>That's it! This short code is enough to already appreciate the power of RoR.<br />
With a single line (and it is true that there is nothing else, no definition of Article or whatever before, this can be the first line of a script) we connected to our database and got the content of the table "products".<br />
Because Rails is smart and knows that "Product" refers to the table "products" in the database.<br />
Rails is even smart enough to know that the plural of "category" is not "categorys" but "categories"!<br />
So if we had a table "categories" in our database, to get all the categories it would be:</p>
<pre class="brush:ruby">categories = Category.all</pre>
<h3><span id="Retrieving_only_one_line_of_the_table">Retrieving only one line of the table</span></h3>
<p>Well, getting all the content of a table is good.<br />
But we can also get the last article of the table "products" easily:</p>
<pre class="brush:ruby">lastProduct = Product.last</pre>
<p>And that's it? Yes it is! Why should it be harder though?<br />
Thanks to Rails we don't have to "SELECT * FROM products ORDER BY date DESC LIMIT 1" or something similar <img src='http://www.dallagnese.fr/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<h3><span id="Accessing_the_elements_of_this_line">Accessing the elements of this line</span></h3>
<p>And to access to the content of the last article, we just need to access the attributes.<br />
Let say the table "products" has columns "name" (string), "description" (text) and "price" (int).<br />
We can access these values simply by calling the attributes of the class:</p>
<pre class="brush:ruby">lastProduct.name
lastProduct.description
lastProduct.price</pre>
<h3><span id="Validation">Validation</span></h3>
<p>Validation is also well implemented in Rails and is a strength of this framework.<br />
You can validate forms entered by users very easily.<br />
For example if you want the rate to be between 1 and 5, you just need to add the following code in the Comment model...</p>
<pre class="brush:ruby">validates_inclusion_of :rate, :in =&gt; 1..5,
                              :message =&gt; "rate has to be between 1 and 5"</pre>
<p>...and you will never record a rate which is not between 1 and 5 in the database!<br />
Besides, the visitor who enters by mistake a rate which is not within this range will be warned by the previously specified message.</p>
<h3><span id="References_to_another_table">References to another table</span></h3>
<p>Cool! And what if a column is a reference to another table.<br />
For example let say we can have comments about the product, and the comments of the product are stored in another table called "comments" that has three fields: "product_id" (integer) which is a reference to the product the comment belongs to, "content" (text) which is the comment about the product and a "rate" (int) between 1 and 5 they give to the product.</p>
<p>So the products can have comments and each comment belongs to a product, right?<br />
Well, this relation is very easy to set up with Rails. We need to add one single line in both models (the products model and the comments model).</p>
<p>In the products model, we said a product can have many comments.<br />
Well, Rails talks pretty well English and understands us:</p>
<pre class="brush:ruby">has_many :comments</pre>
<p>In the comments model, we said a comment belongs to a product:</p>
<pre class="brush:ruby">belongs_to :products</pre>
<p>And that's it! The relation is done!<br />
Let say we want to get all the comments of the first product...<br />
If we were working with PHP/MySQL it would have required a few minutes to write the code for it.<br />
With Ruby, it's a few seconds and it's pretty:</p>
<pre class="brush:ruby">comments = Product.first.comments</pre>
<p>And it's done!<br />
As we defined the relation between the comments and the products (adding two lines to the models!), this single line retrieves the comments of the first product.</p>
<h3><span id="More_complex_relation_with_other_tables">More complex relation with other tables</span></h3>
<p>This feature is even more powerful when the relation is more complex.<br />
Let say the comments are written by users that are stored in another table "users".<br />
We want to get the name of the user that wrote the last comment on the first product... (yeah, why not? :p)<br />
We assume there is another column "user" in the table "comments" which is a reference to a user in the table "users", and that this table "users" contains, among others, a column "name" with the user name.</p>
<pre class="brush:ruby">firstProduct = Product.first
lastComment = firstProduct.comments.last
userName = lastComment.user.name
# can be done in 1 call:
userName = Product.first.comments.last.user.name</pre>
<p>Not even one SQL statement. No "JOIN comments USING..." or similar.<br />
Only attribute calls.</p>
<h3><span id="Search_and_Find_in_a_table">Search and Find in a table</span></h3>
<p>OK but how can we find the user whose name is "Thomas"?<br />
Easy!</p>
<pre class="brush:ruby">thomas = User.where(:name =&gt; "Thomas")</pre>
<p>No SQL again (but same as "WHERE name = 'Thomas'").</p>
<p>You will actually have to enter a very small SQL statement when you want to search something.<br />
For example let say we want to retrieve all the products whose description contains "something very interesting".<br />
The code is as follows:</p>
<pre class="brush:ruby">searchTerm = "something very interesting"
results = Product.where("description LIKE '%?%'", searchTerm)</pre>
<p>The question mark in the LIKE statement is replaced by "searchTerm".<br />
This is almost the only time we need to enter some SQL code, and it is not a full SQL code anyway, just a portion of code <img src='http://www.dallagnese.fr/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h3><span id="Additional_Information">Additional Information</span></h3>
<p>I think you saw that with Rails, you can build complete, usable and maintainable websites in a few minutes (or hours).<br />
The best way to see it by yourself is to follow the <a href="http://guides.rubyonrails.org/getting_started.html" target="_blank">Getting Started with Rails Guide</a>.</p>
<p>Why isn't Rails the web framework #1 then??<br />
Because still a very few web hosts provide good Rails hosting for low cost... and most of the web hosts simply do NOT support Rails...<br />
I even myself cannot use Rails as much as I would like to (except on localhost... which is a bit frustrating sometimes!).</p>
<p>This is sad but I hope it will change soon so Rails will get the success it deserves!</p>
<p>I'll write an article about web2py, another framework inspired by Rails which is similar (but not as good as Rails IMHO) but has the advantage of being easier to deploy and accepted by more web hosts.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dallagnese.fr/computers-it/programming/ruby-on-rails-best-web-programming-framework-review/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Served from: dallagnese.fr @ 2012-02-23 03:52:53 by W3 Total Cache -->
