github page/ DHH Score Challenge in ruby I wrote the following code which when executed prints the score of https://github.com/dhh.

require 'typhoeus'
require 'json'

class DHHScoreChallenge
    def getData
        req = Typhoeus.get("https://api.github.com/users/dhh/events/public")
        body =  req.body
        json_body = JSON.parse(body)
   end

   def calculateScore json_body
       type_and_score = {
          :IssuesEvent =&gt; 7,
          :IssueCommentEvent =&gt;  6,
          :PushEvent =&gt; 5,
          :PullRequestReviewCommentEvent =&gt; 4,
          :WatchEvent =&gt; 3,
          :CreateEvent =&gt; 2
       }
       score = 0
       json_body.each do |commit|
          commit_type =  commit['type']
          if type_and_score.has_key? commit_type.to_sym
             score = score + type_and_score[commit_type.to_sym] 
          else
             score = score + 1
         end
       end
       score
   end

   def showScore score
      puts "DHH's github score is #{score}"
   end
end

begin 
    d = DHHScoreChallenge.new
    json_body = d.getData
    score = d.calculateScore(json_body)
    d.showScore(score)
end


I am a beginner in ruby programming and would like to know the best practices of Ruby. I am trying to include portability, encapsulation, reusability in my code. Please let me know if they have been achieved and if there are any improvements that I can make. 
Thanks in advance!
The major thing I see is, the code is imperative. But things will be lot more easier to read and follow, if you practise declarative way of writing code.

I would not name the class as DHHScoreChallenge. It should be ScoreChallenge, so that it can be used for any user that we pass in :)

I would make the method getData private, in order to externalise the service layer dependency.

Also I would move the type_and_score into a class level map

This logic is too complex to read

if type_and_score.has_key? commit_type.to_sym
  score = score + type_and_score[commit_type.to_sym] 
else
  score = score + 1
end


This could have eliminated by using a combination of dig and fetch. Dig will return nil if you cannot find the key in hash and fetch on a hash can return a value if the value of the key returns nil

Also I see that you are converting the event key to symbol and trying to find the symbol in hash. Instead you might as well have created a hash with strings as symbols, it won't be much of a over head if you freeze the hash.

Something like this

  EVENTS_SCORE_MAP = {
    'IssuesEvent' =&gt; 7,
    'IssueCommentEvent' =&gt; 6,
    'PushEvent' =&gt; 5,
    'PullRequestReviewCommentEvent' =&gt; 4,
    'WatchEvent' =&gt; 3,
    'CreateEvent' =&gt; 2
  }.freeze

 EVENTS_SCORE_MAP.fetch(event.dig('type'), 1)


I rewrote the whole thing in a manner which I would in my production system

require 'typhoeus'
require 'json'

# Github service dealing with all the requests to github
class Github
  def events(user_name)
    url = "https://api.github.com/users/#{user_name}/events/public"
    send_request(
      lambda {
        Typhoeus.get(url)
      }, url
    )
  end

  private

  def send_request(request, path)
    request.call
  rescue Timeout::Error
    raise GatewayTimeoutError.new(gateway: 'github api timed out', path: path)
  end
end

# This class deals calculating the score
class ScoreChallenge
  EVENTS_SCORE_MAP = {
    'IssuesEvent' =&gt; 7,
    'IssueCommentEvent' =&gt; 6,
    'PushEvent' =&gt; 5,
    'PullRequestReviewCommentEvent' =&gt; 4,
    'WatchEvent' =&gt; 3,
    'CreateEvent' =&gt; 2
  }.freeze

  def initialize(user_name, score = 0)
    @user_name = user_name
    @score = score
  end

  def pretty_score
    calculate
    puts "#{@user_name} github score is #{@score}"
  end

  private

  def calculate
    events_of_user = JSON.parse(github_service.events(@user_name).body)
    events_of_user.each do |event|
      @score += EVENTS_SCORE_MAP.fetch(event.dig('type'), 1)
    end
  end

  def github_service
    @github_service = Github.new
  end
end

score_challenge = ScoreChallenge.new('DHH')
score_challenge.pretty_score


As you can see, I have exposed only one method called pretty_score. Which does everything that we need. This is the declarative style of programming I was talking about. I am letting my code figure out what to do, rather than me telling it do something step by step

Also Github is a service class I have created. It should ideally sit under a services folder. I have not implemented GatewayTimeoutError here, but for all practical purposes we should assume that these third party services can timeout/error out we should be able to handle them. You can also look into passing blocks, and custom errors as part of the above code.