Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

  • Blog Navigation
Ruby 2.1.0 changes of note.

The Ruby 2.1.0

Illustration of a cut ruby.

Release is nearly a month old, so its well past time to look over the changes and uncover the features least discussed.

This release received relatively exceptional social coverage. The attention largely due to the addition of Generational Garbage collection. A bit of exploration reveals changes that may have been overlooked in the shadow of RGenGC.

private def

:def now returns a symbol, a clearer return response then the former nil

irb(main):001:0> def hello
irb(main):002:1> end
=> :hello

Coupled with new private and protected methods now take in a symbol:

class Offer
  def == other
    if self.class == other.class
      salary == other.salary

  def initialize(compensation)
     @compensation = compensation

  protected def salary

irb(main):150:0> Offer.protected_instance_methods
=> [:salary]

Required keyword arguments

class Offer
  def initialize(compensation:, position: "Engineer")
    @position = position
    @compensation = compensation

Mark the compensation attribute as required by omitting its default value.

irb(main):170:0> 70000)
=> #
irb(main):171:0> 70000, position: "Sales Analyst")
=> #
irb(main):172:0> "Sales Analyst")
ArgumentError: missing keyword: compensation


Now we can take any enumerable and derive a hash from it.

(1..10).collect{|a|[a,(a * 2)]}.to_h


Array implements to_h separately

[[:name, :age], ["Matz", 48]].to_h

#to_h is a convenience method that has been a long time coming.


Refinements build a sandboxed around the duck punching / monkey patching of core classes such as numeric.

module CurrencyDecorator
  refine Numeric do
    def to_currency
      sprintf("%s%0.2f", { :currency => "$", :number => self})

class Currency
  using CurrencyDecorator

  def initialize(numeric)
    @number = numeric.to_f.to_currency
end returns an implicit conversion of any Numeric param to a decorated stringified float conforming to currency format. All within the safe confines of Currency object.

irb(main):052:0> 45.888
<Currency:0x007fd6db0e19b0 @number="$45.89">
irb(main):054:0> 79987.87666767
<Currency:0x007fd6db0e19b0 @number="$79987.88">

Numeric outside Currency is unaffected.

irb(main):017:> 748.to_currency
NoMethodError: undefined method `to_currency' for 748:Fixnum

irb(main):018:0> 748.9.to_currency
NoMethodError: undefined method `to_currency' for 748.9:Float

Updates in Std lib

Vector finally implements cross product

Vector[0.6, 0, 0].cross_product Vector[0, 1.4, 0]

Leveraging GMP

The GNU Multiple Precision Arithmetic Library

Large performance increase for calculations involving Bignums

Bignum and Fixnum respond to bit_length

human_population = 10900000000
=> 34
(human_population * human_population).bit_length
=> 67

Thats the quick tour of the less hyped changes

Next I’ll be running through Ruby Koans to explore behavioral differeinces

  • Actually, `public`, `private`, and `protected` have taken symbols since at least Ruby 1.8. It’s just more useful now that `def` returns a symbol.

  • I’m curious as to why Array implements `.to_h` separately, and why this is important. I would have expected it to just use the Enumerable implementation.

    Any idea why this is?

  • Mark

    Thanks for this. Just a heads-up I think you’re Currency refinements example isn’t quite right – doesn’t care about the return value for initialize – it’ll just return a Currency object. Cheers

  • Refinements are really cool! I look forward to using them in my code.

    I think there are two problems in your example though. These are:

    1. You are using the keyword-arguments version of `sprintf`, but then refer to the values in the string as “%s” and “%0.2f”. The correct code would be either `sprintf(“%s%0.2f”, “$”, self)` or `sprintf(“%s%0.2f”, { :currency => “$”, :number => self})`.

    2. You seem to be trying to return a string in the initializer, instead of storing it somewhere, or something like that. The examples definitely don’t return what they claim, because a constructor can only return an instance of the class, not of a different class (strings on the examples)

    Just in case it’s relevant, I’m running ruby-2.1.0 on RVM.

  • Apologies for nit picking, but your Refinements example has a couple of issues. The Currency initializer will return a Currency instance, not a string as your example suggests. Also your `sprintf` call is mixing two different styles, the format string you’ve specified suggests you meant `sprintf(“%s%0.2f”, “$”, self)` instead.

  • Matthew Jording

    Thanks Olly, updated to reflect intent.

Share This