Wednesday, December 19, 2007

Introducing Rails 2 - Part 1.5

For those who have tried to install rails 2.0 and find it acting all weird afterward. It's probably because you updated rails with an out of date rubygem

if you are having trouble with rails 2.0, you can do a quick check on your rubygem by typing

gem --version

If it's version 0.9.4 or below, then you should update your gem and reinstall rails. You can update rubygem with the following command

gem update --system

This might take awhile, so be patience. After it's done, check the version again by doing

gem --version

and make sure it's at version 1.0.0. Now you can reinstall rails 2.0 by typing

gem install rails --include-dependencies

There's a problem with the old gem, it will only install the rails core for you but skipping ActiveRecord, ActiveResource, and Rake

For those who have an existing project, go into environment.rb and make the following change

RAILS_GEM_VERSION = '2.0.2'

give this a try, it works for me


J

Monday, December 17, 2007

Introducing Rails 2 - Part 1

W and I have decided to upgrade to rails 2.
All you need to do is to type in this command in your command prompt

gem install rails -y --source http://gems.rubyonrails.org

and ruby gem will handle the rest.
After the upgrade is completed, type

rails -- version
to check if it's 2.0.1
and that's it, you are done :)

So before we look at all the new features in rails 2, let's first find out
what has been removed.

1. @params should be replaced with params
eg: params[:data] instead of @params[:data]

the same goes for @flash, @session, @env, and @request

2. find_all & find_first should be replaced with find(:all) & find(:first)
eg: User.find(:all) instead of User.find_all
User.find(:first) instead of User.find_first
note: User.find_by_xxx is still valid

3. acts_as is gone
they are plugins now

4. render_partial should be replaced with render :partial
eg: render :partial => "user" instead of render_partial "user"

5. start_form_tag and end_form_tag should be replaced with form_for or form_tag

you can check out the api description here
http://api.rubyonrails.com/classes/ActionView/Helpers/FormHelper.html#M000920

6. Pagination is gone
mainly cause it sucks (slow)

on the bright side, there are faster and cleaner pagination plugins available
the one I'm currently using is called will_paginate and it can be found at
http://rock.errtheblog.com/will_paginate


7. components are gone

8. Database adapters are gone
you can download the one you need at
http://svn.rubyonrails.org/rails/adapters/

if you are planning to upgrade, go through your codes
to make sure it's rails 2 compatible.

if you are not sure, you might want to upgrade to rails 1.2.6 first,
where they marked everything that will be removed as a deprecated function.


J

Debugging

So the debugging that comes packaged with RadRails is a little bit slow... well, not even a little bit slow, it's tremendously slow! I had run the debugger before, and I guess I was doing some simple debugging and so I didn't notice the time it took to start and debug (or maybe I just expected it to be slow?).

Anyways, I was running some new test cases and they were failing when they should have been working. So, I pulled out my trusty debugger, and lo and behold, it took so long that I left and came back about 5 minutes later and it was still running! I ended up stopping it, as my friend, J, had reported a similar problem earlier. He told me about some sort of fast-debugging gem. I quickly googled it and found a gem that works with RadRails.

Instructions can be found here:

http://www.aptana.com/docs/index.php/Fast_Rails_Debugging_using_Aptana_Rails_IDE

If you ever need to debug, a huge time-saving suggestion would be to install this gem and use it!


W

Monday, December 10, 2007

Getting the Year from a Date Column

So I was running our unit tests that we had created after moving to PostgreSQL, and I found a database specific error. I am so thankful for our unit tests now. Instead of testing the application by hand, all I had to do was click the mouse button. I can't stress enough how important tests are.

Anyways, what I had in my code was a specific call to a MySQL function called YEAR(). This apparently was not supported by PostgreSQL. After doing some searching, I found another SQL function called EXTRACT. This seems to be supported in several databases including MySQL, PostgreSQL, and Oracle(9i, 10g, 11g).

For my purposes of getting the year, I used:

EXTRACT(YEAR FROM date_column)

More information about the EXTRACT function can be found here.

Hopefully this helps anyone having database portability problems!


W

Sunday, December 9, 2007

PostgreSQL

RoR is amazing! I love how everything is so encapsulated! After doing another project where I switched from MySQL to PostgreSQL, I wanted to try out PostgreSQL with RoR. Usually, this means a lot of backend changes and porting SQL scripts.

However, with RoR, it requires very little changes. Firstly, your whole entire database structure is created using the migration scripts. Since the migration scripts are written in Ruby, nothing has to change about these scripts. Any database access from your application do not need to be changed since they are also in Ruby. Then you must be asking, "What needs to be changed?" Very simple, the database.yml needs to be changed. Actually, only 1 line of it. This is the configuration file that RoR uses to access the database. Just change:

adapter: mysql

to

adapter: postgresql

That's it! Really, that's it! Well, actually, no... you need to install the Ruby gem that handles PostgreSQL. Since I'm developing on a Windows machine, I just enter:

>gem install ruby-postgres

For more information, you can visit this page:

http://wiki.rubyonrails.org/rails/pages/PostgreSQL

And truly, that's it. If you don't believe me, give it a try! Changing your database couldn't be easier!


W

Saturday, December 8, 2007

Back to Fun

So I'm back from my short hiatus... and one definite problem I see off the bat is... I practically forgot what I was doing before my leave... Well, that's just interesting. It took me a day or two to re-orientate myself and get back into things. Lesson learned: Before leaving something that you're halfway through, leave notes for yourself to remind you what you were doing... cause really... we all have a little alzheimer every so often.

Now that I'm back into things, this blog should be a little more colourful again. Stay tuned!


W

Tuesday, November 27, 2007

Hiatus

I'd like to say a short sorry for being away for such a long time. We are both on a short hiatus due to an overwhelming work load. Please be patient with us, as things should be up and running again in a few days... I hope...

W

Tuesday, November 6, 2007

Validation Caution

So I was implementing validation rules on a model the other day,
and the model started acting really weird afterward :(

Sometimes it'll save the object, most of the time it wont.
After a few attempts to locate the problem, I noticed
an object can be saved if the boolean attribute
is set to true, but won't save if it's set to false.

turns out this is what's causing all the troubles

validates_presence_of

don't use validate_presence_of to evaluate any boolean or numeric type variables,
because if you a value of 0, it'll be treated as nil

instead, this is what I changed it to

validates_inclusion_of attributes, :in => [true, false]

and life is wonderful once again

J

Monday, November 5, 2007

RESTful Cheatsheet

I found a very handy cheatsheet that I would like to share with you guys. I've found it very helpful through my RESTful endeavors:

http://topfunky.com/clients/peepcode/REST-cheatsheet.pdf

Enjoy!

W

Friday, November 2, 2007

collection_singular_ids

I was taking a look at the has_and_belongs_to_many and has_many relationships.

Going through the documentation, I found the ability to retrieve the ids of each relationship. Sometimes that can be useful. So I decided to give it a try. Here is the documentation:

collection(force_reload = false) - returns an array of all the associated objects. An empty array is returned if none are found.
...
collection_singular_ids - returns an array of the associated objects ids

I was thinking... "Alright, this looks simple enough". Thinking that collection would allow me to write:

user.cars

So, I thought if I wanted to retrieve the ids, I could do this:

user.cars_singular_ids

Boy was I wrong! I got an "undefined method" error... at this moment in time, I'm thinking "HUH?!?! But the documentation says so..."

After looking around for a bit, I found the solution. Apparently, it's all in the lack of punctuation! What the documentation is really saying is that we should specify the singular form of the collection with _id attached, like so:

user.car_ids

This reminds me of a joke I once heard of which explained the importance of punctuation:

A professor wrote "A woman without her man is nothing" on the chalkboard and told his students to punctuate it. All the males in the classroom wrote "A woman, without her man, is nothing." However, all the females in the classroom wrote "A woman: without her, man is nothing!" Clearly, punctuation is important!

Hope you guys don't have to bump your heads against the wall for as long as I did!

W

Vector Graphics

I've always liked the look of vector graphics. I always find the effects produced from these images to be captivating and appealing. Hence, since we're playing around with RoR, I thought it would be neat to generate some vector graphics.

At first, I thought this would be a daunting task for someone who rarely touches any type of art. I was almost scared to open up Photoshop CS2. However, I found a website that was enough to get me going. I had to play around with the functions of CS2 first though to get the hang of things since I'm a total newbie! However, as I became more comfortable with what I was doing, I found that it was pretty simple to create vector graphics.

I'll post up some examples of my work later!

W

Wednesday, October 31, 2007

Unit Test Runs All Methods

So I've been doing A LOT of testing recently, and it's starting to piss me off that I can't just run the method that I'm currently working on. It would be nice if I could, but I haven't been able to find out how to do it.

Currently, I'm solving this problem myself by adding flags to my setup method which will decide which methods to call. This is definitely a hack until I can find out how to do this properly... If I do find a solution, I'll be sure to let you know!


W

Tuesday, October 30, 2007

Ruby Content Assist Solution

So I finally came across a fix for this problem. Apparently, it's a RadRails bug!

I guess I'll have to wait for the fix to come out... T.T

W

Monday, October 29, 2007

Tags Solution

Ok... so what is our solution to tags? We're going to do our own! This is gonna be interesting...

Basically, we couldn't decide which acts_as_taggable we should use, and started digging deeper into both. The plugin had very little documentation, and we needed a rich association table. However, it supported polymorphic associations, but we decided that we wouldn't require such a feature. The gem was lacking in some specifics that we wanted to implement, so in the end, we decided on our own version that was customized to our tastes.

I did come across one called acts_as_taggable_on_steroids which is based on the acts_as_taggable plugin. It includes some nice caching features that are built-in. I think we'll have to read up on caching, as it might be a good idea to cache tags!

Well... it'll definitely be interesting developing our own tags. We'll see what happens!

W

Saturday, October 27, 2007

Eclipse Log Files

Just in case if anyone is wondering how to view Eclipse's log files, here's a FAQ:

http://wiki.eclipse.org/FAQ_Where_can_I_find_that_elusive_.log_file%3F

W

Ruby Content Assist

When developing on any IDE, a nice feature is the content assist. This means you can hit a few key strokes, and a list of possible classes, methods, variables, etc are shown that match what you have typed so far.

In Eclipse for RoR, this feature is also available. You hit CTRL + Spacebar, and the Ruby Content Assist fires and gives you a list of possible completions. However, for some reason, on my setup, this doesn't work. Instead, I get a lovely "Problem Occurred" error pop-up... lovely! The error states that I have a java.lang.NullPointerException. Great... now what?

I've been looking around and seeing how to solve this, and so far, I've come up with nothing. My friend, J, seems to have no problems at all... damn this sucks! I'm so tempted to just reinstall Eclipse + Aptana + RadRails again... sigh... I'll keep you updated as to how I manage to solve this.

W

Tags

So I was reading up on polymorphic associations, and came across tags. Apparently, RoR has support for tags. So I dug a little deeper, and got myself into a mess!

Here's the thing. RoR has something called acts_as_taggable. You create the relevant tables, and then you label a model as taggable, and it can then be tagged. Pretty neat huh? However, there are 2 acts_as_taggable. Yes... 2! And they both have the same name! One is a gem, the other a plugin.

What's interesting is that the plugin was written after the gem, but by the creator of Rails (David Heinemeier Hansson)! So now, I'm having troubles about which one should be used... there seems to be a split in the community, since the gem is documented, but apparently the plugin has good features, but isn't documented. Furthermore, the plugin is the way to go for extending RoR.

Not sure what to do, so I'll research some more, and hopefully come to a decision.


W

Monday, October 22, 2007

RadRails: Data Perspective

So I tried using this new perspective that comes with RadRails. It allows you to view your database in Eclipse and allows for SQL queries and executions.

However, I was running into some problems with my database.yml file. It kept giving me an error about invalid YAML syntax. However, RoR connects perfectly fine with it. I finally figured out that the Data Perspective doesn't like eRb.

I had previously DRYed up our database.yml by specifying our login information in one place, and then attaching it to the end of the hash for each database. However, the Data Perspective doesn't recognize this type of syntax and reports an error. After reverting our database.yml to its original form, the Data Perspective came to life.

Hope this helps anyone else running into the same problem.


W

Sunday, October 21, 2007

Another Introduction

Hello, this is J, I'm W's imaginary friend, hidden within the right side of his brain which he seldom uses. That's why I don't speak very often :) Currently my main focus is on the front-end of the website which includes graphic and user interface designs, generating CSS and RHTML files.

For my designs, I try to follow the principle of parsimony (less is better) It is my goal to keep everything as simple and direct as possible, eliminating any unnecessary feature.

Based on past observations, a complex design often leads to a lot of confusion (doesn't matter how impressive it looks). Moreover, the main purpose of UI is not to impress but connect users with business logics behind the scene. (the ugly stuff) Hence the more simple and direct the design, the easier it'll be to understand, and the more effective it becomes.

Enough words said, I think it's time for me to start doodling, I will keep you all updated with my work, so stay tuned!

J

Aptana + RadRails

WOW! Screw my previous environment setup... this new one rules! A combination of Aptana and RadRails, both as plugins to Eclipse rocks! Everything is integrated by installing just 2 plugins.

I haven't fooled around too much with Aptana yet, but there are many features supporting frontend development.

RadRails just blows me away! Everything is integrated into this little baby here. Features including generation of controllers, models, etc, rake commands, unit tests, database views... the list goes on. If you were to set up an IDE for RoR, this combination is the one you want. Try it out! I'm still exploring and I'm already blown off my feet!

Get it here:

http://www.aptana.com/download_rails_rdt.php

and follow the RadRails section in their documentation wiki:

Saturday, October 20, 2007

Testing

When developing anything, testing should always be at the forefront of your mind. After all, without testing, how are you supposed to know whether your application works or not? We certainly don't want our users to let us know about bugs. Hence, testing should always be a continuous task as you continue to build your application.

RoR provides a built-in testing environment for testing your application. So far, I've gone through testing our models. I will move onto controllers later. What I've seen so far is really nice! Firstly, RoR uses another database for testing. It does not touch your development database, nor your production database. By issuing the command:

>rake db:test:clone_structure

RoR will automatically clone the structure of your development database and create a new one according to your database configuration file. That's pretty neat. Next up, populating your database is easy as well. In RoR, there are things called fixtures which can be called before testing. These files populate your database with data that you need in order to run your test cases and are removed after testing.

For Unit Testing, all the models are available to you for testing. There are setup and teardown methods you can write that setup any pre-test things, such as creating files, and that remove anything post-test.

Testing is done in a usual manner using various assert methods. Errors and Failures are reported when running the tests.

One pretty neat thing is that RoR keeps statistics on your tests, such as code coverage. Simply type in:

>rake stats

and a table of statistics will appear. I will look into that a little more, but it should really helpful in determining whether or not the test cases are covering enough ground.

With RoR, it is very easy to design, code, and test in a continuous manner. Testing is so easy and integrated that it actually feels like its worth testing while I'm testing! That's rare!

W

RESTful Development

Along with Named Routes comes RESTful development. So what is RESTful development? Well, I'm not even going to try to define here. A very uesful link is the RestWiki, which talks about what REST is.

I must say that I quite agree with this architectural style. I can see how it really tries to create uniform interfaces so that different applications are able to communicate with each other. Especially over the World Wide Web, as they say, RESTful development is almost natural. However, I think we have been developing so long without REST that it will be awkward at first to get use to.

RoR, along with Named Routes, supports RESTful development quite well. Each controller, because it represents a model, will have a Named Route corresponding to it. Furthermore, this restricts the controller to having only 7 actions. Yes, that's correct. I said 7!

index
show
new
create
edit
update
destroy

This seems very limiting, but when we're dealing with 1 particular resource, these 7 actions are, in fact, quite sufficient. There may be 1 or 2 extra actions that may need to be customized, but usually, these will be all you need!

With REST, it is easy for other applications to easily hook into yours. With RoR, it is easy to return different formats to the caller, such as XML. A really nice explanation can be found here:

http://softiesonrails.com/tags/rest

Well, have fun poking around REST. Hopefully, this will convince you to try it out for yourselves as well!

W

Friday, October 19, 2007

Named Routes

The RoR project contains a file called routes.rb.

This file handles the routing of URIs to controller actions. Simple things can be done like routing www.mypage.com to some home page, or even a login page such as www.mypage.com/login by doing:

map.connect '', :controller => 'user', :action => 'login'

Something cool here can be done:

map.login 'login', :controller => 'user', :action => 'login'

gives us a shortcut to the login page. In our controller or in our view, we can now use:

login_url # www.mypage.com/login
login_path #/login


This is pretty neat as we can change all our paths to variable paths, and so if we decide to change the structure of our URIs, we only need to change them in one place!

Slightly more advanced are things called Named Routes. By specifying:

map.resources :user

we get several shortcuts that can be used in conjunction with HTTP methods (GET, POST, PUT, UPDATE). For example, we know have access to:

edit_user_path(@user.id)

which will give us the path /user/:id;edit. This will automatically call the edit action in our user controller. Pretty cool huh?

For more in depth information, try this website:

http://ryandaigle.com/articles/2006/08/01/whats-new-in-edge-rails-simply-restful-support-and-how-to-use-it

Named Routes naturally give way to RESTful development. If you don't know what that is, I recommend reading up on it. I'll talk about it sometime later, so check back!

W

Thursday, October 18, 2007

Views

Finally... Views! RoR has done many neat things on the frontend to make development life much easier. There are lots of nice methods that are provided so that you don't have to write pure HTML code. These methods can be found in the API.

Your views also have access to variables found in the controller. As RoR works a lot on implicitness, the view corresponds to the controller action with the same name. For example, if you have edit.rhtml, then the corresponding controller action is named edit. Any variables using @var is accessible in the view. This allows you to separate out all the logic to the controller, and the view is truly used only for displaying purposes! Awesome!

Another wonderful thing about RoR Views, is that there are a bunch of helpers. What do I mean by this? For instance, if you have an object, say @user representing a User model, which usually has a profile, the view can use helpers that automatically link up a form with your @user object. A nice little manual describes this:

http://railsmanual.com/module/ActionView::Helpers::FormHelper/form_for

I've noticed that this makes development a lot more efficient! Just wonderful!

W

Controllers

Next up: Controllers! Being a developer who has had experience with PHP and the .NET framework... controllers are an entirely new beast to me. At the beginning, we were thinking of splitting up login functions, view functions, etc. into separate controllers. This was the way we were used to thinking about modularizing: taking sections of the application and having that chunk as one module. It took us a while to figure out that this was completely wrong!

A controller contains a number of actions. Actions. The name in itself tells you immediately that a controller should have several actions that are common. I guess we knew that, but we didn't know what the commonality was between the actions, until an epiphany hit us. The controller controls a particular model and all the actions corresponding to this model. Therefore, the way that we had first separated our application was based on ACTIONS! Completely wrong! Reconfiguring our minds, it became clear that we should have things like a User Controller, which would handle all of the actions that were to be done on a user, such as save, edit, create, etc.

Thinking in this way takes somewhat of a brain twist, as it is completely different than what we have been taught. However, this definitely opens up new doors and new things to learn. I'm not quite sure I can say I'm fully excited about this, but I can definitely see how all the code can be separated and easily found.

We'll have to play around with the controller some more to get a feel for things, but in the mean time, hang tight and we'll keep you updated!

W

Wednesday, October 17, 2007

Models

RoR, being a model-view-controller architecture, obviously has something called a model. These things are just plain out awesome. They are objects that map directly to the database tables. Their fields are the database columns. And the best part is, the mapping is implicit... no massive amounts of XML mapping files! It's clean, it's intuitive, and best of all, less code to write (which translates to less time spent and less errors)!

Inside the class definition, fields don't need to be specified, as it is implicit that all database columns of the table are part of the model, and getters and setters are all implicit. This means no long list of getters and setters for each field! If there's something special that needs to be done for getters and setters, it's very convenient to just override the defaults.

So what is specified within the class definition then? Well, one of the things is table relations. For example, there are one-to-many relations. Imagine a Store has many Items.

In the Store class definition, you would add:

has_many :items

In the Item class definition, you would add:

belongs_to :store

These two lines specify the one-to-many relation between Store and Item. If you had a Store object and you wanted the items, it would be as simple as:

@items = @store.items

This will retrieve you all of the Items associated to the particular Store object.

There are all sorts of things you can do with relations, and this is only the tip of the iceberg.

Another wonderful thing you can do in models is validation! And RoR has a set list of validation functions that can be used for just about anything. Basically, before a model is saved, RoR runs a validation check on the fields. If any of it fails, the model is not saved, and error messages are created, which can then be displayed to the user. It's absolutely wonderful! Validation methods can be checked out here:

http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html

Well, that's the general idea of models. It's a very nice way to interface with the database while keeping code writing to a minimal. Enjoy!

W

Monday, October 15, 2007

Migration

Wow. I must say, I'm totally impressed with this feature in RoR. I'm so glad that this feature comes packaged with RoR, and that I don't have to do this manually. I remember writing SQL files to do this, and keeping them organized so I can run them later. It was a pain in the ass!

When I heard about this built-in feature, my draw dropped. Migration basically allows you to manipulate the database in any way. Each file has an 'up' and a 'down'. The 'up' makes changes to your database, whereas the 'down' rolls back your changes. Each file is also versioned, so you can quickly move your database to any previous version, or blow it away entirely and rebuild it. This is nice when you first start developing because there may be some kinks in the database design. However, when the database becomes stable and the application is ready to use, user data is stored, and this data should not be lost when adding upgrades or rollbacks. The migration files give a nice way to centralize and remember the changes and their rollbacks.

RoR has an online API documentation that is quite useful and can be found here:

http://api.rubyonrails.org/

Under ActiveRecord::Migration contains all of the possible things you can do with migration.

By running:

>rake db:migrate VERSION=0

RoR will rollback all changes in reverse version order. This will basically blow away your database. If your keen, you'll notice that VERSION is specified, and that the number refers to the version you want your database to be at. So if you're currently on version 10, you could have VERSION=9, which would rollback the changes when version 10 was made.

By running:

>rake db:migrate

RoR will apply all the versions after the current version of your database. Hence, if you have a fresh database, using this command will get you up to speed right away!

Migration... Check it out if you have time. I hope it'll blow you away as much as it did for me.

W

RoR Development Environment

So we've decided on using Eclipse as our IDE for developing in RoR. I managed to find this sweet little site that lists everything you need to get started:

http://www.napcs.com/howto/railsonwindows.html

It gives all the plugins that one might want for having a nice IDE.

One thing that we discovered was that for DBEdit, we could use Eclipse's software update to handle the plugin. The URI is:

http://dbedit.sourceforge.net/update

However, I have been unable to get this to work properly. I'm not sure why. I got so pissed off that I had everything working except for DBEdit, that I removed Eclipse entirely, and started from scratch... but in the end, I'm still scratching my head! But my buddy, J , has been able to get his working perfectly fine... I'm a little envious!

For our database, we've settled for MySQL at the moment. It should serve us well for development at least. MySQL fits like a glove for RoR. It's like a match made in heaven!

We're also using SVN for our code repository and TortoiseSVN for Windows. However, we find that the SubClipse plugin for Eclipse is so good that TortoiseSVN is currently unused!

After working out a few kinks here and there, like getting authentication for our SVN repository working (we forgot to remove the read for anonymous users), the development environment is running smoothly.

Well, time to go play with it some more.

W

Sunday, October 14, 2007

The Journey Begins

So, my friend and I have decided to experiment with something relatively new. No, I'm not talking about something kinky. I'm talking about:

Ruby on Rails (RoR)

We played around with it about a year ago, and it was quite underdeveloped. We took a rest for about a year, and now, we're back to experimenting.

We've decided to try to create a web application using RoR, and see how far it can take us. Hopefully, we won't have to pull all of our hair out by the end of this.

As both of us are not experienced RoR developers... this journey can be likened to the blind leading the blind. Either way, it should be a memorable ride.

So, sit back and relax, and enjoy our journey to enlightenment.


W