1

I am pulling bitbucket repo list using Ruby. The response from bitbucket will contain only 10 repositories and a marker for the next page where there will be another 10 repos and so on ... (they call it pagination)

So, I wrote a recursive function which calls itself if the next page marker is present. This will continue until it reaches the last page.

Here is my code:

#!/usr/local/bin/ruby
require 'net/http'
require 'json'
require 'awesome_print'

@repos = Array.new

def recursive(url)

    ### here goes my net/http code which connects to bitbucket and pulls back the response in a JSON as request.body 
    ### hence, removing this code for brevity

    hash = JSON.parse(response.body)

    hash["values"].each do |x|
        @repos << x["links"]["self"]["href"]
    end

    if hash["next"]
        puts "next page exists"
        puts "calling recusrisve with: #{hash["next"]}"
        recursive(hash["next"])
    else
        puts "this is the last page. No more recursions"
    end
end

repo_list = recursive('https://my_bitbucket_url')
@repos.each {|x| puts x}

Now, my code works fine and it lists all the repos.

Question: I am new to Ruby, so I am not sure about the way I have used the global variable @repos = Array.new above. If I define the array in function, then each call to the function will create a new array overwriting its contents from previous call.

So, how do the Ruby programmers use a global symbol in such cases. Does my code obey Ruby ethics or is it something really amateur (yet correct because it works) way of doing it.

undur_gongor
  • 15,657
  • 5
  • 63
  • 75
slayedbylucifer
  • 22,878
  • 16
  • 94
  • 123

1 Answers1

6

The consensus is to avoid global variables as much as possible.

I would either build the collection recursively like this:

def recursive(url)
  ### ...

  result = [] 

  hash["values"].each do |x|
    result << x["links"]["self"]["href"]
  end

  if hash["next"]
    result += recursive(hash["next"])
  end
  result
end

or hand over the collection to the function:

def recursive(url, result = [])
  ### ...

  hash["values"].each do |x|
    result << x["links"]["self"]["href"]
  end

  if hash["next"]
    recursive(hash["next"], result)
  end
  result
end

Either way you can call the function

repo_list = recursive(url)

And I would write it like this:

def recursive(url)
  # ...

  result = hash["values"].map { |x| x["links"]["self"]["href"] }
  result += recursive(hash["next"]) if hash["next"]
  result
end
undur_gongor
  • 15,657
  • 5
  • 63
  • 75
  • The `+=` approach I had never used for arrays. So was not aware of that. I think this is what I exactly needed. I knew from the beginning the way I have defined the variable is not looking good. Thanks for your time and answer. I will go with the 2nd approach `def recursive(url, result = [])`. – slayedbylucifer Feb 27 '15 at 10:30