自動更新するやつ作ったった。
https://rails-versions.kbn.one/
以下解説。
手続き
最初に書いたコードがこれ。
# gem install octokit
require 'octokit'
require 'yaml'
TARGET = 'rails/rails'
Octokit.auto_paginate = true
hash = {}
Octokit.tags(TARGET).each do |tag|
next if tag['name'].include?('rc') || tag['name'].include?('beta')
res = Net::HTTP.get(URI.parse("https://raw.githubusercontent.com/#{TARGET}/#{tag['commit']['sha']}/.travis.yml"))
travis = YAML.load(res)
break if travis.nil? || travis['rvm'].nil?
hash[tag['name']] = travis['rvm'].map(&:to_s)
end
columns = hash.values.flatten.uniq.sort
puts "rails|#{columns.join('|')}"
puts (["---"] * (columns.length + 1)).join('|')
hash.each do |k,v|
puts "#{k}|" + columns.map{|c| v.include?(c) ? 'o' : ''}.join('|')
end
関数型パラダイム
関数パラダイムを意識して書きなおしたのがこれ。
値の変化する変数を出来るだけ使わないように、変化する場合はスコープが出来るだけ小さくなるようにした。
# gem install octokit
require 'octokit'
require 'yaml'
TARGET = 'rails/rails'
def main
md_table 'rails', tags.lazy.map(&method(:pair)).take_while{|k,v| v}.to_h
end
def md_table(name, hash)
columns = hash.values.flatten.uniq.sort
lines = ["#{name}|#{columns.join('|')}"]
lines << (["---"] * (columns.length + 1)).join('|')
lines + hash.map{|k,v| "#{k}|" + columns.map{|c| v.include?(c) ? 'o' : ''}.join('|')}
end
def tags
Octokit.auto_paginate = true
Octokit.tags(TARGET).reject{|tag| tag['name'].include?('rc') || tag['name'].include?('beta') }
end
def pair(tag)
[tag['name'], rvm_list_on(tag['commit']['sha'])]
end
def rvm_list_on(sha)
travis = yaml("https://raw.githubusercontent.com/#{TARGET}/#{sha}/.travis.yml")
return nil if travis.nil? || travis['rvm'].nil?
travis['rvm'].map(&:to_s)
end
def yaml(url)
YAML.load(Net::HTTP.get(URI.parse(url)))
end
puts main
各メソッドの役割が明確になり、独立していて、ユニットテストを書きやすくなった。
コード量は若干増えたが、読みやすく、保守性の高いコードになったと思う。
書き換えるにあたり、 kenokabe 氏の投稿が大いに参考になった。 http://qiita.com/kenokabe/items/618692858044a89adbc0
消されてしまって残念です。
課題
-
map(&method(:pair)).take_while{|k,v| v}
のとこはなんかもっと別の書き方がありそうな気がする - 本当は
md_table enum.to_h
じゃなくてenum.to_h.to_md_table
って書きたい気分だけど綺麗に書けない。