How do I turn the following if / else
statement:
if /_?town$/.match? name
['Springfield', 'Shelbyville', 'Kent', 'Carter', 'Benson'].sample
elsif /_?state$/.match? name
['TX'].sample
else
'text'
end
into a case
statement in Rails / Ruby?
I tried
case name
when /_?town$/.match?
['Springfield', 'Shelbyville', 'Kent', 'Carter', 'Benson'].sample
when /_?state$/.match?
['TX'].sample
else
'text'
end
but I am getting a wrong number of arguments error related to match?
case
statements do not work like that. The object behind the case
is not passed as an argument to any method call that is found after each when
. Instead, it is passed to a very special method (===
) call as an argument.
Instead, when there is a case block defined like this:
case x
when a
# ...
when b
# ...
else
# ...
end
Then the equivalent if-else-block would look like this:
if a === x
# ...
elsif b === x
# ...
else
# ...
end
Note the method being called (===
) and the order (it is, a === x
, not x === a
). The ===
method is defined on many types of classes and has differently behavior.
For example:
String#===
and Integer#===
return true
when both values are equal.Range#===
returns true
, when the argument is included in the range.Object#===
returns true
, when the argument is an instance of Object
Regexp#===
returns true
, then the argument matches the regexp.This means the behavior of a case-block depends on the objects and their ===
implementation. That makes case-blocks extremely powerful. But it doesn't support passing the object to any other method than the ===
.
That said, you can either still call match?
(or any other method call), but then you have to write the full statement behind the when
and leave the case
blank. This might be preferable when you want to avoid having long if-elsif-blocks.
case
when /_?town$/.match? name
['Springfield', 'Shelbyville', 'Kent', 'Carter', 'Benson'].sample
when /_?state$/.match? name
['TX'].sample
else
'text'
end
Or – in your specific example – you could write it like this, because regexp.match?(name)
has almost the same behavior as regexp === name
(See Regexp#===
in the docs):
case name
when /_?town$/
['Springfield', 'Shelbyville', 'Kent', 'Carter', 'Benson'].sample
when /_?state$/
['TX'].sample
else
'text'
end