Ruby Case Statement Assignment Of Mortgage

I found case statements in Ruby pretty interesting as they are capable of doing a little more than the equivalent constructs in other languages. We all know how a simple case statement works, we test on a condition that we give to a case statement, we then walk through a set of possible matches each of which is contained in a when statement e.g.:

print "Enter your grade: " grade = gets.chomp case grade when "A" puts 'Well done!' when "B" puts 'Try harder!' when "C" puts 'You need help!!!' else puts "You just making it up!" end

So far nothing special, the above works just the way you would expect. But, you can do more with a case statement in Ruby.

Multi-Value When And No-Value Case

Ruby allows you to supply multiple values to a when statement rather than just one e.g.:

print "Enter your grade: " grade = gets.chomp case grade when "A", "B" puts 'You pretty smart!' when "C", "D" puts 'You pretty dumb!!' else puts "You can't even use a computer!" end

Pretty cool, but nothing too revolutionary. It doesn’t end there though you can use a case statement without giving it a value to match against, which allows a case statement to mimic the behavior of an if statement, e.g.:

print "Enter a string: " some_string = gets.chomp case when some_string.match(/\d/) puts 'String has numbers' when some_string.match(/[a-zA-Z]/) puts 'String has letters' else puts 'String has no numbers or letters' end

So, why would you use it instead of an if statement? Well, there is probably no reason, they are equivalent. But, it is good to be aware that you can do this, especially if you run into it in the wild, wouldn’t want to be caught unawares.

It All Evaluates To An Object

You probably keep hearing this over and over, but everything in Ruby works with objects. Things are no different when it comes to case statements. A case statement will always return a single object, just like a method call. So, you can safely wrap a case statement in a method call and Ruby will have no problems with it. For example, the above version of the case statement ca be re-written like this:

print "Enter a string: " some_string = gets.chomp puts case when some_string.match(/\d/) 'String has numbers' when some_string.match(/[a-zA-Z]/) 'String has letters' else 'String has no numbers or letters' end

We are now wrapping the whole case statement in a puts method call, rather than doing it within each individual when statement. This works because no matter which when/else succeeds, the whole case statement returns the result of the last line that was executed (in our case it just always returns a string), and so the puts just writes out whatever string is returned.

How It All Works Under The Hood

You can almost consider case/when statements to be syntactic sugar for a method call. Every object in Ruby inherits a method called the case equality method, also known as the triple equals (===). You can think of it as an operator if it helps (the === operator), but we know that Ruby operators are just syntactic sugar for method calls. So whenever a when is trying to match a value (except when we are using a no-value case) there is a method call behind the scenes to the === method/operator. We can therefore take our very first example and re-write it using if statements to be completely equivalent to a case statement:

print "Enter your grade: " grade = gets.chomp if "A" === grade puts 'Well done!' elsif "B" === grade puts 'Try harder!' elsif "C" === grade puts 'You need help!!!' else puts "You just making it up!" end

The implications of this are as follows. Any class you write can override the === method and therefore define it’s own behavior for usage in a case statement. For built-in objects such as strings, the === operator/method is simply equivalent to the == method/operator. But you don’t have to be restricted to this. If you want your class to have the ability to participate in a case statement in some specialized way all you need to do is something like this:

class Vehicle attr_accessor :number_of_wheels def initialize(number_of_wheels) @number_of_wheels = number_of_wheels end def ===(another_vehicle) self.number_of_wheels == another_vehicle.number_of_wheels end end four_wheeler = Vehicle.new 4 two_wheeler = Vehicle.new 2 print "Enter number of wheel for vehicle: " vehicle = Vehicle.new gets.chomp.to_i puts case vehicle when two_wheeler 'Vehicle has the same number of wheels as a two-wheeler!' when four_wheeler 'Vehicle has the same number of wheels as a four-wheeler!' else "Don't know of a vehicle with that wheel arrangement!" end

In this case even though we are matching directly on the vehicle object in our case/when statement, behind the scenes a method call is made to the === operator and so the real match is made on the number of wheels attribute that the vehicle object has (as per what is defined in the === method).

This idea of hiding method calls behind syntax that doesn’t look like method calls, seems to be rather common in Ruby. Personally I like it, you can do some rather elegant things, but the building blocks are still just a bunch of method calls. When it comes to the case statement though, I hardly ever use it when I program in Java for example, but it looks to me like it can be somewhat more handy in Ruby especially with the ability to define custom case behavior for your own objects.

Image by dahliascakes

Whenever you need to use some statements you could consider using a Ruby case statement instead. In this post, you will learn a few different use cases and how it all really works under the hood.

Note: In other programming languages this is known as a switch statement.

The components of a case statement in Ruby:

KeywordDescription
caseStarts a case statement definition. Takes the variable you are going to work with.
whenEvery condition that can be matched is one when statement.
elseIf nothing matches then do this. Optional.

Ruby Case & Ranges

The statement is more flexible than it might appear at first sight. Let’s see an example where we want to print some message depending on what range a value falls in.

I think this code is pretty elegant compared to what the version would look like.

Ruby Case & Regex

You can also use regular expressions as your condition. In the following example we have a with an initial letter that tells us how risky this product is to consume.

When Not to Use Ruby Case

When you have a simple 1:1 mapping, you might be tempted to do something like this.

In my opinion it would be better to do this instead:

The hash solution is more efficient and easier to work with. Don’t you think?

How case works: the === method

You may be wondering how works under the hood. If we go back to our first example, this is what is happening:

As you can see, the condition is reversed because Ruby calls on the object on the left. The is just a method that can be implemented by any class. In this case, implements this method by returning true only if the value is found inside the range.

This is how is implemented in Rubinius (for the class):

Source: https://github.com/rubinius/rubinius/blob/master/core/range.rb#L178

Procs + Case

Another interesting class that implements is the class.

Related post: Learn more about procs & lambdas.

In this example I define two , one to check for an number, and another for .

This is what is really happening:

Using on a proc has the same effect as using .

Conclusion

You have learned how the Ruby case statement works and how flexible it can be. Now it’s your turn to start making the best use of it in your own projects.

I hope you found this article useful!

Please share this post so more people can learn! 🙂

Related

Share this post!

casecapacity

when0

  "You ran out of gas."

when1..20

  "The tank is almost empty. Quickly, find a gas station!"

when21..70

  "You should be ok for now."

when71..100

  "The tank is almost full."

else

  "Error: capacity has an invalid value (#{capacity})"

end

caseserial_code

when/\AC/

  "Low risk"

when/\AL/

  "Medium risk"

when/\AX/

  "High risk"

else

  "Unknown risk"

end

casecountry

when"europe"

  "http://eu.example.com"

when"america"

  "http://us.example.com"

end

SITES={

  "europe"  =>"http://eu.example.com",

  "america"=>"http://us.example.com"

}

 

SITES[country]

(1..20)   ===capacity

(21..70)  ===capacity

(71..100)===capacity

def===(value)

  include?(value)

end

odd  =proc(&:odd?)

even=proc(&:even?)

 

casenumber

whenodd

  puts"Odd number"

wheneven

  puts"Even number"

end

odd.===(number)

even.===(number)

0 thoughts on “Ruby Case Statement Assignment Of Mortgage”

    -->

Leave a Comment

Your email address will not be published. Required fields are marked *