配列同士でどちらかに所属する要素を取り出す

やりがちな書き方

a = [1, 2, 3]
b = [2, 3, 4]

c = (a + b).uniq #=> [1, 2, 3, 4]

これは集合で言うと和集合になる。RubyではArray同士の和集合を出力するメソッド | がある

https://docs.ruby-lang.org/ja/latest/class/Array.html#I_--7C

なので、元のコードは下記のように書き直せる

続きを読む

オブジェクト指向設計実践ガイドを読んだ

今更ながら読んだ。

書いてる内容は今の自分にとってはふんふんそうだよね。という感じ。 以下、思った点

続きを読む

dotfilesを一元管理するときにちょっと苦が減る方法

.vimrc、.zshrc、.gitconfigといったいわゆるドットファイルを複数のマシンで使いまわすためにgithubに置くってところまでは誰もがやっているところだと思う。 ただ、それだけだといちいちローカルにコピーするとか、編集後にdotfileにコピーして…なんてめんどくさくてやらないことが多い 結果として会社のPCで登録したaliasを個人macで使おうとしたら登録してなかったり、家で試したvimプラグインを反映し忘れてててげんなりする。 というわけで最近以下のようにローカルのファイルは外部ファイル読み込みにしてしまった

続きを読む

【Ruby】正規表現で文字列を置き換えようとしてハマった

ある文字列について、あるパターンに合致した部分を装飾して置き換えたいことがあった。

例えば、「123hoge456」を「123 + hoge + 456」みたいにhogeをマッチさせて再利用する感じ。

そのためのコードを以下のように書いたのだが思ったように動かない。

str = "123hoge456"
str.sub!(/(hoge)/, " + #{$1} + ") # => "123 +  + 456"

どうやら、$1に何も入っていない? そう思って次の行で$1を出力してみる

1    a = "123hoge456"
2    a.sub!(/(hoge)/, " + #{$1} + ") # => "123 +  + 456"
3    p $1 # => "hoge"

あれ、$1にはちゃんと入っている??
更に、実際には書いてたコードでは2回こういう処理するようになってたのに更に奇妙な挙動になってた

1    a = "123hoge456"
2    b = "123huga456"
3    a.sub!(/(hoge)/, " + #{$1} + ") # => "123 +  + 456"
4    b.sub!(/(huga)/, " + #{$1} + ") # => "123 + hoge + 456"

ここで分かった人には分かったと思うのだが、実は最初のsubの呼び出し時点ではまだ$1はnilになっているのが原因。
3行目が終わったところでは$1に"hoge"が入っているので、さっきの例では出力できたし、この例では次の4行目の引数に与えられている。
なんとなく第一引数の正規表現がすぐに処理されているように感じるけど、メソッド呼び出す時点では処理されていないってわけで。
なるほどなー

じゃ本来やりたかったことをやるにはどうすればよいかというと、以下のようにsubにブロックを渡してやると良い。

1    a = "123hoge456"
2    a.sub!(/(hoge)/){ " + #{$1} + " } # => "123 + hoge + 456"

更に言うと、そもそもブロック使うならマッチ部分を受け取れるので、

1    a = "123hoge456"
2    a.sub!(/(hoge)/){|match|  " + #{match} + " }# => "123 + hoge + 456"

これで事足りるのであった。。。

よくよくみたらリファレンスにも書かれてた。
http://docs.ruby-lang.org/ja/2.1.0/class/String.html#I_SUB

注意:

第 2 引数 replace に $1 を埋め込んでも意図した結果にはなりません。 この文字列が評価される時> 点ではまだ正規表現マッチが行われておらず、 $1 がセットされていないからです。

入門Chef soloを読んだ

入門Chef Solo - Infrastructure as Code

入門Chef Solo - Infrastructure as Code

Wordpressでなんか作ろうかと思っているのだけど、手元のVagrantで開発環境作りたいなーと思ってて、どうせならChefでインフラの構成管理してみるかってことで今更ながらChefを本格的に触ってみた。

意外とネットではわからなかったChef入門

今までもどんなもんかは大体知ってたつもりだったからネットで入門記事でも見れば使えるだろうと思って読み始める…がどれもまったくわからない。
いや、書いてあることはわかるし動くには動くんだけど用語とか概念がわからない。肝心なところの説明があっさりしていて、失礼ながらほんとに理解できてますかとか思ってしまうレベル。
おそらく紙面の都合とか無理に説明しようとすると複雑すぎてかえってわかりづらいとかだろうけど…

かといって公式ドキュメントはそれはそれは難解っていう。

このような状況で体系的にChefの説明をしていてわかりやすい本でも読みたいなってところで調べてみると候補は以下の感じ、

参考;書評「Chef活用ガイド」と「Chef実践入門」について - さよならインターネット

Chef実践入門 ~コードによるインフラ構成の自動化 (WEB+DB PRESS plus)

Chef実践入門 ~コードによるインフラ構成の自動化 (WEB+DB PRESS plus)

Chef活用ガイド コードではじめる構成管理

Chef活用ガイド コードではじめる構成管理

この二冊は圧倒的知名度だし、このどちらかにしようと最初は考えてた。
Kindleで読みたいなってところから前者よりだったんだけど、レビューによると長くて厚いリファレンス本臭がするしなぁと迷っていたんだけど、@naoya_itoさんの「入門Chef Solo」がボリューム的にも内容的にも価格的にもベストじゃね?とか思って勢いで買った。

恐縮ながら書評

結果的にはベストチョイスだった。
凄くわかりやすいしボリュームの割に網羅的。 目次を見れば一目瞭然。

第1章 Chefとは何かを知りたい ─ Chef Overview

第2章 Chef Soloをインストールして試したい ─ Hello Chef!

第3章 nginxをChef Soloで立ち上げたい

第4章 Chef Soloの試験環境を3分で用意する ─ Vagrant

第5章 リモートからchef-soloを実行する ─ knife-solo

第6章 レシピを作って実行する流れをおさらいしたい

第7章 サードパーティのChef クックブックを使いたい

第8章 代表的なレシピのサンプルを見たい ─ td-agent のレシピを読む

第9章 パッケージをインストールする ─ Package

第10章 サービスを起動したい ─ ServiceとNotification

第11章 テンプレートから設定ファイルを配置したい ─ Template

第12章 ファイルやディレクトリを扱いたい ─ Cookbook File, Directory

第13章 ユーザーを作成したい ─ User, Group

第14章 gitレポジトリからファイルを取ってくる ─ Git

第15章 任意のシェルスクリプトを実行したい ─ Execute, Script

第16章 その他のResource

第17章 レシピ落ち穂拾い ─ run_list, ファイル分け, include_recipe

第18章 Resourceを自分で定義したい ─ Definition

第19章 AttributeとData Bag

第20章 ノードを役割ごとにグルーピングして管理したい ─ Role

第21章 サードパーティのクックブックをBundler 風に管理したい ─ Berkshelf

第22章 Chef Serverの様子を知りたい ─ 概要からセットアップまで

第23章 どこまでをChefでやるべきか

一見「長っ!」って感じだけどこれだけの内容で百数十ページでさらさら読めるのでそこは安心していただきたい。

これをひと通り読めば公式のcookbookが読めるようになるからそれの利用とか編集もできるようになる(読む前は正直意味不明だったw)
あと読んでて印象深かったのは、下記の部分

このスナップショット機能をはじめとする AWS の各種サービス利用すると、そうでは ない場合に比較して運用が非常に楽になりました。それだけでも十分に楽だったので、こ れ以上の自動化は必要無いかな......なんて思っていました。 ところがスナップショットを多数とって管理しているうちに、どのスナップショットが どういった状態で保存されたものなのかを管理するのが大変になってきました。

これはまさに僕も思っていて、AWSのAMIみたいなスナップショットがあれば別にいいんじゃね?って最初は思ってたんだけど、古いスナップショットとか結局何が今と違うのかわからなくなるんだよね。

すべての状態はコードに記 載されているので記憶に頼る必要はありませんし、履歴は git でバージョン管理されてい ます。インスタンスを立ち上げたらとりあえずレシピを適用しておけば、思ったとおりの 状態にノードが収束してくれます。こんなに良いことはないですね。

Chef使うとここが解消されるってね。フンフンなるほどなーという感じだった。インフラをコードで扱えることの真髄だね。
利点はわかってるつもりだったけど改めて再認識。

価格も手頃だし、マジでおすすめします。

入門Chef Solo - Infrastructure as Code

入門Chef Solo - Infrastructure as Code

達人出版会ならpdfでも買えます。

補足1

書籍の中で、nginxをインストールするためにepelを追加する場面があるのだけど、

{
   "run_list" : [
     "yum::epel"
   ]
}

実は、この書籍が発行された後にyumのcookbookがバージョンアップしていて、yumのrecipeからepelというのはなくなっている。
なのでこのまま実行すると、

Chef::Exceptions::RecipeNotFound
--------------------------------
could not find recipe epel for cookbook yum

こんな感じで怒られる。
対応方法は2つある。

  1. yum-epelを使う
    これを落としてきて使う。コマンド的にはこんな感じ

  $ knife cookbook site install yum-epel
  $ vi nodes/hoge.json

  {
   "run_list" : [
       "yum-epel",
       "nginx"
    ]
  }  

2. yumyum_repositoryというResourceを使って自分で定義する
自分で書いたnginxのrecipeを以下のように追記して、nodeの方はいじらない。
詳しくはyumのcookbookのREADME.mdに例が書いてある。

yum_repository 'epel' do
  description 'Extra Packages for Enterprise Linux'
  mirrorlist 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-6&arch=$basearch'
  gpgkey 'http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6'
  action :create
end

更に補足

epelからnginx入れるとバージョンが1.0.15になる。
最新のStableバージョンが1.6.1なのでだいぶレガシーである…
これを回避して新しいバージョンを入れる方法は別エントリで書きます。