<?xml version="1.0" encoding="UTF-8"?>
<code>
  <code>class VotingSystem  
  #Hello, I am Rodger the old and unhappy programmer. the variable nbrOfVotes is an array of 2 dimensions. The first dimension contains the number of votes for the answer "YES, IT SUCKS"... and the other dimension contain the number of votes for the answer "NO, IT DOESN'T SUCK". In the near future there will be other possible answers... but I don't care! I retire in 2 days!
  @@nbrOfVotes = Array.new
  
  #The users who sent their vote arrive in this very top secret method!! (I retire in 2 days!)
  def receiveAVote(theVote)
    if theVote == "YES, IT SUCKS"
     @@nbrOfVotes[0] = 0 if @@nbrOfVotes[0].nil?
     @@nbrOfVotes[0] = @@nbrOfVotes[0] + 1
    else
      if theVote == "NO, IT DOESN'T SUCK"
        @@nbrOfVotes[1] = 0 if @@nbrOfVotes[1].nil?
        @@nbrOfVotes[1] = @@nbrOfVotes[1] + 1
      else
          puts "THIS IS NOT A VALID ANSWER YOU MORON... btw i retire in 2 days!"
      end
    end
  end

  #This is the function that compile ALL the votes... I retire in 2 days!
  def compileAllTheVotes
    for i in (0..1)
      if i == 0
        @@nbrOfVotes[0] = 0 if @@nbrOfVotes[0].nil?
        puts "HERE IS THE NUMBER OF VOTES FOR 'YES IT SUCKS' : " + @@nbrOfVotes[0].to_s
      else
        if i == 1
          @@nbrOfVotes[1] = 0 if @@nbrOfVotes[1].nil?
          puts "HERE IS THE NUMBER OF VOTES FOR 'NO IT DOESN'T SUCKS' : " + @@nbrOfVotes[1].to_s
        end
     end
    end
  end
end</code>
  <comment>Ouch... this guy badly needs (but doesn't deserve) help! Original article on RubyFleebie is here : http://www.rubyfleebie.com/rubyize-this-6th-edition</comment>
  <created-at type="datetime">2008-04-17T00:20:48+00:00</created-at>
  <id type="integer">283</id>
  <language>Ruby</language>
  <permalink>rubyize-this-6th-edition</permalink>
  <refactors-count type="integer">8</refactors-count>
  <title>Rubyize this : 6th edition</title>
  <trackback-url>http://www.rubyfleebie.com/rubyize-this-6th-edition/trackback</trackback-url>
  <updated-at type="datetime">2008-09-16T14:49:49+00:00</updated-at>
  <user-id type="integer">184</user-id>
  <refactors type="array">
    <refactor>
      <code>class VotingSystem
  def initialize
    @votes = {
      "yes, it sucks" =&gt; 0,
      "no, it doesn't suck" =&gt; 0,
    }
  end
 
  def vote(vote)
    vote.downcase!
    if @votes.has_key? vote
      @votes[vote] += 1
    else
      puts "THIS IS NOT A VALID ANSWER YOU MORON&#8230; btw i retire in 2 days!"
    end
  end
 
  def compile_votes
    @votes.each do |vote, count|
      puts "HERE IS THE NUMBER OF VOTES FOR '#{vote}': #{count}"
    end
  end
end</code>
      <code-id type="integer">283</code-id>
      <comment></comment>
      <created-at type="datetime">2008-04-17T00:37:33+00:00</created-at>
      <id type="integer">5178</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 6th edition</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>Vince</user-name>
      <user-website></user-website>
    </refactor>
    <refactor>
      <code>class VotingSystem  
  def initialize
    @votes = {  "yes, it sucks" =&gt;  0, "no, it doesn't suck" =&gt; 0, "other"  =&gt; 0}
  end
  
  def process_vote(vote)
    begin
      @votes[vote.downcase] += 1
    rescue
      @votes['other'] += 1
    end
  end
  
  def output
    total = @votes.values.inject(0) {|sum, n| sum + n }
    @votes.each do |answer, number|
      percent = number.to_f / total * 100.0
      puts "Here is the number of votes for '#{answer}' : #{number}  =&gt; #{percent}%"
    end
  end
end</code>
      <code-id type="integer">283</code-id>
      <comment>almost the same as Vince. But he did a hell of a job, so there isn't much left to change.</comment>
      <created-at type="datetime">2008-04-17T12:39:41+00:00</created-at>
      <id type="integer">5199</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 6th edition</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>Sam Figueroa</user-name>
      <user-website>http://apirate.iwasmeantto.be</user-website>
    </refactor>
    <refactor>
      <code></code>
      <code-id type="integer">283</code-id>
      <comment>Cool I didn't know about the begin/rescue for the hash</comment>
      <created-at type="datetime">2008-04-17T13:08:01+00:00</created-at>
      <id type="integer">5200</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 6th edition</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>Vince</user-name>
      <user-website></user-website>
    </refactor>
    <refactor>
      <code>class VotingSystem
  def vote(answer, question = "is 'the flinstones' a boring t.v. show?")				
    if @@votes.has_key?(question.downcase) &amp;&amp; @@votes[question.downcase].has_key?(answer.downcase)
      @@votes[question][answer.downcase] += 1
      puts "There are #{@@votes[question.downcase][answer.downcase]-1} people who think like you!"
    else
      puts "Inexistant question or answer"
    end		
  end	
	
  private
  @@votes =  {	
    "is 'the flinstones' a boring t.v. show?" =&gt; {"yes, it sucks!" =&gt; 0, "no, it rocks!" =&gt; 0},
    "what is your name?" =&gt; {"frank" =&gt; 0, "what's the point to vote on that?" =&gt; 0}		
  }	
end</code>
      <code-id type="integer">283</code-id>
      <comment>Here is my solution... nothing revolutionary but it does the job. I also added the possibility to vote on multiple questions</comment>
      <created-at type="datetime">2008-04-17T13:13:21+00:00</created-at>
      <id type="integer">5201</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 6th edition</title>
      <user-id type="integer">184</user-id>
      <user-name>FrankLamontagne</user-name>
      <user-website>http://www.rubyfleebie.com</user-website>
    </refactor>
    <refactor>
      <code>class VotingSystem  
  @@votes = {  "yes, it sucks" =&gt;  0, "no, it doesn't suck" =&gt; 0, "other"  =&gt; 0}

  def cast_vote(vote)
    @@votes[vote.downcase] += 1
  rescue
    @@votes['other'] += 1
  end

  def results 
    @@votes.each do |vote, count|
      puts "there are #{count} vote(s) for '#{vote}'"
    end
  end
end
</code>
      <code-id type="integer">283</code-id>
      <comment>not much different than what has already been submitted.</comment>
      <created-at type="datetime">2008-04-17T13:53:21+00:00</created-at>
      <id type="integer">5203</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 6th edition</title>
      <user-id type="integer">237</user-id>
      <user-name>jswanner</user-name>
      <user-website>http://jacobswanner.com</user-website>
    </refactor>
    <refactor>
      <code># A choice in a Voting System
class VotingChoice
  attr_reader :label

  def initialize(label = "Empty Choice")
    @label = label
  end

  def to_s
    @label
  end
end

# THE Voting System
class VotingSystem
  # Constructor
  # [choices] an array of available choices to the user (you know what they are on opening the vote and they cannot change!)
  def initialize(choices)
    choices &lt;&lt; VotingChoice.new("Abstention") # If the user does not know what to vote for

    # A hash of the available choices, used for the UI
    @choices = choices.collect { |c| c.label.to_sym }

    # A hash to record the votes
    @votes = Hash.new
    @choices.each_index do |idx|
      @votes[@choices[idx]] = 0
    end
    # Let's not forget the invalid ones
    @votes[:invalid] = 0
  end

  # Display the choices and record user's vote
  def vote
    @choices.each do |choice|
      puts "  " + choice_id(choice).to_s + ". " + choice.to_s
    end
    print "Please vote: "

    if choice = STDIN.gets
      record_vote(choice.to_i)
    end
  end

  # Display the results
  def results
    puts "\nResults of the vote:"
    # Go through the choices rather than votes so we get a consistent order
    @choices.each do |choice|
      puts "  " + choice.to_s + ": " + @votes[choice].to_s
    end
    # And the invalids
    puts "  Invalid: " + @votes[:invalid].to_s
  end

  private

  def record_vote(choice_id)
    if valid_choice?(choice_id)
      @votes[@choices.at(choice_id-1)] += 1
    else
      puts "THIS IS NOT A VALID ANSWER YOU #*%!... I could do that for an extra 2 years!"
      @votes[:invalid] += 1
    end
  end

  # Return a unique id for the choice. We could have used the array index directly
  # but starting at 0 is not user friendly and dangerous ( "string".to_i =&gt; 0 )!
  def choice_id(choice)
    @choices.index(choice) + 1
  end

  def valid_choice?(choice_id)
    ( choice_id &gt; 0 ) &amp;&amp; !@choices.at(choice_id-1).nil?
  end
end

vc = [ VotingChoice.new("YES, IT SUCKS"),
       VotingChoice.new("NO, IT DOESN'T SUCK"),
       VotingChoice.new("THERE MUST BE A BETTER WAY") ]
vs = VotingSystem.new(vc)
3.times { vs.vote }
vs.results</code>
      <code-id type="integer">283</code-id>
      <comment>Maybe not quite a refactoring...</comment>
      <created-at type="datetime">2008-04-18T22:00:19+00:00</created-at>
      <id type="integer">5285</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 6th edition</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>fifoo</user-name>
      <user-website></user-website>
    </refactor>
    <refactor>
      <code># voting system related code
class Topic
  attr_accessor :name, :answers
  
  def initialize(p_topic_name)
    @name = p_topic_name
    @answers = {}
  end
  
  def add_answer(p_answer)
    @answers[p_answer.downcase] = 0
    return self
  end
  
  def select_answer(p_answer)
    answer = p_answer.downcase
    verify_valid_answer(answer)
    @answers[answer] = @answers[answer] + 1
  end
  
  def count_response(p_answer)
    answer = p_answer.downcase
    verify_valid_answer(answer)
    return @answers[answer]
  end
  
  private
  def verify_valid_answer(p_answer)
    raise "You have selected an unknown answer - #{p_answer}" if !@answers.has_key?(p_answer)
  end
end

class VotingSystem
  
  @@topics = {}
  
  def self.add_topic(p_topic)
    @@topics[p_topic.name.downcase] = p_topic
    return self
  end
  
  def self.cast(p_topic_name, p_answer)
    topic_name = p_topic_name.downcase
    verify_valid_topic(topic_name)
    @@topics[topic_name].select_answer(p_answer)
  end
  
  # display all results if p_topic_name is not specified
  def self.result(p_topic_name = nil)
    if p_topic_name.nil?
      @@topics.each do |e_topic_name, e_topic|
        show_result_from(e_topic)
      end
    else
      topic_name = p_topic_name.downcase
      verify_valid_topic(topic_name)
      show_result_from(@@topics[topic_name])
    end
  end
  
  private
  def self.verify_valid_topic(p_topic_name)
    raise "You have selected an unknown topic - #{p_topic_name}" if !@@topics.has_key?(p_topic_name)
  end
  
  def self.show_result_from(p_topic)
    puts "Topic - '#{p_topic.name}'"
    p_topic.answers.each do |e_answer, e_count|
      puts "#{e_count} people agreed on '#{e_answer}'"
    end
  end
end

# usages 

# setup voting system with topics
VotingSystem.add_topic(Topic.new("is 'the flinstones' a boring t.v. show?").add_answer("yes, it sucks!").add_answer("no, it rocks!"))
# yet another topic to vote
VotingSystem.add_topic(Topic.new("should i ask again?").add_answer("yes, go on!").add_answer("no, its ok!"))

# add few casts
VotingSystem.cast("is 'the flinstones' a boring t.v. show?", "yes, it sucks!")
VotingSystem.cast("should i ask again?", "no, its ok!")

# view all results
VotingSystem.result

# view specific result
puts "--------------"
VotingSystem.result("is 'the flinstones' a boring t.v. show?")
</code>
      <code-id type="integer">283</code-id>
      <comment>most of the suggestions are great, here is my one. 
while i complied this suggestion i had the following points in mind - 
 1. extensibility 
 2. simplicity in terms of exposing api
 
</comment>
      <created-at type="datetime">2008-04-19T07:29:53+00:00</created-at>
      <id type="integer">5297</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 6th edition</title>
      <user-id type="integer">379</user-id>
      <user-name>we4tech</user-name>
      <user-website nil="true"></user-website>
    </refactor>
    <refactor>
      <code>class Poll
  attr_accessor :question
  def initialize(question, answers=[])
    @question, @answers = question, {}
    answers.each {|key| @answers[key] = 0}
  end
  
  def vote_for(answer)
    raise 'unknown answer' unless @answers.has_key?(answer)
    @answers[answer] += 1
  end
  
  def results
    @answers.each { |answer, votes| puts "#{votes} : #{answer}" }
    puts "Out of #{@answers.values.inject {|memo,v| v + memo}} votes"
  end
end

&gt;&gt; p = Poll.new("can haz chezburger?", ["laterz", "nao"])
=&gt; #&lt;Poll:0x35cb2c @answers={"laterz"=&gt;0, "nao"=&gt;0}, @question="can haz chezburger?"&gt;
&gt;&gt; p.vote_for "nao"
=&gt; 1
&gt;&gt; p.vote_for "nao"
=&gt; 2
&gt;&gt; p.vote_for "laterz"
=&gt; 1
&gt;&gt; p.results
1 : laterz
2 : nao
Out of 3 votes</code>
      <code-id type="integer">283</code-id>
      <comment>System is a vile word in a class name. It is meaningless and encourages a pile up of concerns that should remain separated.

Since that dude retired 2 weeks ago, I think it's safe to scrap that piece of code. Normally it's better to refactor than re-write... but this is egregious.</comment>
      <created-at type="datetime">2008-05-04T00:11:43+00:00</created-at>
      <id type="integer">6036</id>
      <language>Ruby</language>
      <rating type="integer">5</rating>
      <ratings-count type="integer">1</ratings-count>
      <title>On Rubyize this : 6th edition</title>
      <user-id type="integer">3</user-id>
      <user-name>danielharan</user-name>
      <user-website>http://danielharan.com/</user-website>
    </refactor>
  </refactors>
</code>
