The Ruby Way - What does it mean?

July 1, 2014

Why?

Two blocks of code, which would you prefer?

My Attempt:

def triangle(a,b,c)
	if((a <= 0) || (b <= 0) || (c <= 0))
		raise TriangleError
	end

	if((a + b < c) || (a + c < b) || ( b + c < a))
		raise TriangleError
	end

	if((a + c == b) || (a + b == c) || (b + c == a))
		raise TriangleError
	end

	if((a == b) && (a == c) && (b == c))
		:equilateral
	elsif ((a == b) || (a == c) || (b == c))
		:isosceles
	else
		:scalene
	end
end

The Ruby Way?:

def triangle(a,b,c)
	raise TriangleError unless triangleSideLengthsAreValid?(a,b,c)
	return :equilateral if [a,b,c].uniq.length == 1
	return :isosceles if [a,b,c].uniq.length == 2
	return :scalene if [a,b,c].uniq.length == 3
end

def triangleSideLengthsAreValid?(a,b,c)
	ax,bx,cx = [a,b,c].sort
	return (ax+bx)>cx
end

The first block is my first attempt at the about_triangle_project_2 from the Ruby Koans pretty much the sort of code you would expect to see from the first attempt when learning a new language properly. The second block is something I found after I googled for other solutions. I prefer the second solution over mine since it is much clearer at conveying what is happening. The intent is much easier to grasp than my attempt and its less code.

How?

So what or how do you explain the Ruby Way and how do you start thinking in the Ruby Way? Those are questions I don’t have an answer to…yet! Hal Fulton said

On the one hand, it means a method or technique, but it can also mean a road or path. Obviously these two meanings are interrelated, and I think when I say, “the Ruby Way,” I mean both of them.

So to me the interesting point is “the method or technique”. I looked for some more examples today and came across this code that swaps two values

x, y = y, x

Really!?!? Is that’s all it takes to swap values.

Mind Blown

Look at this

def self.find_by_year_month(year, month)
  requested_date = Date.new(year, month, 1)
  from = requested_date - 1
  to =  requested_date >> 1
  
  engagements = find(:all, :conditions => ["start BETWEEN ? and ?", from, to],
                           :order      => :start)
  
  engagements.group_by do |engagement|
    engagement.start.strftime("%Y%m%d")
  end
end

compared to this

def self.find_by_year_month(year, month)
  date = Time.gm year, month
  engagements = {}
  all = find(:all, :conditions => ["start >= ? and start <= ?", date.last_month.end_of_month, date.next_month.beginning_of_month], :order => :start)
  all.each do |e|
    key = e.start.strftime('%Y%m%d')
    engagements[key] = [] unless engagements.has_key?(key)
    engagements[key].push e
  end
  engagements
end

I know that I would prefer the first code block over the second. Also, while searching I came across the GitHub Style Guide for Ruby, that has some nice advice on coding style that I will often be revisiting.

Conclusion

I am still figuring out the how. To me I don’t believe that thinking or writing code in the Ruby Way will happen overnight. I have read a few suggestions of blogs and books that will help you to start doing things in the Ruby Way but clearly this is a skill that needs to be practiced to master. All I can say is that this language is very impressive and around every corner has more and more sweet features


Discussion, links, and tweets

My name is Deon Heyns and I am a developer learning things and documenting them in realtime. Python, Ruby, Scala, .NET, and Groovy are all languages I have written code in. I appeared in the New York Post once. I host my code up at GitHub and Bitbucket so have a look at my code, fork it and send those pull requests.

comments powered by Disqus