views:

430

answers:

13

Similar questions have been asked for .NET and Java, but not for Ruby. So, what’s your favorite feature in Ruby?

You might also be interested in hidden features of Ruby.

Please be specific and post one feature per answer. An explanation or a code sample would be nice.

+2  A: 

That classes are objects and new is a method on the class:

c = Array
a = c.new()

And I like how case works. It calls === on every case value and returns a value:

if(0 <= age &&  age <= 10){
  x = "kid"
}else if(10 <= age && age <= 80)
  x = "person"
}else if(80 <= age && age <= 99)
  x = "old"
}else{
  x = "???"
}

=>

x = case age
  when 0..10:  "kid"
  when 10..80: "person"
  when 80..99: "old"
  default:     "???"
end

This works because ranges (0..10) have a === method that checks if something is in the range: (5..10) === 6 ==> true. Regexes support === too, so you can do:

case str
  when /regex1/: ...
  when /regex2/: ...
  ...
end

You can even write an === method for your own objects.

Jules
your if-statement is not ruby
banister
+7  A: 

This is a pretty small, almost insignificant feature, but I really like this construct:

var ||= "default"

This sets var to a default value ("default") if var has not been set yet, or retains the current value of var if it has been set already. I like the compact syntax.

Along the same lines, I can do something like this:

new_val = old_val || "default"

to set a default value, too.

In general, I like how all Ruby expressions return a value, so I can use operators like || to write short, compact statements.

mipadi
You should note that if var or old_val are false, they will lose their value and be assigned the default.
Samuel
@Samuel - seconded, also a frequent Perl bug (the same idiom is used there and like "if ($foo)", it regularly screws up things when e.g. the string "0" is a valid value).
mjy
In this case it is only nil/false that the default value would be overwritten, so it's a minor bug.
The Wicked Flea
+1  A: 

question mark/exclamation point naming convention

often no parens needed after method call

closures

rubygems

Okay, I guess that's a few favorites :)

J Cooper
I would add examples to make it clear. Like string.chop vs string.chop! and defined?
Tilendor
+2  A: 

Another nice feature: ensure. It's like finally but has a concise syntax in Ruby. You can use it when you have something like this:

def foo(x)
  return_value = bar(x)
  dosomething(x)
  return return_value
end

=>    

def foo(x)
  bar(x)
ensure
  dosomething(x)
end
Jules
That's straight-outta-Eiffel. Almost always what you need, but awkward in too many languages.
Dustin
+2  A: 

Open classes are one of my favorites. For example, this:

# try.rb

class TryObjectMock
  public_instance_methods.reject { |x| x =~ /^__/ }.each { |x| undef_method(x) }

  def method_missing(symbol, *args)

  end
end

class Object
  def try
    self.nil? ? TryObjectMock.new : self 
  end
end

makes code that handles nilable objects clearer:

irb(main):001:0> require 'try'
irb(main):002:0> puts "5".try.to_i
5
irb(main):003:0> puts nil.try.to_i
nil
irb(main):004:0> puts [1, 2].try.find { |x| x == 2 }.try + 3
5
irb(main):005:0> puts [1, 2].try.find { |x| x == 3 }.try + 3
nil
irb(main):006:0> puts nil.try.find { |x| x == 3 }.try + 3
nil
irb(main):007:0>

It avoids a lot of if-elses:

irb(main):007:0> a = [1, 2]
irb(main):008:0> puts(if a
irb(main):009:2>        if b = a.find { |x| x == 2 }
irb(main):010:3>          b + 3
irb(main):011:3>        end
irb(main):012:2>      end)
5
irb(main):013:0> c = "5"
irb(main):014:0> puts(c ? c.to_i : nil)
5

The trick works by defining the method try for every class in the object space. When it's called it returns a special object when the object is nil (nil is an instance of NilClass, which is a subclass of Object!) or the object itself otherwise. That special object simply returns nil for every method called (through the empty method_missing implementation). Note that it also works for operators, since they are methods of the left-side object.

Romulo A. Ceccon
+11  A: 

Blocks are really nice:

my_array.each { |element| print element } 

#...

File.open("foo.txt") do |file|
  # do stuff with file
end
CMS
+1 for blocks and the fact that you can define your own iterators.
Keltia
I don't like how blocks are passed to functions. Smalltalk has a better way (blocks are treated like normal arguments).
Jules
There are many features in Ruby, but this is my favorite. It might be imperfect, but when I first learned about it, I thought: "This is totally amazing!"
Yaser Sulaiman
+3  A: 

I like being able to call functions without parentheses, and functions returning the last evaluated expression.

The former saves a lot of unnecessary parentheses, and makes code easier to read.

The latter can get quite confusing sometimes, but it's great for one-line (esp. logical) functions.

Can Berk Güder
+3  A: 

Enumerable! Some examples on why it's awesome.

a = ['foo', 'bar', 'baz']

a.delete_if {|i| i =~ /^f/ }
# vs
new = []
a.each do |i|
  if i !~ /^f/
    new << i
  end
end



a.select {|i| i =~ /^f/ }
# vs
new = []
a.each do |i|
  if i =~ /^f/
    new << i
  end
end


a.detect {|i| i =~ /^f/ }
# vs
a.each do |i|
  if i =~ /^f/
    return i
  end
end

It's very nice to be able to say directly what you want to achieve, with 'select', 'detect', 'delete_if' and so on, instead of looping and doing everything by hand. Enumerable makes it easier to type, and easier to understand when reading the code.

August Lilleaas
+1  A: 

My favorite feature right now (after dealing with Soap4R recently) is probably the introspection that's available. These two methods are particularly useful:

public_methods - Returns a list of all the methods on an object. Super useful from the debugger or irb when you're trying to figure out what you can do to something. (A close second

instance_variables - Returns a list of all the instance variables on an object.

There's all sorts of other good stuff here: http://www.ruby-doc.org/core/classes/Object.html

+1  A: 

instance_eval and class_eval :)

banister
After trying to dynamically add methods in C# and realizing I had to do MSIL, I greatly missed Ruby. :(
Sarah Vessels
+1  A: 

if statements are expressions, too, so the last line of the block returns a value. Allows for code like:

my_var = if some_var.is_true?
           if some_other_var > 8
             1
           else
             23
           end
         else
           5
         end

Here, my_var would end up with the value 1, 23, or 5, depending on how the conditions evaluated.

Sarah Vessels
+2  A: 

Boolean operators on non boolean values.

&& and ||

Both return the value of the last expression evaluated. With short circuiting these create handy short cuts. They treat any value that isn't nil or false as true for the purposes of short circuit detection.

Example:

a = b || c

Assigns the value of c to a only if b is nil or false.

a = b && c

Assigns the value of c to a only b is not nil or false, otherwise, assigns b.

This behaviour explains the ||= mentioned already.

However the &&= operator doesn't get the same love.

string &&= string + "suffix"

is equivalent to

if string
  string = string + "suffix"
end

It's very handy for destructive operations that should not proceed if the variable is undefined.

EmFi
+2  A: 

I couldn't possibly pick just one, but the first that came to mind was splat: *

Basically it lets you turn an array into an argument list and vice versa, letting you do stuff like this:

odds  = [1, 3, 7]
evens = [2, 4, 6]

case 4
  when *odds  then "odd!"
  when *evens then "even!"
end
# => "even!"


arr = [ :a, 1, :b, :2 ]    
Hash[*arr] # => { :a => 1, :b => 2 }


a, b, c = *(1..3)
puts a # => 1
puts b # => 2
puts c # => 3


a = 1, *[2, 3] # => [1, 2, 3]


# And of course...
def f(*args)
  puts args
end

f 1, 2, 3 # => [1, 2, 3]
Jordan