Whenever I get asked what’s the best way to learn a programming language, my answer is by building things. I suggest starting by writing simple Ruby scripts that perform some useful tasks.
Easier said than done, especially when it’s all new and you don’t know where to start. There is a lot of resources on how to write Ruby on Rails apps, but much less on how to write scripts. I’d like to share with you some tips on how I approach it.
A few days ago I wrote a blog post Top 10 most popular Rails repositories to get familiar with real-world apps. I had a list of over 100 links to Ruby on Rails apps on Github. I wrote a script to get the number of stars from GitHub, sort the list, and output the top 10 links as a markdown list. I’ll use it as an example for this post.
Try to define the task that transforms inputs to your desired output.
In my case, I have a file where each line is a link to the GitHub repository. What I want my script to do is:
Now you can play with things you don’t know, these ‘somehows’. In my case, it was ‘somehow get the number of stars’. I checked GitHub docs and found out, that they output this value in one of the endpoints, I just need to create an access token. Then I searched for Ruby gem that will make working with GitHub API quick and easy. I found the octokit gem.
In your case these unknowns can be ‘somehow open a file’ or ‘somehow sort an array’, but when you know what you don’t know, it’s much easier to fix it.
When writing small scripts, I often try new things by starting irb
session and playing there.
For example, I’ve never used the octokit gem and GitHub API, so I installed it, started irb
, and tried:
require 'octokit'
client = Octokit::Client.new(:access_token => "MY_ACCESS_TOKEN")
repo = client.repo('discourse/discourse')
I checked what repo
object looks like and found out that I can get the number of stars using #watchers
method.
If you cannot find anything interesting by just printing it, you can always check the object’s class names and lookup them in the documentation.
Don’t try to write it all in one take. Set some small checkpoints, code and run it, fix errors, until you get to the checkpoint. Then move to the next one. Use puts
and pry
gem to help you with this.
In my example, the first step would be to open a file and read it line by line, do nothing with these lines just print it:
File.readlines('open-source-rails-apps.txt').each do |line|
puts line
end
Ok, it’s working. I played with the octokit gem in console, so I know that to get repository details I need to have its full name, not the URL like I have in my list. Let’s try to output full names then.
File.readlines('open-source-rails-apps.txt').each do |line|
puts line.gsub('https://github.com/', '')
end
Great, now I have full names, so time to get repository details, I use pry
gem to check out what’s inside such a repo.
require 'octokit'
require 'pry'
client = Octokit::Client.new(access_token: 'MY_ACCESS_TOKEN')
File.readlines('open-source-rails-apps.txt').each do |line|
repo = client.repo(line.gsub('https://github.com/', ''))
binding.pry
end
Oops, I get an error that disourse/discourse\\n
is not a valid repository name, I’ll remove the end of line character from the end and run it again.
require 'octokit'
require 'pry'
client = Octokit::Client.new(access_token: 'MY_ACCESS_TOKEN')
File.readlines('open-source-rails-apps.txt').each do |line|
repo = client.repo(line.gsub('https://github.com/', '').chomp)
binding.pry
end
Now program stops on the binding.pry
line. I enter repo
to check how it looks. I see there is #watchers
method that returns the number of stars. I’ll use it later, #full_name
and #url
methods as well. I don’t need to download the rest of the repositories, so just enter exit-program
. The next step is to store these repository objects in an array. I’ll sort it later.
require 'octokit'
client = Octokit::Client.new(access_token: 'MY_ACCESS_TOKEN')
repositories = []
File.readlines('open-source-rails-apps.txt').each do |line|
repo = client.repo(line.gsub('https://github.com/', '').chomp)
repositories << repo
end
puts repositories.count
All repositories are loaded to an array, now it’s time to sort it and take the first 10 elements.
require 'octokit'
client = Octokit::Client.new(access_token: 'MY_ACCESS_TOKEN')
repositories = []
File.readlines('open-source-rails-apps.txt').each do |line|
repo = client.repo(line.gsub('https://github.com/', '').chomp)
repositories << repo
end
repositories.sort{|repo| repo.watchers}.first(10).each{|repo| puts repo.watchers}
It works, now I need to output it in the correct format.
require 'octokit'
client = Octokit::Client.new(access_token: 'MY_ACCESS_TOKEN')
repositories = []
File.readlines('open-source-rails-apps.txt').each do |line|
repo = client.repo(line.gsub('https://github.com/', '').chomp)
repositories << repo
end
repositories
.sort{|repo| repo.watchers}
.first(10)
.each.with_index(1){|repo, index| "#{index}. [#{repo.full_name}](#{repo.url})"}
and the list is ready to copy/paste :)
Of course, with experience, these steps are bigger, but more or less, that’s the way I write these kinds of scripts. Hope it helps you.
Happy scripting :)