Moving to Ruby on Rails: A Love Story
-
Upload
casey-dreier -
Category
Technology
-
view
4.222 -
download
0
description
Transcript of Moving to Ruby on Rails: A Love Story
Moving To Ruby on RailsA 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
• 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
• 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
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
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).
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
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.
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
What Rails Is Not Important Note
* or at least web development problems.
The answer to all life’s problems.*
ExampleBuilding a (very) Basic Web App in 15 minutes
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
• 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
• 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
The Approach
A Test Case
Side-by-Side
Rails Takes Over
LaunchPad
Intranet-Focused
Profit!
if success?
if success?
• 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
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?
Yes!
• 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
How Did It Go?
• 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
• 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
PHP Rails
• 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...
• 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
• 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
• 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?
• 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
• 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
Thanks!
• Gracious support from the Statler Web Team:
• John Cowan
• Dave DeHaan
• Steve Halasz
• Wioletta Holownia
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.