Riding Ruby On Rails installer

Written by Walter

Well open a terminal then paste the following:

sudo mkdir -p /usr/local/src
sudo chgrp admin /usr/local/src
sudo chmod -R 775 /usr/local/src
cd /usr/local/src
curl -O http://walter.schreppers.com/files/install_ror.tar.gz
tar -xzvf install_ror.tar.gz
./install.sh

This will install latest, ruby, rails and mysql on a fresh macbook!
In /usr/local you find all install scripts that do the job.
Running tiger or panther, on leopard ruby should already be running rails as I've heard). The install scripts are based on good tutorial found here : ruby on rails manual install tutorial. I updated everything to latest version (except mysql, kept current version). And patches are also installed for ruby with this mysql. Anyway, the above gives me a sweet setup on my macbook and after a day of reading my first webshop version is already up and running (see below)

Edit the install.sh with favorite editor if running on ppc to download the correct powerpc binary (the install.sh is kept really simple to read, just comment out or in any options)




After the install.sh is all finished, a testapp is created and run with mongrel.
Just point your browser to http://localhost:3000 to view the running test site.



Above is my first rails project (also running on localhost through mongrel). A webshop which I'm building for upcomming projects (yes rails proven to be agile and fast in developing).

I did have a lot of help+code to startup by reading the agile web development with rails book ofcourse. After spending friday and saturday reading some rails and ruby tutorials my webshop is running in development nicely on my macbook, including unit and functional tests of the models and controllers, ajax goodness for the shopping cart+fall back when javascript is disabled).

For me this book is perfect, not only that in their first real world project they used to show the rails framework happens to be just the thing I wanted to build, a simple and clean webshop (originally I planned to do it with php and or drupal). Ruby is a language comparable to php accept it has some more bells and whisles built in the language which makes coders, including me, happy :). But the real kicker is the rails framework. A really proper worked out model/view/controller pattern (similar to java frameworks) helps in keeping all code in the right place and minimize code duplication. The ActiveRecord which handles ORM (object relational mapping) This means in plain english mysql tables are mapped automatically to ruby classes and vice versa letting you work with these objects instead of writing sql queries.
Example:

product = Product.find(params[:id])

With product being a mysql table with key id.
We have a model class Product with a static member find that returns a product instance. Instead of writing the select * from product where id=... we can just call Product.find and get back that specific product. We did not have to implement the find method either it was nicely inherited from the base class ActiveRecord.

There is more going on (like using belongs_to and has_many calls which automatically creates a join table in sql behind the scenes to get you a path from one model to another in an efficient way) But as a small summary to get you into the model/controller/view way of working. Another advantage is that this code is easily deployed on mysql, sqllite, postgress etc without changing a single line of code since all the queries etc are done behind the scenes in the ActiveRecord framework.

Also the whole unit and functional testing framework is baked right in there as well as the ajax functionality which redefines the web today (people mostly know ajax from google websites such as gmail etc :) ).

Though I do have to mention there is still work to be done with ajax support I bumped into the well known problem where I want an ajax style link to subtract elements from my shopping cart (instead of a button). This works fine and dandy with javascript/ajax, accept when user turns off the javascript we want our site to fall-back to plain http post/get's instead of ajax. So happens I had to google around and found the following solution :

<%= link_to_remote( image_tag("trash.png"),
:url => { :action => :delete_from_cart, :id => cart_item.product } ,
:href => { :action => :delete_from_cart, :id => cart_item.product }
)
%>

Because the link_to_remote creates standard an a href with target '#' we run into problems when javascript is turned off.
Normally we use ajax style posts like this:
<% form_remote_tag :url => { :action => :add_to_cart, :id => product } do %>
<%= submit_tag "In winkelwagentje" %>
<% end %>

This creates the button 'In winkelwagentje' with ajax+fall_back goodness. The problem with my cart was that I did not want a button but a regular href with an image of a trash can (i used a small minus sign as seen in screenshot for now because I did not have the time to find a nice trash can icon :S ) .

Though adding the extra href option does solve this problem (letting me use a href instead of a button and it supports fall back now) It is not clean and also we violate the post/get order of things in fall_back mode but people have been doing that all the time in php so it just works for now is a good summary :)


Now after the praise some things I noticed (I'm not through the book, just started on chapter 17 about internals of ActiveRecord itself).
Ruby seems keen on getting rid of code duplication (a good thing ofcourse) and therefore has some cewl tricks up its sleeve.

1. Filters, this reminds me of a talk I followed at K.U.Leuven about aspect oriented programming. It basically allows you to add default code to any or some methods of your class.

Example:
class StoreController < ApplicationController
before_filter :find_cart, :except => :empty_cart #this calls find_cart before any method except empty_cart

Means run the find_cart method before you run any method except for empty_cart.
They did this to initilize a cart instance so that we dont have to do it seperately in every method.
The find_cart method is nothing more than this:

def find_cart
@cart = (session[:cart] ||= Cart.new)
end

All seems well. First critic on this. Well this normally goes inside a constructor doesn't it? Why the strange construct here, it is not necessary.

Luckily there is another example:

class LoginController < ApplicationController
layout "admin"

before_filter :authorize, :except => :login #alles moet authorized zijn behalve voor login actie zelf

This redirects you to the login page whenever you are not logged in and trying to access one of the administrative functionality of the site.

My critic on these constructs is that it seems fine and dandy. But what happens if my class is filled with 20 or 30 of these filters?
We get a spaghetti that is allmost impossible to debug or trace how the code is actually running. And we did not really need this kind of construct to do it that way. But yes it is less typing to do it and that fits the 'agile' definition :).

Everyone seems to ignore that issue for now (same as the aspect oriented people I guesse :D).

2. In testing framework we find yet another construct for setting the private locals. Apparantly it has a setup method (which is called before the others, a bit like the index method in the controllers):

class AdminControllerTest < Test::Unit::TestCase
fixtures :products

def setup
@controller = AdminController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new

@first_id = products(:first).id
end

Here it is used to initialize controller, request, response locals before actually running the tests. Again, why yet another way of doing this. Ok it is cool that there are many ways of doing it. But wait, was that not just the critique the author had for c++ (okay he states orthogonal programming language aspects). In short yes in c++ there are too many ways of doing the same thing which results that after years of experience you still read code and go, hey I have not seen this way of doing that before. Which is true, I do have that same experience in C++. But we are seeing the same already happening right here in the rails framework built on top of the 'flawless' ruby language :D. Anyway just like to point out that nothing is perfect, that's all :).

And for the record, yes ruby is cewl, yes it will take over the web and will make SAP Netweaver lovers spin heads some day in the near future :D. Then again, the sap developers are getting rich so easily, who blames em for going with the 'cash' way instead of the 'better' way to develop software :D




Back to archive