リファクタリングRuby読書記録(6.20-8.3)

読んだ。

  • 委譲の隠蔽とその逆
  • 自己カプセル化フィールド
  • 値から参照へ

あたりがおもしろかった。フィールドアクセスについての派閥があるというのを初めて知った。クラス内では自由にフィールドにアクセスできるべき、という直接変数アクセス派とクラス内でも必ずgetter/setterを使うべきという間接変数アクセス派がある。自分は直接変数アクセスから始めるタイプだな。

PackStack with Vagrant (2016-09-25)

devstackを使っていたけど、毎回どこかでハマるのでpackstackを使ってみる。

例によってVagrantで楽に構築したかったので、上記ページを参考にしてVagrantfileを作った。

Vagrantfile

ダッシュボード用にポートフォワードしておく。

# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
  config.vm.box = "centos/7"
  
  config.vm.network "forwarded_port", guest: 5000, host: 5000
  config.vm.network "forwarded_port", guest: 80, host: 8080

  config.vm.synced_folder ".", "/vagrant"
  config.vm.provider "virtualbox" do |vb|
    vb.cpus = 2
    vb.memory = 8192
  end
 
  config.vm.provision "shell", path: "provision.sh"

  config.vm.define 'controller' do |manage|
    manage.vm.hostname = 'controller'
    manage.vm.network :private_network, ip: "192.168.33.10", virtualbox__intnet: "intnet"
  end
end

provision.sh

手順の通りにセットアップするだけのシェルスクリプト。

sudo systemctl disable firewalld
sudo systemctl stop firewalld
sudo systemctl disable NetworkManager
sudo systemctl stop NetworkManager
sudo systemctl enable network
sudo systemctl start network

sudo yum install -y https://rdoproject.org/repos/rdo-release.rpm
sudo yum install -y centos-release-openstack-mitaka
sudo yum update -y
sudo yum install -y openstack-packstack

vaagrnt upしてAllInOneで構築

$ vagrant up controller
$ packstack --allinone
$ sudo cat /root/keystonerc_demo
unset OS_SERVICE_TOKEN
export OS_USERNAME=demo
export OS_PASSWORD=c4f25cd303da4fc7
export PS1='[\u@\h \W(keystone_demo)]\$ '
export OS_AUTH_URL=http://10.0.2.15:5000/v2.0

export OS_TENANT_NAME=demo
export OS_IDENTITY_API_VERSION=2.0

ブラウザでHorizonにアクセスできる。

http://localhost:8080/dashboard

リファクタリングRuby読書記録(6.9-6.19)

Rubyらしいテクニックが増えてきた。興味深かったのは以下4つ。

  • サンドイッチメソッドの抽出
  • クラスアノテーションの導入
  • 動的メソッド定義
  • 動的レセプタから動的メソッド定義へ

それぞれのテクニックを組み合わる手法もサンプルとして紹介されており、勉強になった。

Rubyでstdoutl/errを標準出力/エラーとファイルの両方に出力する

stdout/stderrをファイルにも出力したくていろいろ調べて、いい感じの解決方法を見つけたのでメモしておく。

ruby-listにmatzが投稿していた(Re: puts,printの出力をファイルにも出力するには)。

これを実行すると、こうなる。

defout = Object.new
defout.instance_eval{@ofile=open("/tmp/test.log", "w")}
class <<defout
  def write(str)
    STDOUT.write(str)
    @ofile.write(str)
  end
end
$stdout = defout

puts 'aaa'
$ ruby ./test.rb
aaa
$ cat ./test.log
aaa

なるほど、標準出力と標準エラーにputsされている。便利。

これができると、次はstdoutとstderrの両方をファイルにも出力したくなる。その場合はこうしちゃえばいい。

defout = Object.new
defout.instance_eval{@ofile=open("/tmp/test.log", "a")}
class <<defout
  def write(str)
    STDOUT.write(str)
    @ofile.write(str)
    @ofile.flush
  end
end
$stdout = defout

deferr = Object.new
deferr.instance_eval{@ofile=open("/tmp/test.log", "a")}
class <<deferr
  def write(str)
    STDERR.write(str)
    @ofile.write(str)
    @ofile.flush
  end
end
$stderr = deferr

puts 'aaa'
warn 'bbb'
puts 'ccc'
$ ruby ./test.rb
aaa
bbb
ccc
$ cat ./test.log
aaa
bbb
ccc

flushしないとtest.logにstdoutが先に全て出力され、その後にstderrが出力されてしまうようだ。また、この方法だとsystemのような子プロセスの出力はteeされないので注意しないといけない。