LoginSignup
21
21

More than 3 years have passed since last update.

ruby と rails のバージョン表 (ついでに関数プログラミング)

Last updated at Posted at 2015-01-26

自動更新するやつ作ったった。
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 って書きたい気分だけど綺麗に書けない。

21
21
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
21