Some Ruby concepts explained for .net developers

I'm normally a .net developer, it's been my bread and butter for the past seven years and will be for several more. But it's also important for me to keep in touch with other languages out there, including Ruby. Here's my personal cheat sheet to remember naming conventions.

Method Names are lower case and use underscores, as do Method Arguments. The result of the last expression is automatically returned - there is no direct equivalent of void, although nil can serve that purpose.

def my_method(some_argument)
  1 + 1 # implicitly returns 2.
end

Local Variables are also lower case with underscores, and no special var keyword is required to declare them.

def some_method
  my_variable = 2
  1 + my_variable
end

Instance Variables - that is, a non-static field in a class - are prefixed with @. Somewhat surprisingly, they can be declared within a method.

class MyClass
  def do_stuff
    @test = 4
  end

  def testing
    2 + @test
  end
end

myc = MyClass.new
puts myc.do_stuff
puts myc.testing

This outputs 4 and 6. If I remove the puts myc.do_stuff line, this throws an error: test.rb:8:in '+': nil can't be coerced into Fixnum (TypeError).

Constructors are methods called initialize:

class MyClass
  def initialize(initial_value)
    @test = initial_value
  end

  def testing
    return 2 + @test
  end
end

myc = MyClass.new(3)
puts myc.testing

This outputs 5. Instance Variables are private by default, but Ruby has three special ways to declare a variable as public: attr_accessor, attr_reader and attr_writer. Changing the class to this:

class MyClass
  attr_reader :test

  # .. rest as above
end

myc = MyClass.new(3)
puts myc.test # outputs 3
myc.test = 4  # undefined method 'test='

So attr_reader is like public dynamic Test { get; private set; } in .net, while attr_writer is like { private get; set; } and attr_accessor is like { get; set; }.

To create property getters and setters, just create methods. In the end, that is what attr_reader etc. are doing, just like the .net auto-property syntax creates actual methods on compilation.

def test=(value)
  puts "I'm a property setter for @test!"
  @test = value
end

def test
  puts "I'm a property getter for @test!"
  return @test
end

Supposedly, attr_ methods are faster than manually implementing methods - not sure if it's true, but they are definitely the recommended way if you don't need actual logic in your getters and setters.

The syntax above used a Ruby symbol, as evidenced by the colon - :test. This is the concept that I took the longest to figure out. In a way, symbols are like interned strings in .net, since the same symbol will always mean the same thing whereas instances of strings may not be reference equal despite having the same content. Generally, Symbols should be seen as constant identifiers (they are in fact immutable). I recommend this blog post for some more information, but interned string seems to be the best .net analogue I could come up with.

Class Variables are static properties. In method names, self. is the equivalent of a static method. There are some caveats when inheriting with regards to static properties.

class MyClass
  @@static_var = 8

  def initialize(my_value)
    @instance_var = my_value
  end

  def testing
    @instance_var + @@static_var
  end

  def self.static_var=(value)
    @@static_var = value
  end
end

myc = MyClass.new(3)
puts myc.testing  # 11

myc2 = MyClass.new(4)
puts myc2.testing # 12

MyClass.static_var = 10
puts myc.testing  # 13
puts myc2.testing # 14

Constants are not prefixed and use SCREAMING_CAPS syntax.

class MyClass
  MY_CONSTANT = 20

  def testing
    4 + MY_CONSTANT
  end
end

myc = MyClass.new
puts myc.testing # 24

Class Inheritance uses < BaseClass syntax. Like .net, Ruby does not support multiple inheritance but unlike .net, there are no interfaces.

class MyClass
  def initialize
    @test = 4
  end
end

class MyDerivedClass < MyClass
  def testing
    2 + @test
  end
end

myc = MyDerivedClass.new
puts myc.testing # 6

Modules in Ruby are a bit like single-namespace assemblies in .net. Modules can contain Constants, methods, classes, etc. The include keyword is like using in .net.

module MyModule
  SOME_CONSTANT = 20

  def MyModule.say_hello
    puts "Hello!"
  end
end

class MyClass
  include MyModule

  def testing
    MyModule.say_hello
    4 + SOME_CONSTANT
  end
end

myc = MyClass.new
puts myc.testing # Hello!, followed by 24

Modules do not support inheritance, despite them being like classes (in fact, Ruby's class class inherits from the Module class, which inherits from Object). What's somewhat noteworthy is that constants do not need the Module name, unless there is something "closer" in scope.

class MyClass
  include MyModule

  SOME_CONSTANT = 30

  def testing
    puts 4 + SOME_CONSTANT            # 34
    puts 4 + MyModule::SOME_CONSTANT  # 24
  end
end

The double colon (::) was described as the namespace resolution operator on Stack Overflow.

There is obviously a lot more to Ruby that doesn't translate 1:1 to .net, but I hope that the above code samples make it a bit easier to understand Ruby as a .net developer