# Seeking advice on Ruby code style

**URL:** <https://www.ruby-forum.com/t/seeking-advice-on-ruby-code-style/81703>\
**Category:** Ruby\
**Created:** [January 11, 2007, 2:49pm UTC](https://www.ruby-forum.com/t/seeking-advice-on-ruby-code-style/81703 "2007-01-11T14:49:45Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alexandru\_ESUngur](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/b5e925/32.png) [@Alexandru\_ESUngur](https://www.ruby-forum.com/u/Alexandru_ESUngur)\
**Post date:** [January 11, 2007, 2:49pm UTC](https://www.ruby-forum.com/t/seeking-advice-on-ruby-code-style/81703/1 "2007-01-11T14:49:45Z")

</div>

Hi all,

I recently recently released my first vim script, nothing big, it  
just toggles words between true/false, on/off, etc. You can find  
more here [- : vim online](http://vim.sourceforge.net/scripts/script.php?script_id=1748)  
if you want.

The thing is, I’m not sure if I chose the most elegant/beautiful/\*\*  
way to solve the problem, basically I ended up deciding between  
two ways of handling the problem:

class String  
@@pairs = [%w[on off], %w[yes no], %w[true false] ]

def toggle\_word1  
pair = @@pairs.select{|p| p.include?(downcase)}.flatten  
return nil if pair.empty?  
antiword = pair[pair.index(downcase) ^ 1]  
case self  
when upcase then return antiword.upcase  
when downcase then return antiword.downcase  
when capitalize then return antiword.capitalize  
else return antiword  
end  
end

def toggle\_word2  
pair = @@pairs.select{|p| p.include?(downcase)}.flatten  
wordcase = %w[upcase downcase capitalize].detect {|c| send(c) ==  
self} || “downcase”  
pair.empty? ? nil : pair[pair.index(downcase) ^ 1].send(wordcase)  
end  
end

Both toggle\_word1 and toggle\_word2 are doing the exact same thing, that  
is:  
“Yes”.toggle\_word1 # =\> “No”  
“No”.toggle\_word2 # =\> “Yes”  
and so on.

My question is, which is more elegant, more… rubyful ?  
I like that toggle\_word1 is almost like plain english, especially  
that “case” construct, but I like in toggle\_word2 that the same “case”  
construct was replaced with a single line of code, well with two  
actually. However perhaps toggle\_word2 is a little too much  
code golfing…?

Thank you in advance for your comments,  
Have a nice day everyone,  
Alex

---

<div class="post-metadata">

**Author:** ![Alexandru\_ESUngur](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/b5e925/32.png) [@Alexandru\_ESUngur](https://www.ruby-forum.com/u/Alexandru_ESUngur)\
**Post date:** [January 11, 2007, 3:22pm UTC](https://www.ruby-forum.com/t/seeking-advice-on-ruby-code-style/81703/2 "2007-01-11T15:22:05Z")

</div>

On Thu, Jan 11, 2007 at 10:49:29PM +0900, Alexandru E. Ungur wrote:

> I recently recently released my first vim script, nothing big, it  
> just toggles words between true/false, on/off, etc. You can find  
> more here [- : vim online](http://vim.sourceforge.net/scripts/script.php?script_id=1748)  
> if you want.  
> […]

Here’s a cleaner implementation (assuming I understand it correctly):

class String  
PAIRS = Hash[\*%w(on off yes no true false)]  
PAIRS.to\_a.each { |v,k|  
v.freeze  
k.freeze  
PAIRS[k] = v  
}  
PAIRS.freeze

def toggle\_word  
return self unless antiword = PAIRS[downcase]  
case self  
when upcase  
antiword.upcase  
when downcase  
antiword.downcase  
when capitalize  
antiword.capitalize  
else  
antiword  
end  
end

end

Note that I am avoiding class variables (which are almost always the  
wrong  
choice, see

> **[O'Reilly Media - Technology and Business Training](https://www.oreilly.com)**
>
> Gain technology and business knowledge and hone your skills with learning resources created and curated by O'Reilly's experts: live online training, video, books, our platform has content from 200+ of the world's best publishers.

) and using a constant instead. The freezing is optional, but I like to  
freeze what my constants point to. Notice that I am reversing all the  
entries in the hash so it’s easy to toggle both ways. I kept the case  
statement from toggle\_word1 over the golfing in toggle\_word2, but I’ll  
point out that Ruby only requires a return when short-circuiting.

> Thank you in advance for your comments,  
> Have a nice day everyone,  
> Alex  
> –Greg

---

<div class="post-metadata">

**Author:** ![Alexandru\_ESUngur](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/b5e925/32.png) [@Alexandru\_ESUngur](https://www.ruby-forum.com/u/Alexandru_ESUngur)\
**Post date:** [January 11, 2007, 3:42pm UTC](https://www.ruby-forum.com/t/seeking-advice-on-ruby-code-style/81703/3 "2007-01-11T15:42:09Z")

</div>

On Jan 11, 2007, at 8:49 AM, Alexandru E. Ungur wrote:

> My question is, which is more elegant, more… rubyful ?  
> I like that toggle\_word1 is almost like plain english, especially  
> that “case” construct, but I like in toggle\_word2 that the same “case”  
> construct was replaced with a single line of code, well with two  
> actually. However perhaps toggle\_word2 is a little too much  
> code golfing…?

I think in both cases you are repeating too much work that could be  
done ahead of time. How about:

class String  
base = %w[on off yes no true false]  
all = base  
all += base.map {|x| x.upcase }  
all += base.map {|x| x.capitalize }  
t = Hash[\*all]  
TOGGLE = t.merge t.invert

def toggle\_word3  
TOGGLE[self] || TOGGLE[downcase]  
end  
end

if **FILE** == $0  
require ‘test/unit’

class My\_Test \< Test::Unit::TestCase  
def test\_toggle\_word3  
assert\_equal(‘off’, ‘on’.toggle\_word3)  
assert\_equal(‘Off’, ‘On’.toggle\_word3)  
assert\_equal(‘YES’, ‘NO’.toggle\_word3)  
assert\_equal(‘yes’, ‘nO’.toggle\_word3)  
assert\_equal(‘false’, ‘true’.toggle\_word3)  
assert\_equal(nil, ‘unknown’.toggle\_word3)  
end  
end  
end

Gary W.

---

<div class="post-metadata">

**Author:** ![Alexandru\_ESUngur](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/b5e925/32.png) [@Alexandru\_ESUngur](https://www.ruby-forum.com/u/Alexandru_ESUngur)\
**Post date:** [January 19, 2007, 4:29pm UTC](https://www.ruby-forum.com/t/seeking-advice-on-ruby-code-style/81703/4 "2007-01-19T16:29:24Z")

</div>

On Thu, Jan 11, 2007 at 11:40:52PM +0900, removed\_email\_address@domain.invalid wrote:  
[…]

> TOGGLE = t.merge t.invert

Yow, how did I miss Hash#invert? That’s beautiful.

–Greg

---

<div class="post-metadata">

**Author:** ![Alexandru\_ESUngur](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/b5e925/32.png) [@Alexandru\_ESUngur](https://www.ruby-forum.com/u/Alexandru_ESUngur)\
**Post date:** [January 19, 2007, 4:29pm UTC](https://www.ruby-forum.com/t/seeking-advice-on-ruby-code-style/81703/5 "2007-01-19T16:29:26Z")

</div>

Alexandru E. Ungur wrote:

> ```
> when capitalize then return antiword.capitalize
> 
> ```
> 
> code golfing…?
> 
> Thank you in advance for your comments,  
> Have a nice day everyone,  
> Alex

class String  
def toggle\_word3  
words = %w[on off yes no true false]  
word = words[i = words.index(downcase)]  
anti = words[i + (i%2\>0 ? -1 : 1 )]  
%w( capitalize upcase ).each{|meth|  
return anti.send(meth) if word.send(meth) == self }  
anti  
end  
end

---

<div class="post-metadata">

**Author:** ![Alexandru\_ESUngur](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/b5e925/32.png) [@Alexandru\_ESUngur](https://www.ruby-forum.com/u/Alexandru_ESUngur)\
**Post date:** [January 19, 2007, 4:30pm UTC](https://www.ruby-forum.com/t/seeking-advice-on-ruby-code-style/81703/6 "2007-01-19T16:30:38Z")

</div>

Boy, am I glad I asked for advice…  
I hesitated for a few days to ask for advice on this, since I thought:  
this is too easy, how to ask for advice on such a simple problem?, I  
mean, in how many ways you can toggle a word, right? Now I feel really  
dumb… 🙂 as I’ve seen, the answer is: in many and **very**  
interesting ways.  
Simply amazing and enlightening…

A _big_ thank you to you all!  
All the best,  
Alex
