Migrating a PHP application to Ruby on Rails

Being primarily a PHP / Python developer, I decided to tackle something new and take on ruby on rails. It’s been quite a whirlwind, and one of my exersizes was to attempt to migrate a pre-existing PHP application, that already has its database defined, some HTML and so on… to a rails application. This article notes several important points that I ran across along the way that I hope will help anyone who finds themselves in this situation. Arguably, I found this to the the hardest thing to do when studying rails, because as a framework, Rails expects certain naming conventions (such as having an “id” column in every database table), that may not necessarily be present in your existing PHP application.

1. Installation

Installation has certainly gotten a lot easier than some documentation out there suggests. In my case I ended up using RVM since the ruby version in the CentOS repositories was too old and started throwing exceptions. Following this guide gave me a ruby on rails installation with no issues:

https://www.digitalocean.com/community/articles/how-to-install-ruby-on-rails-on-centos-6-with-rvm

2. Migrating the database

My first concern was the database. As I mentioned previously, normally when working with Rails, the framework creates the database with certain expected columns, such as id, date created and date accessed. The php application already had an existing database which did not have this structure. It turns out it is very easy to migrate an existing database into Rails. The trick is not to run and DB migrations (these are not needed because the database is already defined), instead you simply dump the schema by doing the following:

  • Pre-requisite: if you are using a mysql database, make sure to create a new rails app with the mysql driver defined, rather than the default sqlite, by running command:

rails new AppName -d mysql

  • Amend the file in [application_dir]config/database.yml to reference your database. This includes the database name, and credentials to access the database
  • Run the following command to generate the database schema file localted in db/schema.rb:

rake db:schema:dump

3. The server

Coming from a LAMP environment, I am quite used to just loading the appropriate module into apache and that’s it… Rails wasn’t like that, until Passenger came along. With it, the procedure is pretty much the same, for apache simply follow the guide here:

http://www.modrails.com/documentation/Users%20guide%20Apache.html

4. The code…

The actual code itself is very similar to any MVC framework… once you get used to the file locations, and get a handle on all the helpers/keywords you’re good to go. I just wanted to point out a couple of points which took me a while to understand in ruby:

  • The difference between “string” and “symbol”. On the surface, the appear to be doing the same functions, apart from their notation, in which a symbol prepends a colon…. but I couldnt figure out why symbols were needed, until I ran across this very good explanation:

Ruby’s object oriented ways have a cost: lots of objects make for slow code. Every time you type a string, Ruby makes a new object. Regardless of whether two strings are identical, Ruby treats every instance as a new object. You could have “live long and prosper” in your code once and then again later on and Ruby wouldn’t even realize that they’re pretty much the same thing. Here is a sample irb session which demonstrates this fact:

irb> "live long and prosper".object_id
=> -507772268
irb> "live long and prosper".object_id
=> -507776538

Notice that the object ID returned by irb Ruby is different even for the same two strings.

To get around this memory hoggishness, Ruby has provided “symbols.” Symbols are lightweight objects best used for comparisons and internal logic. If the user doesn’t ever see it, why not use a symbol rather than a string? Your code will thank you for it. Let us try running the above code using symbols instead of strings:

irb> :my_symbol.object_id
=> 150808
irb> :my_symbol.object_id
=> 150808

  • Maybe as an artifact of having to migrate existing PHP code, there were some instances where I wanted a form to be able to manipulate both Active Record (database) objects, and non-database objects, from within the same form. In such a case,  it’s easier to use the form_tag which allows you to use arbitrary data inputs/outputs, rather than the form_for, which expects fields in the form to map to active record / model objects