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.

2
  • A global variable is define with prefix $. @ marks class instance variables of the current object. Commented Feb 27, 2015 at 9:36
  • This question may help stackoverflow.com/questions/1042384/… Commented Feb 27, 2015 at 9:36

1 Answer 1

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
Sign up to request clarification or add additional context in comments.

1 Comment

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 = []).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.