KEMBAR78
Ruby for C# Developers | PPT
Ruby for C# Developers Cory Foy http://www.cornetdesign.com St. Louis Code Camp May 6 th , 2006
Overview What is Ruby? Ruby Basics Advanced Ruby Ruby and .NET integration Wrap-up
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
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)”
Will It Change Your Life? Yes! Ok, Maybe It’s fun to program with And what is programming if it isn’t fun?
Ruby Basics Variables, Classes and Methods Properties / Attributes Exceptions Access Control Importing Files and Libraries Duck Typing
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 Basics – Duck Typing What is this?
Ruby Basics – Duck Typing How about this?
Ruby Basics – Duck Typing What about this?
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 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 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 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 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 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 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 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 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 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]: <&quot;Nicely toasted&quot;> expected but was <nil>. 1 tests, 1 assertions, 1 failures, 0 errors
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 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 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! ;))
Advanced Ruby - Modules Blocks and Iterators Modules Mixins / Inheritance Reflection Other Goodies
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”
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
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
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
Advanced Ruby - Iterators Pickaxe Book, page 50 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
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
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”
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!
Advanced Ruby - Reflection How could we call the Length of a String at runtime in .NET? String myString = &quot;test&quot;; int len =  (int)myString .GetType() .InvokeMember(&quot;Length&quot;, System.Reflection.BindingFlags.GetProperty,  null, myString, null); Console.WriteLine(&quot;Length: &quot; + len.ToString());
Advanced Ruby - Reflection In Ruby, we can just send the command to the object myString = “Test” puts myString.send(:length)  # 4
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 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 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 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 and .NET Bridge Example Basic Arrays Interacting with Objects Creating Forms Attaching to Events
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

Ruby for C# Developers

  • 1.
    Ruby for C#Developers Cory Foy http://www.cornetdesign.com St. Louis Code Camp May 6 th , 2006
  • 2.
    Overview What isRuby? Ruby Basics Advanced Ruby Ruby and .NET integration Wrap-up
  • 3.
    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
  • 4.
    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 &quot;#@name (#@age)&quot; # 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)”
  • 5.
    Will It ChangeYour Life? Yes! Ok, Maybe It’s fun to program with And what is programming if it isn’t fun?
  • 6.
    Ruby Basics Variables,Classes and Methods Properties / Attributes Exceptions Access Control Importing Files and Libraries Duck Typing
  • 7.
    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
  • 8.
    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
  • 9.
    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
  • 10.
    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
  • 11.
    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
  • 12.
    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
  • 13.
    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
  • 14.
    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
  • 15.
    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
  • 16.
    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
  • 17.
    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
  • 18.
    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
  • 19.
    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
  • 20.
    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
  • 21.
    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
  • 22.
    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
  • 23.
    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
  • 24.
    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?
  • 25.
    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?
  • 26.
    Ruby Basics –Duck Typing What is this?
  • 27.
    Ruby Basics –Duck Typing How about this?
  • 28.
    Ruby Basics –Duck Typing What about this?
  • 29.
    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!
  • 30.
    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
  • 31.
    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
  • 32.
    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!
  • 33.
    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
  • 34.
    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.
  • 35.
    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
  • 36.
    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
  • 37.
    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
  • 38.
    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]: <&quot;Nicely toasted&quot;> expected but was <nil>. 1 tests, 1 assertions, 1 failures, 0 errors
  • 39.
    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
  • 40.
    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
  • 41.
    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! ;))
  • 42.
    Advanced Ruby -Modules Blocks and Iterators Modules Mixins / Inheritance Reflection Other Goodies
  • 43.
    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”
  • 44.
    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
  • 45.
    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
  • 46.
    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
  • 47.
    Advanced Ruby -Iterators Pickaxe Book, page 50 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
  • 48.
    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
  • 49.
    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”
  • 50.
    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!
  • 51.
    Advanced Ruby -Reflection How could we call the Length of a String at runtime in .NET? String myString = &quot;test&quot;; int len = (int)myString .GetType() .InvokeMember(&quot;Length&quot;, System.Reflection.BindingFlags.GetProperty, null, myString, null); Console.WriteLine(&quot;Length: &quot; + len.ToString());
  • 52.
    Advanced Ruby -Reflection In Ruby, we can just send the command to the object myString = “Test” puts myString.send(:length) # 4
  • 53.
    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)
  • 54.
    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
  • 55.
    Ruby and .NETWhy? Provide Scripting ability in your apps Quickly prototype Class Introspection What about JScript.NET? Ruby is cross platform JScript might be better choice
  • 56.
    Ruby and .NETThree 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
  • 57.
    Ruby and .NETBridge Example Basic Arrays Interacting with Objects Creating Forms Attaching to Events
  • 58.
    Ruby Resources ProgrammingRuby 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