Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

best-rubyで55のRuby のテクニック・イディオム・リファクタリング手法について知る

f:id:tbpg:20170224001009p:plain

best-ruby というサイトで55個の Ruby のテクニック・イディオム・リファクタリング手法について紹介しています。
※2017/02/23 時点で55個でしたが、増えたり減ったりするかもしれません

コンテンツは Tricks, Idiomatic Ruby, Refactorings, Best Practices の4つに分類されています。
※ここで紹介されている手法は Ruby Tricks, Idiomatic Ruby, Refactorings and Best Practices で紹介されていたものをベースに作ったサンプルコードです

Tricks

例: 簡易DB pstore

Rubyのオブジェクトを外部ファイルに格納するためのクラスです。
この例では実行時のパスに person.pstore として保存されます。

  • commit のケース
require 'pp'
require 'pstore'

db = PStore.new('person.pstore')

db.transaction do
  DATA.read.each_line.map(&:chomp).each.with_index(1) do |line, i|
    name, age = line.split(',')
    db["name#{i}"] = name
    db["age#{i}"] = age
  end
  db.commit
end

# readonly
db.transaction(true) do
  pp db.roots
  # => ["name1", "age1", "name2", "age2", "name3", "age3"]
end

__END__
tanaka,34
suzuki,24
sato,23
  • abort のケース
require 'pp'
require 'pstore'

db = PStore.new('person.pstore')

db.transaction do
  DATA.read.each_line.map(&:chomp).each.with_index(1) do |line, i|
    name, age = line.split(',')
    db["name#{i}"] = name
    db["age#{i}"] = age
  end
  db.abort
end

# readonly
db.transaction(true) do
  pp db.roots
  # => []
end

__END__
tanaka,34
suzuki,24
sato,23

pstore に関しては るりま にもまとまっています。

pstore - るりま

Idiomatic Ruby

変数の swap のイディオム

require "pp"

big = 99
small = 11
pp big
pp small
big, small = small, big
pp big
pp small

# => 99
# => 11
# => 11
# => 99

Refactorings

case の分岐によって生成するクラスを切り替えるとき。
かつ、クラスのコンストラクタの引数が統一されているとき。
best-ruby では case の代わりに Hash を利用することを勧めています。

Before

case 文のケース

require "pp"

class Rubyist
  def say_papa
    puts "Matz"
  end
end

class Perler
  def say_papa
    puts "Larry Wall"
  end
end

class PHPer
  def say_papa
    puts "Rasmus Lerdorf"
  end
end

def factory(main_language)
  case main_language
  when "ruby" then Rubyist
  when "perl" then Perler
  when "php" then PHPer
  end
end

DATA.each_line.map(&:chomp).each do |language|
  language_user = factory(language).new
  language_user.say_papa
end

__END__
ruby
perl
php
  • result
Matz
Larry Wall
Rasmus Lerdorf

Before

case 文のケース

require "pp"

class Rubyist
  def say_papa
    puts "Matz"
  end
end

class Perler
  def say_papa
    puts "Larry Wall"
  end
end

class PHPer
  def say_papa
    puts "Rasmus Lerdorf"
  end
end

LANGUAGE_USER_CLASSES = {
  "ruby" => Rubyist,
  "perl" => Perler,
  "php" => PHPer,
}

DATA.each_line.map(&:chomp).each do |language|
  language_user = LANGUAGE_USER_CLASSES[language].new
  language_user.say_papa
end

__END__
ruby
perl
php

参考資料

Best Practices

これは気になったらリンク先をどうぞ。

まとめ

掲載しているテクニックの数は55です。
どのくらい知っていたか一度チェックしておくとよさそうです。
(納得して使うかどうかは別として)

私は 30 / 55 知っていました。
別に多ければいいというものではないですけど。

外部資料