# Ruby if-statement, possible to shorten it further?

Is it possible to shorten this, or to improve the code in any way? I know it's just a simple if-statement, but it's always fun to learn a shorter way of doing things.

if self.citizenship == 'ES'
@identification_type = IDENTIFICATION_TYPES[0]
elsif self.country == 'ES'
@identification_type = IDENTIFICATION_TYPES[1]
end


You could remove a little duplication like this:

@identification_type = if self.citizenship == 'ES'
IDENTIFICATION_TYPES[0]
elsif self.country == 'ES'
IDENTIFICATION_TYPES[1]
end

• In other words: the way to shorten this if-statement is to realize that is isn't an if-statement, it's an if-expression! In fact, there are no statements in Ruby, everything is an expression. – Jörg W Mittag Dec 30 '11 at 13:28

I don't know Ruby, so I'm not sure this is at all idiomatic. However, you can do something like this (if you're looking for a one-liner):

@identification_type = IDENT_TYPES[[@citizenship, @country].index('ES')]


Just so this makes some sort of sense (in case I didn't understand your code), here is some context:

IDENT_TYPES = {0 => :citizen, 1 => :country}

class Foo
attr_accessor = :citizenship, :country, :identification_type

def initialize(citizenship, country)
@citizenship = citizenship
@country = country
@identification_type = IDENT_TYPES[[@citizenship, @country].index('ES')]
puts @identification_type
end
end

foo = Foo.new('ES', 'EN')
foo = Foo.new('EN', 'ES')
foo = Foo.new('EN', 'EN')


This outputs:

citizen
country
nil

• Interesting approach, but I don't think this code communicates very well. – Torbjørn Dec 30 '11 at 9:10

You could replace the if with case. Normally, the case-statement contains a variable and the when-statements contain constant or variables. But you may do it the other was:

#Some code to make it executable
IDENTIFICATION_TYPES = [1,2]
class MyObject
def citizenship; 'ES';end
def country;  'ES';end

def test
#The code:
@identification_type  = case 'ES'
when self.citizenship
IDENTIFICATION_TYPES[0]
when self.country
IDENTIFICATION_TYPES[1]
end
end
end

p MyObject.new.test


Advantage: you don't need to repeat the == 'ES'.

Disadvantage: Mixed checks (ES or AS...) is not possible.

• Now things like 1.citizenship and [].country are possible. Don't do this. – steenslag Dec 30 '11 at 21:45
• The modification of Object was only a quick possibility to make the example executable - it wasn't meant to be 'real' code. In real case, the code should be embedded in a Object.- I adapted the example to avoid a change of Object. – knut Dec 30 '11 at 21:59

Based on your code (somewhat like @AdamWagner's answer), here's a way without a case statement (though self.country is always evaluated):

criteria=[self.citizenship, self.country]
@identification_type=
IDENTIFICATION_TYPES.at criteria.index{|e| 'ES'==e}


And a way with a case statement:

k=case 'ES'
when self.citizenship then 0
when self.country     then 1
end
end
@identification_type=
IDENTIFICATION_TYPES.at k