Ruby for C# Developers - Cory Foy

burnwholeInternet και Εφαρμογές Web

5 Φεβ 2013 (πριν από 4 χρόνια και 7 μήνες)

206 εμφανίσεις

Cory Foy

http://www.cornetdesign.com

Tampa Code Camp

July 15th, 2006

Ruby for C# Developers


Ruby for C# Developers

Cory Foy

http://www.cornetdesign.com

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Overview


What is Ruby?


Ruby Basics


Advanced Ruby


Ruby and .NET integration


Wrap
-
up

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

What is Ruby?


First released in 1995 by Yukihiro
Matsumoto (Matz)


Object
-
Oriented


number = 1.abs #instead of Math.abs(1)


Dynamically Typed


result = 1+3

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

What is Ruby?


http://www.rubygarden.org/faq/entry/show/3


class Person


attr_accessor :name, :age # attributes we can set and retrieve


def initialize(name, age) # constructor method


@name = name # store name and age for later retrieval


@age = age.to_i


# (store age as integer)


end


def inspect # This method retrieves saved values


"#@name (#@age)" # in a readable format


end


end



p1 = Person.new('elmo', 4) # elmo is the name, 4 is the age


puts p1.inspect # prints “elmo (4)”

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Will It Change Your Life?


Yes!


Ok, Maybe


It’s fun to program with


And what is programming if it isn’t fun?

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Variables, Classes and Methods


Properties / Attributes


Exceptions


Access Control


Importing Files and Libraries


Duck Typing

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics
-

Variables


Local (lowercase, underscores)


fred_j = Person.new(“Fred”)


Instance (@ sign with lowercase)


@name = name


Class (@@ with lowercase)


@@error_email = “testing@test.com”


Constant (Starts with uppercase)


MY_PI = 3.14


class Move


Global ($ with name)


$MEANING_OF_LIFE = 42

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics
-

Classes


Class definitions are started with
class,
are named with a CamelCase
name, and ended with
end

class Move


attr_accessor :up, :right




def initialize(up, right)


@up = up


@right = right


end

end

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics
-

Classes


Attributes and fields normally go at the
beginning of the class definition

class Move


attr_accessor :up, :right




def initialize(up, right)


@up = up


@right = right


end

end

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics
-

Classes


initialize

is the same concept as a
constructor from .NET or Java, and is called
when someone invokes your object using
Move.new

to set up the object’s state

class Move


attr_accessor :up, :right




def initialize(up, right)


@up = up


@right = right


end

end

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics
-

Methods


Methods return the last expression
evaluated. You can also explicitly return from
methods

class Move


def up


@up


end



def right


return @right


end

end

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics
-

Methods


Methods can take in specified
parameters, and also parameter lists
(using special notation)

class Move


def initialize(up, right)


@up = up


@right = right


end

end

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics
-

Methods


Class (“Static”) methods start with
either
self.

or
Class.


class Move


def self.create


return Move.new


end



def Move.logger


return @@logger


end

end

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics
-

Properties


Like .NET, Ruby supports the concept
of Properties (called Attributes)

class Move


def up


@up


end

end

class Move


def up=(val)


@up = val


end

end

move = Move.new

move.up = 15

puts move.up #15

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics
-

Properties


Unlike .NET, Ruby provides
convenience methods for doing this

class Move


attr_accessor :up #Same thing as last slide

end

move = Move.new

move.up = 15

puts move.up #15

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics
-

Properties


You can specify read or write only
attributes as well

class Move


attr_reader :up #Can’t write


attr_writer :down #Can’t read

end

move = Move.new

move.up = 15 #error

d = move.down #error

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics
-

Exceptions


Ruby has an Exception hierarchy


Exceptions can be caught, raised and
handled


You can also easily retry a block of
code when you encounter an exception

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics
-

Exceptions

process_file = File.open(“testfile.csv”)


begin
#put exceptional code in begin/end block


#...process file


rescue IOError => io_error


puts “IOException occurred. Retrying.”


retry
#starts block over from begin


rescue => other_error


puts “Bad stuff happened: “ + other_error


else
#happens if no exceptions occur


puts “No errors in processing. Yippee!”


ensure
# similar to finally in .NET/Java


process_file.close unless process_file.nil?

end

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Access Control


Ruby supports Public, Protected and
Private methods


Private methods can
only

be accessed
from the instance of the object, not from
any other object, even those of the
same class as the instance

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Access Control


Access is controlled by using keywords

class Move


private


def calculate_move


end


#Any subsequent methods will be private until..


public


def show_move


end


#Any subsequent methods will now be public

end

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Access Control


Methods can also be passed as args

class Move


def calculate_move


end



def show_move


end



public :show_move


protected :calculate_move

end

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics
-

Imports


To use a class from another file in your
class, you must tell your source file
where to find the class you want to use


require ‘calculator’

class Move


def calculate_move


return @up * Calculator::MIN_MOVE


end

end

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics
-

Imports


There are two types of imports


require


Only loads the file once


load


Loads the file every time the method is executed


Both accept relative and absolute paths, and
will search the current load path for the file

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Duck Typing


What defines an object?


How can you tell a car is a car?


By model?


By name?


Or, by it’s behavior?

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Duck Typing


We’d use static typing! So only the valid
object could be passed in


What if my object has the same
behavior as a Car?

class CarWash


def accept_customer(car)



end

end


How would we
validate this in
.NET or Java?

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Duck Typing


What is
this?

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Duck Typing


How
about
this?

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Duck Typing


What
about
this?

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Duck Typing


We know objects based on the
behaviors

and
attributes

the object
possesses


This means if the object passed in can
act like the object we want, that should
be good enough for us!

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Duck Typing


Or we could just let it fail as a runtime
error

Class CarWash


def accept_customer(car)


if car.respond_to?(:drive_to)


@car = car


wash_car


else


reject_customer


end


end

end

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Unit Tests


In a static
-
typed language, how do we
use the compiler?


Find misspellings


Find improper usage


Enforce contracts


Find missing semicolons

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Unit Tests


What is a Unit Test?


“In computer programming, a unit test is
a procedure used to validate that a
particular module of source code is
working properly.” (Wikipedia)


Sounds like our compiler is just a unit
testing mechanism!

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Unit Tests


Ruby comes built in with a Unit Testing
framework


Test::Unit


Create individual tests


Create test suites


Invoke our tests and suites


Using this framework and Test
-
Driven
Development, we can have a high
confidence level in our code

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Unit Tests


Let’s build a toaster!


Should be able to have
toasting levels set


Should heat the bread based on
the toasting levels


Different breads have different
cooking times.

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Unit Tests


Let’s start with a basic test

class TestToaster < Test::Unit::TestCase


def test_toast_bread


toaster = Toaster.new


bread = WonderBread.new


toaster.heat_level = 5


toaster.toast(bread)


assert_equal(“Nicely toasted”, bread.status)


end

end

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Unit Tests


And run it

root@dilbert $ruby testtoaster.rb

Loaded suite testtoaster

Started

E

Finished in 0.0 seconds.



1) Error:

test_toast_bread(TestToaster):

NameError: uninitialized constant TestToaster::Toaster


testtoaster.rb:4:in `test_toast_bread'


1 tests, 0 assertions, 0 failures, 1 errors

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Unit Tests


Next, let’s build our objects to allow our
test to run

class Toaster


attr_accessor :heat_level




def toast(bread)




end

end

class WonderBread


attr_accessor :status

end

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Unit Tests


And run them

root@dilbert $ruby testtoaster.rb

Loaded suite testtoaster

Started

F

Finished in 0.093 seconds.



1) Failure:

test_toast_bread(TestToaster) [testtoaster.rb:10]:

<"Nicely toasted"> expected but was

<nil>.


1 tests, 1 assertions, 1 failures, 0 errors

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Unit Tests


Finally, let’s make the test pass

class Toaster


def toast(bread)


bread.status = “Nicely toasted”


end

end

root@dilbert $ruby testtoaster.rb

Loaded suite testtoaster

Started

.

Finished in 0.0 seconds.


1 tests, 1 assertions, 0 failures, 0 errors

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Unit Tests


We then keep writing tests to drive the
behavior of the code we want to write


A side benefit is we get a suite of
regression tests for our code

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Unit Tests


How did the compiler help us again?


Find misspellings (Unit Tests)


Find improper usage (Unit Tests)


Enforce contracts (Duck Typing)


Find missing semicolons (No semicolons!
;))

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Advanced Ruby
-

Modules


Blocks and Iterators


Modules


Mixins / Inheritance


Reflection


Other Goodies

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Advanced Ruby
-

Blocks


A block is just a section of code
between a set of delimters


{ } or
do..end

{ puts “Ho” }


3.times do


puts “Ho “

end #prints “Ho Ho Ho”

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Advanced Ruby
-

Blocks


Blocks can be associated with method invocations.
The methods call the block using
yield

def format_print


puts “Confidential. Do Not Disseminate.”


yield


puts “© SomeCorp, 2006”

end


format_print { puts “My name is Earl!” }


-
> Confidential. Do Not Disseminate.


-
> My name is Earl!


-
> © SomeCorp, 2006

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Advanced Ruby
-

Blocks


Methods can act like the
using

statement from
.NET using blocks

def MyConnection.open(*args)


conn = Connection.open(*args)


if block_given?


yield conn #passes conn to the block


conn.close #closes conn when block finishes


end



return conn

end

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Advanced Ruby
-

Iterators


Iterators in Ruby are simply methods
that can invoke a block of code


Iterators typically pass one or more
values to the block to be evaluated

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Advanced Ruby
-

Iterators

def fib_up_to(max)


i1, i2 = 1, 1


while i1 <= max


yield i1


i1, i2 = i2, i1+i2 # parallel assignment


end

end


fib_up_to(100) {|f| print f + “ “}


-
> 1 1 2 3 5 8 13 21 34 55 89


Pickaxe Book, page 50

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Advanced Ruby
-

Modules


At their core, Modules are like
namespaces in .NET or Java.

module Kite


def Kite.fly


end

end


module Plane


def Plane.fly


end

end

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Advanced Ruby
-

Mixins


Modules can’t have instances


they
aren’t classes


But Modules
can

be included in
classes, who inherit all of the instance
method definitions from the module


This is called a
mixin

and is how Ruby
does “Multiple Inheritance”

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Advanced Ruby
-

Mixins

module Print


def print


puts “Company Confidential”


yield


end

end


class Document


include Print


#...

end


doc = Document.new

doc.print { “Fourth Quarter looks great!” }


-
> Company Confidential


-
> Fourth Quarter looks great!

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Advanced Ruby
-

Reflection


How could we call the Length of a
String at runtime in .NET?

String myString = "test";

int len = (int)myString



.GetType()



.InvokeMember("Length",
System.Reflection.BindingFlags.GetProperty,



null, myString, null);

Console.WriteLine("Length: " + len.ToString());

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Advanced Ruby
-

Reflection


In Ruby, we can just send the
command to the object

myString = “Test”

puts myString.send(:length) # 4

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Advanced Ruby
-

Reflection


We can also do all kinds of fancy stuff

#print out all of the objects in our system

ObjectSpace.each_object(Class) {|c| puts c}


#Get all the methods on an object

“Some String”.methods


#see if an object responds to a certain method

obj.respond_to?(:length)


#see if an object is a type

obj.kind_of?(Numeric)

obj.instance_of?(FixNum)

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Basics


Other Goodies


RubyGems


Package Management for
Ruby Libraries


Rake


A Pure Ruby build tool (can use
XML as well for the build files)


RDoc


Automatically extracts
documentation from your code and
comments

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby and .NET


Why?


Provide Scripting ability in your apps


Quickly prototype


Class Introspection


What about JScript.NET?


Ruby is cross platform


JScript might be better choice

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby and .NET


Three projects in the works


Ruby to .NET Bridge


http://rubydotnet.sourceforge.net/


MS Funded Ruby CLR project


http://www.plas.fit.qut.edu.au/rubynet/


RubyCLR


http://rubyforge.org/projects/rubyclr

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby and .NET


Bridge Example


Basic Arrays


Interacting with Objects


Creating Forms


Attaching to Events

Ruby for C# Developers

Tampa Code Camp

July 15th, 2006

Cory Foy

http://www.cornetdesign.com

Ruby Resources


Programming Ruby by Dave Thomas (the
Pickaxe Book)


http://www.ruby
-
lang.org


http://www.rubyforge.org


http://www.rubycentral.org


http://www.ruby
-
doc.org


http://www.rubygarden.org


http://www.stlruby.org