Ruby + Ruby on Rails

Sam Ruby

In case you were curious…

No relation

Ruby

Elevator Pitch

Smalltalk 80

Source: wikipedia

Preface

Myth: scripting languages can’t scale

Basics

Ruby has all the basics that one would expect from a programming language…

assigments

name = "Sally";
tip = price * 0.15;

if statements

if answer != 'yes' then
  STDOUT.puts('Why not?');
end

loop statements

while Time.now.hour < 17
  Kernel.sleep(60);
end

total = 0;
for item in [ 6, 17, 3 ]
  total += item;
end

functions

def circumference(radius)
  return 2 * Math::PI * radius;
end

classes

class Dog
  def bark()
    STDOUT.puts("woof!");
  end
end

fifi = Dog.new();
fifi.bark();

Note: new is a method on the Dog object.

Back to the 80's

“New” stuff

Everything is an object

Integer.parseInt(“5”)
“5”.to_i
Math.abs(-5)
-5.abs

type-checking is dynamic

def dump(results) results << "abc" results << "xyz" end
Examples of classes that implement ”<<” :

everything is modifyable

Facilities enabled by being able to modify existing classes:

message-sending

Facilities enabled by being able to capture messages:

Block Example

sorted_employees = employees.sort_by {|e| e.lastname}

Block Usages

Closure Example

def high_paid_employees(employees, limit) employees.select{|e| e.salary > limit} end

Part III

Incredible shrinking code

Hello World!

class Greeting { public static void main(String args[]) { System.out.println(“Hello World!”); } }
Kernel::puts(“Hello World!”);

Hello World!

class Greeting { public static void main(String args[]) { System.out.println(“Hello World!”); } }
puts(“Hello World!”);

Hello World!

class Greeting { public static void main(String args[]) { System.out.println(“Hello World!”); } }
puts(“Hello World!”)

Hello World!

class Greeting { public static void main(String args[]) { System.out.println(“Hello World!”); } }
puts “Hello World!”

Omittable

Beans

class Point { private int x; public int getX() { return this.x; } public void setX(int x) { this.x = x; } }

Beans

class Point def x() return @x end def x=(x) @x=x end end

Beans

class Point { private float x; public float getX() { return this.x; } public void setX(float x) { this.x = x; } }
class Point def x() @x end def x=(x) @x=x end end

Beans

class Point { private float x; public float getX() { return this.x; } public void setX(float x) { this.x = x; } }
class Point attr_accessor :x end

Beans

class Point { private float x,y; public float getX() { return this.x; } public void setX(float x) { this.x = x; } public float getY() { return this.y; } public void setY(float y) { this.y = y; } }
class Point attr_accessor :x, :y end

Rails

class Entry < ActiveRecord::Base acts_as_tree :order => “updated” validates_presence_of :updated end
Note:

Expansion

Like a macro, that one line expands to define the following methods:

Exceptions

Scanner sc = new Scanner(new File(args[0])); while (sc.hasNextLine()) { System.out.println(sc.nextLine()); } sc.close();

Exceptions

Scanner sc = new Scanner(new File(args[0])); try { while (sc.hasNextLine()) { System.out.println(sc.nextLine()); } } finally { sc.close(); }

Exceptions

f = open(ARGV[0]) begin for line in f.readlines puts line end ensure f.close end

Exceptions

open(ARGV[0]) do |f| f.each {|line| puts line} end

Ruby

Elevator Pitch

Memes

Memes
  • Agile
  • Pragmatic
  • Less Code

Summary

Dynamic languages

Begs the Question?

Does the world need another Smalltalk, even with a bettter syntax and all?

Result

Rails

Elevator Pitch

Memes

MVC(Model View Controller)

Ruby on Rails

Ruby on Rails

Flow

Simple flow:

JDBC

Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/mysql";
Connection con = DriverManager.getConnection(url,"root", "");

Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(
  "SELECT * FROM users where clue>0");
while ( rs.next() ) {
  System.out.println(rs.getString("name"));
}

JNDI

Context env = 
  (Context) new InitialContext().lookup("java:comp/env");
DataSource pool = (DataSource) env.lookup("jdbc/test");
Connection conn = pool.getConnection();

Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(
  "SELECT * FROM users where clue>0");
while ( rs.next() ) {
  System.out.println(rs.getString("name"));
}

PHP

mysql_connect("localhost", "root", "");
mysql_select_db("db");

$result = mysql_query("SELECT * FROM users where clue>0");
while ($row=mysql_fetch_array($result)) {
  print $row["name"];
}

Rails

for user in User.find(:all, conditions=>'clue>0')
  puts user.name
end

database

development:
  adapter: mysql
  database: customer_development
  host: localhost
  username: root
  password:
test:
  adapter: mysql
  database: customer_test
  host: localhost
  username: root
  password:
production:
  adapter: mysql
  database: customer_production
  host: localhost
  username: root
  password:

Example of Conventions

Junit:
import junit.framework.TestCase; public class ThingTester extends TestCase { public void testSomeThing() throws Exception { assertEquals(“non-zero”, 0, ””.length()); } }

Extend a class, and follow a convention, and voila instant test cases

Example of Conventions

But what if you were in a language where introspection and reflection weren’t read-only?

User

class User < ActiveRecord::Base end user = User.find :first puts user.name

view (html)

<% for entry in @entries %>

  <%= entry_header entry %>
  <div class="blogbody">
    <%= entry_title entry %>
    <%= entry.summary or entry.content %>
    <%= sigline entry %>
  </div>
<% end %>

view (xml)

@entries.each do |entry|
  xml.entry do
    xml.title   entry.title
    xml.link    :href=>url_for(entry.by_date)
    xml.id      entry.atomid
    xml.updated entry.updated.iso8601
    xml.author  { xml.name entry.author.name } if entry.author
    xml.content do
      xml.div :xmlns=>'http://www.w3.org/1999/xhtml' do
        xml << entry.content
      end
    end
  end
end

Controller

class BlogController < ApplicationController
  def posts
    paginate :conditions => 'parent_id IS NULL',
      :order_by => 'published DESC'
  end
end

Function tests

def test_index
  get :posts, :path=>['index.html']
  assert_response :success
  assert_template 'html'

  # only two posts have titles
  assert_tag :tag=>'div', :attributes => {:class => 'content'},
    :children => {:count => 2, :only => {:child => {:tag => 'h3'} } }
end

“There exists a div tag in the response with class=’content’ which has exactly two child ‘h3’ tags”

Summary

“Rails is a full-stack, open-source web framework in Ruby for writing real-world applications with joy and less code than most frameworks spend doing XML sit-ups” – http://www.rubyonrails.org/

Rails

Elevator Pitch

Language?

Could Rails be done in other languages?

To date, it seems that Rails is often immitated, never duplicated

LINQ

Elevator Pitch

Video

Arms Race

Java vs C#

First example

Side-by-side
var q = c.customers .where(c => c.City == “London”) .select(c => c.CompanyName);
q = c.customers. find_all {|c| c.city == “London”}. map {|c| c.companyName}

Syntatic Sugar

var q = c.customers .where(c => c.City == “London”) .select(c => c.CompanyName);
var q = from c in customers where c.City == “London” select c.CompanyName;

Syntatic Sugar

LINQ

Elevator Pitch

Ruby on Rails Adoption

Outlook

References