Ruby for C# Developers


Published on

This was a presentation from 2006 for the St. Louis Code Camp presenting Ruby for C# Developers and showing the power of Ruby interacting with .NET.

Published in: Technology, Education
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Ruby for C# Developers

  1. 1. Ruby for C# Developers Cory Foy St. Louis Code Camp May 6 th , 2006
  2. 2. Overview <ul><li>What is Ruby? </li></ul><ul><li>Ruby Basics </li></ul><ul><li>Advanced Ruby </li></ul><ul><li>Ruby and .NET integration </li></ul><ul><li>Wrap-up </li></ul>
  3. 3. What is Ruby? <ul><li>First released in 1995 by Yukihiro Matsumoto (Matz) </li></ul><ul><li>Object-Oriented </li></ul><ul><ul><li>number = 1.abs #instead of Math.abs(1) </li></ul></ul><ul><li>Dynamically Typed </li></ul><ul><ul><li>result = 1+3 </li></ul></ul>
  4. 4. What is Ruby? <ul><li> </li></ul>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 ='elmo', 4) # elmo is the name, 4 is the age puts p1.inspect # prints “elmo (4)”
  5. 5. Will It Change Your Life? <ul><li>Yes! </li></ul><ul><li>Ok, Maybe </li></ul><ul><li>It’s fun to program with </li></ul><ul><li>And what is programming if it isn’t fun? </li></ul>
  6. 6. Ruby Basics <ul><li>Variables, Classes and Methods </li></ul><ul><li>Properties / Attributes </li></ul><ul><li>Exceptions </li></ul><ul><li>Access Control </li></ul><ul><li>Importing Files and Libraries </li></ul><ul><li>Duck Typing </li></ul>
  7. 7. Ruby Basics - Variables <ul><li>Local (lowercase, underscores) </li></ul><ul><ul><li>fred_j =“Fred”) </li></ul></ul><ul><li>Instance (@ sign with lowercase) </li></ul><ul><ul><li>@name = name </li></ul></ul><ul><li>Class (@@ with lowercase) </li></ul><ul><ul><li>@@error_email = “” </li></ul></ul><ul><li>Constant (Starts with uppercase) </li></ul><ul><ul><li>MY_PI = 3.14 </li></ul></ul><ul><ul><li>class Move </li></ul></ul><ul><li>Global ($ with name) </li></ul><ul><ul><li>$MEANING_OF_LIFE = 42 </li></ul></ul>
  8. 8. Ruby Basics - Classes <ul><li>Class definitions are started with class, are named with a CamelCase name, and ended with end </li></ul>class Move attr_accessor :up, :right def initialize(up, right) @up = up @right = right end end
  9. 9. Ruby Basics - Classes <ul><li>Attributes and fields normally go at the beginning of the class definition </li></ul>class Move attr_accessor :up, :right def initialize(up, right) @up = up @right = right end end
  10. 10. Ruby Basics - Classes <ul><li>initialize is the same concept as a constructor from .NET or Java, and is called when someone invokes your object using to set up the object’s state </li></ul>class Move attr_accessor :up, :right def initialize(up, right) @up = up @right = right end end
  11. 11. Ruby Basics - Methods <ul><li>Methods return the last expression evaluated. You can also explicitly return from methods </li></ul>class Move def up @up end def right return @right end end
  12. 12. Ruby Basics - Methods <ul><li>Methods can take in specified parameters, and also parameter lists (using special notation) </li></ul>class Move def initialize(up, right) @up = up @right = right end end
  13. 13. Ruby Basics - Methods <ul><li>Class (“Static”) methods start with either self. or Class. </li></ul>class Move def self.create return end def Move.logger return @@logger end end
  14. 14. Ruby Basics - Properties <ul><li>Like .NET, Ruby supports the concept of Properties (called Attributes) </li></ul>class Move def up @up end end class Move def up=(val) @up = val end end move = move.up = 15 puts move.up #15
  15. 15. Ruby Basics - Properties <ul><li>Unlike .NET, Ruby provides convenience methods for doing this </li></ul>class Move attr_accessor :up #Same thing as last slide end move = move.up = 15 puts move.up #15
  16. 16. Ruby Basics - Properties <ul><li>You can specify read or write only attributes as well </li></ul>class Move attr_reader :up #Can’t write attr_writer :down #Can’t read end move = move.up = 15 #error d = move.down #error
  17. 17. Ruby Basics - Exceptions <ul><li>Ruby has an Exception hierarchy </li></ul><ul><li>Exceptions can be caught, raised and handled </li></ul><ul><li>You can also easily retry a block of code when you encounter an exception </li></ul>
  18. 18. Ruby Basics - Exceptions process_file =“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. 19. Ruby Basics – Access Control <ul><li>Ruby supports Public, Protected and Private methods </li></ul><ul><li>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 </li></ul>
  20. 20. Ruby Basics – Access Control <ul><li>Access is controlled by using keywords </li></ul>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. 21. Ruby Basics – Access Control <ul><li>Methods can also be passed as args </li></ul>class Move def calculate_move end def show_move end public :show_move protected :calculate_move end
  22. 22. Ruby Basics - Imports <ul><li>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 </li></ul>require ‘calculator’ class Move def calculate_move return @up * Calculator::MIN_MOVE end end
  23. 23. Ruby Basics - Imports <ul><li>There are two types of imports </li></ul><ul><ul><li>require </li></ul></ul><ul><ul><ul><li>Only loads the file once </li></ul></ul></ul><ul><ul><li>load </li></ul></ul><ul><ul><ul><li>Loads the file every time the method is executed </li></ul></ul></ul><ul><li>Both accept relative and absolute paths, and will search the current load path for the file </li></ul>
  24. 24. Ruby Basics – Duck Typing <ul><li>What defines an object? </li></ul><ul><li>How can you tell a car is a car? </li></ul><ul><ul><li>By model? </li></ul></ul><ul><ul><li>By name? </li></ul></ul><ul><li>Or, by it’s behavior? </li></ul>
  25. 25. Ruby Basics – Duck Typing <ul><li>We’d use static typing! So only the valid object could be passed in </li></ul><ul><li>What if my object has the same behavior as a Car? </li></ul>class CarWash def accept_customer(car) end end <ul><li>How would we validate this in .NET or Java? </li></ul>
  26. 26. Ruby Basics – Duck Typing <ul><li>What is this? </li></ul>
  27. 27. Ruby Basics – Duck Typing <ul><li>How about this? </li></ul>
  28. 28. Ruby Basics – Duck Typing <ul><li>What about this? </li></ul>
  29. 29. Ruby Basics – Duck Typing <ul><li>We know objects based on the behaviors and attributes the object possesses </li></ul><ul><li>This means if the object passed in can act like the object we want, that should be good enough for us! </li></ul>
  30. 30. Ruby Basics – Duck Typing <ul><li>Or we could just let it fail as a runtime error </li></ul>Class CarWash def accept_customer(car) if car.respond_to?(:drive_to) @car = car wash_car else reject_customer end end end
  31. 31. Ruby Basics – Unit Tests <ul><li>In a static-typed language, how do we use the compiler? </li></ul><ul><ul><li>Find misspellings </li></ul></ul><ul><ul><li>Find improper usage </li></ul></ul><ul><ul><li>Enforce contracts </li></ul></ul><ul><ul><li>Find missing semicolons </li></ul></ul>
  32. 32. Ruby Basics – Unit Tests <ul><li>What is a Unit Test? </li></ul><ul><li>“ In computer programming, a unit test is a procedure used to validate that a particular module of source code is working properly.” (Wikipedia) </li></ul><ul><li>Sounds like our compiler is just a unit testing mechanism! </li></ul>
  33. 33. Ruby Basics – Unit Tests <ul><li>Ruby comes built in with a Unit Testing framework – Test::Unit </li></ul><ul><ul><li>Create individual tests </li></ul></ul><ul><ul><li>Create test suites </li></ul></ul><ul><ul><li>Invoke our tests and suites </li></ul></ul><ul><li>Using this framework and Test-Driven Development, we can have a high confidence level in our code </li></ul>
  34. 34. Ruby Basics – Unit Tests <ul><li>Let’s build a toaster! </li></ul><ul><li>Should be able to have toasting levels set </li></ul><ul><li>Should heat the bread based on the toasting levels </li></ul><ul><li>Different breads have different cooking times. </li></ul>
  35. 35. Ruby Basics – Unit Tests <ul><li>Let’s start with a basic test </li></ul>class TestToaster < Test::Unit::TestCase def test_toast_bread toaster = bread = toaster.heat_level = 5 toaster.toast(bread) assert_equal(“Nicely toasted”, bread.status) end end
  36. 36. Ruby Basics – Unit Tests <ul><li>And run it </li></ul>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. 37. Ruby Basics – Unit Tests <ul><li>Next, let’s build our objects to allow our test to run </li></ul>class Toaster attr_accessor :heat_level def toast(bread) end end class WonderBread attr_accessor :status end
  38. 38. Ruby Basics – Unit Tests <ul><li>And run them </li></ul>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. 39. Ruby Basics – Unit Tests <ul><li>Finally, let’s make the test pass </li></ul>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. 40. Ruby Basics – Unit Tests <ul><li>We then keep writing tests to drive the behavior of the code we want to write </li></ul><ul><li>A side benefit is we get a suite of regression tests for our code </li></ul>
  41. 41. Ruby Basics – Unit Tests <ul><li>How did the compiler help us again? </li></ul><ul><ul><li>Find misspellings (Unit Tests) </li></ul></ul><ul><ul><li>Find improper usage (Unit Tests) </li></ul></ul><ul><ul><li>Enforce contracts (Duck Typing) </li></ul></ul><ul><ul><li>Find missing semicolons (No semicolons! ;)) </li></ul></ul>
  42. 42. Advanced Ruby - Modules <ul><li>Blocks and Iterators </li></ul><ul><li>Modules </li></ul><ul><li>Mixins / Inheritance </li></ul><ul><li>Reflection </li></ul><ul><li>Other Goodies </li></ul>
  43. 43. Advanced Ruby - Blocks <ul><li>A block is just a section of code between a set of delimters – { } or do..end </li></ul>{ puts “Ho” } 3.times do puts “Ho “ end #prints “Ho Ho Ho”
  44. 44. Advanced Ruby - Blocks <ul><li>Blocks can be associated with method invocations. The methods call the block using yield </li></ul>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. 45. Advanced Ruby - Blocks <ul><li>Methods can act like the using statement from .NET using blocks </li></ul>def*args) conn =*args) if block_given? yield conn #passes conn to the block conn.close #closes conn when block finishes end return conn end
  46. 46. Advanced Ruby - Iterators <ul><li>Iterators in Ruby are simply methods that can invoke a block of code </li></ul><ul><li>Iterators typically pass one or more values to the block to be evaluated </li></ul>
  47. 47. Advanced Ruby - Iterators <ul><li>Pickaxe Book, page 50 </li></ul>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. 48. Advanced Ruby - Modules <ul><li>At their core, Modules are like namespaces in .NET or Java. </li></ul>module Kite def end end module Plane def end end
  49. 49. Advanced Ruby - Mixins <ul><li>Modules can’t have instances – they aren’t classes </li></ul><ul><li>But Modules can be included in classes, who inherit all of the instance method definitions from the module </li></ul><ul><li>This is called a mixin and is how Ruby does “Multiple Inheritance” </li></ul>
  50. 50. Advanced Ruby - Mixins module Print def print puts “Company Confidential” yield end end class Document include Print #... end doc = doc.print { “Fourth Quarter looks great!” } -> Company Confidential -> Fourth Quarter looks great!
  51. 51. Advanced Ruby - Reflection <ul><li>How could we call the Length of a String at runtime in .NET? </li></ul>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. 52. Advanced Ruby - Reflection <ul><li>In Ruby, we can just send the command to the object </li></ul>myString = “Test” puts myString.send(:length) # 4
  53. 53. Advanced Ruby - Reflection <ul><li>We can also do all kinds of fancy stuff </li></ul>#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. 54. Ruby Basics – Other Goodies <ul><li>RubyGems – Package Management for Ruby Libraries </li></ul><ul><li>Rake – A Pure Ruby build tool (can use XML as well for the build files) </li></ul><ul><li>RDoc – Automatically extracts documentation from your code and comments </li></ul>
  55. 55. Ruby and .NET <ul><li>Why? </li></ul><ul><ul><li>Provide Scripting ability in your apps </li></ul></ul><ul><ul><li>Quickly prototype </li></ul></ul><ul><ul><li>Class Introspection </li></ul></ul><ul><li>What about JScript.NET? </li></ul><ul><ul><li>Ruby is cross platform </li></ul></ul><ul><ul><li>JScript might be better choice </li></ul></ul>
  56. 56. Ruby and .NET <ul><li>Three projects in the works </li></ul><ul><li>Ruby to .NET Bridge </li></ul><ul><ul><li> </li></ul></ul><ul><li>MS Funded Ruby CLR project </li></ul><ul><ul><li> </li></ul></ul><ul><li>RubyCLR </li></ul><ul><ul><li> </li></ul></ul>
  57. 57. Ruby and .NET <ul><li>Bridge Example </li></ul><ul><ul><li>Basic Arrays </li></ul></ul><ul><ul><li>Interacting with Objects </li></ul></ul><ul><ul><li>Creating Forms </li></ul></ul><ul><ul><li>Attaching to Events </li></ul></ul>
  58. 58. Ruby Resources <ul><li>Programming Ruby by Dave Thomas (the Pickaxe Book) </li></ul><ul><li> </li></ul><ul><li> </li></ul><ul><li> </li></ul><ul><li> </li></ul><ul><li> </li></ul><ul><li> </li></ul>