moving to ruby on rails: a love story

31
Moving To Ruby on Rails A Love Story

Upload: casey-dreier

Post on 19-Jan-2015

4.221 views

Category:

Technology


0 download

DESCRIPTION

In January, the Statler Hotel School Web Team made a decision to switch programming languages that power their internal and external websites. After much deliberation, they decided upon Ruby and embraced the Ruby on Rails development framework. In this presentation, Casey Dreier of the SHA web team will discuss the challenges and payoffs of moving to Rails, including migration issues, performance, learning curves, and deployment hurdles.

TRANSCRIPT

Page 1: Moving to Ruby on Rails: A Love Story

Moving To Ruby on RailsA Love Story

Page 2: Moving to Ruby on Rails: A Love Story

Part IRuby and Rails

“Ruby on Rails is astounding. Using it is like watching a kung-fu movie, where a dozen bad-ass frameworks prepare

to beat up the little newcomer only to be handed their asses in a variety of imaginative ways.”

- Nathan TorkingtonO'Reilly Program Chair for OSCON

Page 3: Moving to Ruby on Rails: A Love Story

• An interpreted scripting language, like PHP.

• Created in 1993 by Yukihiro “Matz” Matsumoto

• “I wanted a scripting language that was more powerful than Perl, and more object-oriented than Python.”

• An attempt to create a more natural programming language using “the principle of least surprise”

["item1","item2","item3"].length=> 3

"the quick fox jumped over the lazy dog".length  => 38{:key => 'value'}.length

=> 1

What is Ruby? Basic History

Page 4: Moving to Ruby on Rails: A Love Story

• All classes are open

• Closures and Namespacing

• Excels at Meta-Programming

• Strives for Code Readability and simplicity (Syntactic Sugar)

class Greeter  attr_accessor :name  def say_hi    "hey #{name}"  endend

greeter = Greeter.newgreeter.name = 'Casey'greeter.say_hi

=> "hey Casey"

class Greeter {  private name = null;  public function set_name($name) {    $this->name = $name;  }  public function get_name() {    return $this->name;  }  public function say_hi() {    return "hey " + $this->get_name();  }}

greeter = new Greeter();greeter->set_name('Casey');greeter->say_hi();    => "hey Casey"

Ruby PHP5

What is Ruby? Some Defining Features

Page 5: Moving to Ruby on Rails: A Love Story

What is Ruby? Cool Syntax Examples

(0..20).inject {|sum,n| sum + n * n}=> 2870

Calculate Sum of the Squares of the Integers Between 0 and 20:

(5.minutes + 30.days).from_now   => Fri, 11 Dec 2009 16:09:11 EST -05:00

class Fixnum  # You can, but please don't do this  def +( other )    self - other  endend

Operators are actually Methods (and you can override them)

Time Arithmetic

Page 6: Moving to Ruby on Rails: A Love Story

What is Rails? The Basics

• A powerful, MVC-structured, web application development framework.

• Ruby's Killer App.

• Full Stack Web Application Framework (web server, database, business logic, routing, testing framework.

• Created by Danish programmer David Heinemeier Hannson in 2004 for 37Signals' Basecamp.

• A system written to make programmers' lives happier by solving common problems encountered during web development (i.e. data validation, SQL queries, caching).

Page 7: Moving to Ruby on Rails: A Love Story

What is Rails? Opinions

• Model-View-Controller Archetecture

• Don’t Repeat Yourself (DRY)

• You Aren’t Gonna Need It (YAGNI)

• Keep It Simple, Stupid (KISS)

• Convention Over Configuration

• Elegance of code

• TDD or BDD

Page 8: Moving to Ruby on Rails: A Love Story

What is Rails? Structure

• Model => Database, View => HTML/Layout, Controller => Business Logic

• ORM for your Model to your DB Table

request

widgets/show/1

class WidgetController

def show

@widget =

Widget.find(1)

end

end

class Widget

end

<h2>

<%= @widget.name %>

</h2>

<p>

<b>Size:</b>

<%= @widget.size %>

</p>

show.html.erb widget_controller.rb

widget.rb

Fire Gasket Show

Rails enforces an MVC approach to code.

Page 9: Moving to Ruby on Rails: A Love Story

class Widget < ActiveRecord::Baseend

What is Rails? Code Example

widgets = Widget.find(:all) => “SElECT * FROM widgets”

new_widgets = Widget.all(:order => “created_at DESC”, :conditions => [“created_at >”, 2.weeks.ago] ) => “SELECT * FROM widgets WHERE created_at > ‘10-28-2009’ ORDER BY created_at DESC”

new_widgets.first.name => “My Widget Name”

CREATE TABLE widgets ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), desc VARCHAR(255),

created_at DATE, updated_at DATE

);

SQL

Model

Usage

Page 10: Moving to Ruby on Rails: A Love Story

What Rails Is Not Important Note

* or at least web development problems.

The answer to all life’s problems.*

Page 11: Moving to Ruby on Rails: A Love Story

ExampleBuilding a (very) Basic Web App in 15 minutes

Page 12: Moving to Ruby on Rails: A Love Story

Part IIComing Down to Earth

“cru ext/apache2/libboost_oxt.a ext/apache2/libboost_oxt/boost/*.o ext/apache2/libboost_oxt/oxt/*.o ranlib ext/apache2/libboost_oxt.a -mtune=pentium4 -I/usr/kerberos/include -I/usr/

include/httpd -D_REENTRANT -I/usr/local/include -Wall -g -DPASSENGER_DEBUG -DBOOST_DISABLE_ASSERTS ext/apache2/usr/lib/libaprutil-0.so:

undefined reference to `XML_GetErrorCode' collect2: ld returned 1 exit status

rake aborted! Command failed with status (1): [g++ ext/common/ApplicationPoolServerExecut...]”

- make

Page 13: Moving to Ruby on Rails: A Love Story

• We spend a lot of time fixing old, buggy code.

• Old code very hard to read (not best practices!)

• Wanted to spend more time writing new stuff for our clients instead of fixing old stuff.

• Wanted a way to easily test our code.

• FoxPro is going the way of Esperanto.

Reasons We’re Moving

Page 14: Moving to Ruby on Rails: A Love Story

• The Hotel School currently uses PHP, with some Perl and some large FoxPro systems.

• Database by Oracle.

• Web-centric code goes back to 2000, FoxPro potentially older.

• Version control via Perforce, with custom Development server/Production server Apache environment.

• Custom templating engine written in PHP that hooks into Perforce versioning system for public website at http://www.hotelschool.cornell.edu

Legacy Systems What We’re Starting With

Page 15: Moving to Ruby on Rails: A Love Story

The Approach

A Test Case

Side-by-Side

Rails Takes Over

LaunchPad

Intranet-Focused

Profit!

if success?

if success?

Page 16: Moving to Ruby on Rails: A Love Story

• We needed to answer the basic question, can Rails work in our current setup?

• To test that we decided to redo an old system in Rails.

• Criteria for a good test case:

• Old and buggy code?

• Is it an important system? (If yes, then no).

• Is it relatively atomic? That is, does it interconnect with other systems?

• LaunchPad, in our case.

Step 1: Test Approach

Page 17: Moving to Ruby on Rails: A Love Story

What Rails Likes We Do Not Have

System Rails Likes We Have

DB MySQL/Postgres Oracle

Versioning Git Perforce

DB Table Structurespecific

conventions wild, wild west

Convention Over Configuration

Can Rails Be Configured?

Page 18: Moving to Ruby on Rails: A Love Story

Yes!

Page 19: Moving to Ruby on Rails: A Love Story

• Easily handles legacy database schemas, you just need to add more information about the table.

• Flexible adapters for all major DBs.

• We can set Rails environment settings via Apache (for our Dev and Production differences).

Rails is Very Flexible

class Widget < ActiveRecord::Base set_table_name “ol_widget” set_primary_key “w_id”

belongs_to :owner, :foreign_key => “owner”end

class Owner < ActiveRecord::Base set_table_name “webadmin.widget_owner” set_primary_key “netid”

has_many :widgets, :foreign_key => “owner”end

Page 20: Moving to Ruby on Rails: A Love Story

How Did It Go?

Page 21: Moving to Ruby on Rails: A Love Story

• Short answer, it went well.

• Total time: ~ 7 mo

• Actual coding time: ~ 4 mo

• We proved Rails could work for us!

• Installed Rails on production and dev servers (not trivial).

• Handles deploys successfully.

• Connect to and manipulate legacy DB schemas.

Step 1: Test Approach

Page 22: Moving to Ruby on Rails: A Love Story

• We decided to move forward. Next focus is on our Intranet system, StatlerWire (~50 apps).

• Since we can’t replace all existing apps at once, we need to integrate them somehow.

• We put Rails in a subdirectory in our PHP system, and use a symlink to create a similar URL:

• http://statlerwire.sha.cornell.edu/mywire/admins/... (PHP)

• http://statlerwire.sha.cornell.edu/admins/... (Rails)

• We load the same CSS and use the same HTML layout.

• The client does not know the difference.

Step 2: Side-by-Side

Page 23: Moving to Ruby on Rails: A Love Story

PHP Rails

Page 24: Moving to Ruby on Rails: A Love Story

• Rails currently runs in a subdirectory within the Statlerwire filesystem.

• We were able to mimic behavior of the PHP-based system within our Rails app, and utilize the same database data and structure for Access Control.

• All future development is now done in Rails.

• Anytime significant upgrades are requested in existing systems, we try to take that opportunity to rewrite into Rails.

• This piece-wise approach seems to work pretty well.

Step 2: In Progress...

Page 25: Moving to Ruby on Rails: A Love Story

• I’ve focused mainly on our intranet, but what about our public site?

• Our font-facing website runs a custom-built PHP templating system (Enki) that uses XML for structural markup and inline PHP for DB access/data processing.

• It works very differently than how Rails “likes” to work.

• This is not a system we can convert in pieces, so how can we try to keep things DRY?

• Option 1 (easy): Continue to use Enki as normal, and access our Rails DB via PHP code in front end.

• Option 2 (harder): Instead of accessing the DB directly, attempt to use our Rails system as a Web Service. We can utilize Rails validation, ActiveRecord, etc, via JSON or XML.

Step 2: A Caveat

Page 26: Moving to Ruby on Rails: A Love Story

• We’re going to try Option 2, web services.

• Luckily, Rails makes it easy to support different types of requests at the controller-level.

• Built-in support for REST and HTTP verbiage.

• We’ll let you know how this goes.

Step 2: A Caveat

class WidgetController < ApplicationController def show @widget = Widget.find(params[:id]) respond_to do |format| format.html format.xml { render :xml => @item } format.json { render :json => @item.to_json } end endend

Page 27: Moving to Ruby on Rails: A Love Story

• There’s so much to work with, we have to accept that we’ll be using PHP for a while to come.

• Probably the last thing to go will be the front-facing website.

• Before that, we have a variety of internal FoxPro systems that are large and in charge that need to be rewritten.

• Timeline of 2 - 3 years (realistically).

Step 3: Rails Forever?

Page 28: Moving to Ruby on Rails: A Love Story

• Rails encourages good, well-tested code. Creates an “a priori” environment for future programming working with your code.

• Rails handles a lot of the basic, ugly stuff no one likes to work with.

• Rails embraces the best practices of the new web: AJAX, Logic Abstraction from the View, REST.

• Rails/Ruby is really fun to work (and fall in love) with.

• Large, active community creating plugins, documentation, gems, bug fixes.

In Summary - Benefits

Page 29: Moving to Ruby on Rails: A Love Story

• The learning curve.

• Initial server setup can be difficult.

• Need certain levels of write access to the filesystem by the web server.

• Windows server setup might be difficult.

• If you don’t like MVC, you’re outta luck.

In Summary - Drawbacks

Page 30: Moving to Ruby on Rails: A Love Story

Thanks!

• Gracious support from the Statler Web Team:

• John Cowan

• Dave DeHaan

• Steve Halasz

• Wioletta Holownia

Page 31: Moving to Ruby on Rails: A Love Story

Other Frameworks

• PHP

• CakePHP - http://www.cakephp.org

• CodeIgniter - http://codeigniter.com

• Python

• Pylons - http://pylonshq.com/

• Django - http://www.djangoproject.com/

• Java

• Don’t use Java.

Rails (and Ruby) isn’t the only way to go. Other languages have frameworks boast similar features like MVC, ORM, and Schema Generation.