RubyのMixinを簡単にだけ整理したメモ
たまにはRubyを。
元ネタというかメインで参照したのはこちら
prependって結局どうなんだっけ?prependをクラスメソッドにするにはどうするんだっけ?というところを整理したかったので。
実行環境は、ruby2.3.1p112
ruby --version ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux]
サンプルコード
Abstract moduleを各クラスに突っ込む。
module Abstract def self.included(klass) puts "" puts "Included hook: #{klass}" puts "ancestors: #{klass.ancestors}" puts "singleton: #{klass.singleton_class.ancestors}" end def self.prepended(klass) puts "" puts "Prepended hook: #{klass}" puts "ancestors: #{klass.ancestors}" puts "singleton: #{klass.singleton_class.ancestors}" end def self.extended(klass) puts "" puts "Extended hook: #{klass}" puts "ancestors: #{klass.ancestors}" puts "singleton: #{klass.singleton_class.ancestors}" end def say puts "Hello, World!" end end class Include include Abstract def say puts "Hello!" end end Include.new.say class Prepend prepend Abstract def say puts "Hello!" end end Prepend.new.say class Extend extend Abstract def self.say puts "Hello!" end end Extend.say class SelfPrepend class << self prepend Abstract def say puts "Hello!" end end end SelfPrepend.say class ClassPrepend singleton_class.prepend Abstract def self.say puts "Hello!" end end ClassPrepend.say
アウトプット
Included hook: Include ancestors: [Include, Abstract, Object, Kernel, BasicObject] singleton: [#<Class:Include>, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject] Hello! Prepended hook: Prepend ancestors: [Abstract, Prepend, Object, Kernel, BasicObject] singleton: [#<Class:Prepend>, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject] Hello, World! Extended hook: Extend ancestors: [Extend, Object, Kernel, BasicObject] singleton: [#<Class:Extend>, Abstract, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject] Hello! Prepended hook: #<Class:SelfPrepend> ancestors: [Abstract, #<Class:SelfPrepend>, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject] singleton: [#<Class:#<Class:SelfPrepend>>, #<Class:#<Class:Object>>, #<Class:#<Class:BasicObject>>, #<Class:Class>, #<Class:Module>, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject] Hello, World! Prepended hook: #<Class:ClassPrepend> ancestors: [Abstract, #<Class:ClassPrepend>, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject] singleton: [#<Class:#<Class:ClassPrepend>>, #<Class:#<Class:Object>>, #<Class:#<Class:BasicObject>>, #<Class:Class>, #<Class:Module>, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject] Hello, World!
理解したこと
prependはancestorsで考えたときに、子孫側に挿入される。
include/extendはancestorsで考えたときに、祖先側に挿入される。
extendは、singleton_class(特異クラス)に対して挿入される。
クラスメソッド(として扱うもの)をprepend
する書き方は2パターンある。(詳しく追っていないので、どちらかがまずい方法だ、みたいなツッコミ歓迎。)
Goで同時実行数を制限しながらループを並列処理する。
Web+DB Press Vol95 のGoの記事を読んで理解するために自分でも書いてみた。
- 作者: 小出淳子,黒澤剛志,牧大輔,横江亮佑,山口貴也,尾藤正人,佐藤琢哉,中橋研太郎,田中慎司,小西裕介,伊藤直也,稲富駿,前島真一,長野雅広,山際康貴,のざきひろふみ,うらがみ,岡林大,遠藤雅伸,ひげぽん,海野弘成,はまちや2,竹原,大場寧子,大場光一郎,野々下裕子,WEB+DB PRESS編集部
- 出版社/メーカー: 技術評論社
- 発売日: 2016/10/22
- メディア: 大型本
- この商品を含むブログを見る
秒単位でスリープ処理を入れてしまっているので、実行時間は長いです。そこはお勉強用ということで。
出力結果
time:2016-12-02 14:40:49.5804542 +0900 JST index:-1 item:-1 sleepなし。順番不定。 time:2016-12-02 14:40:49.580639488 +0900 JST index:2 item:3 time:2016-12-02 14:40:49.580686796 +0900 JST index:3 item:4 time:2016-12-02 14:40:49.580652343 +0900 JST index:0 item:1 time:2016-12-02 14:40:49.580703936 +0900 JST index:4 item:5 time:2016-12-02 14:40:49.580712672 +0900 JST index:5 item:6 time:2016-12-02 14:40:49.580725039 +0900 JST index:6 item:7 time:2016-12-02 14:40:49.580731445 +0900 JST index:1 item:2 sleepあり。順番に出力。 time:2016-12-02 14:40:50.582086998 +0900 JST index:0 item:1 time:2016-12-02 14:40:51.581872261 +0900 JST index:1 item:2 time:2016-12-02 14:40:52.581816362 +0900 JST index:2 item:3 time:2016-12-02 14:40:54.583265777 +0900 JST index:3 item:4 time:2016-12-02 14:40:56.583142187 +0900 JST index:4 item:5 time:2016-12-02 14:40:58.582018719 +0900 JST index:5 item:6 time:2016-12-02 14:41:01.584457553 +0900 JST index:6 item:7 sleepあり。Sleepの短い順番に出力。 time:2016-12-02 14:41:03.585628436 +0900 JST index:1 item:2 time:2016-12-02 14:41:04.58563381 +0900 JST index:0 item:3 time:2016-12-02 14:41:05.585852568 +0900 JST index:3 item:2 time:2016-12-02 14:41:06.585637432 +0900 JST index:2 item:5 time:2016-12-02 14:41:06.585995853 +0900 JST index:5 item:1 time:2016-12-02 14:41:12.586825274 +0900 JST index:4 item:8
セマフォ取得用のオブジェクトで、同時実行数の制限。deferで開放しないと詰まる。
WaitGroupでプログラムの待ちを設定。ないと、スリープ処理をしてる間にプログラムが終了してしまう。deferでセマフォを開放するタイミングで一緒にWaitGroupも減らす。
Certificate Managerを試す、、、ためのメール受信の設定
ケース
AWS Certificate Managerを使用して、SSL/TLS証明書を取得して、HTTPS接続を確立したい。
ドメインは、(お名前.comとかで)適当に取得しておいたものを使う。
問題
AWS Certificate Managerは、証明書の発行のときに、検証Eメールを送信する。自分(もしくは関係者)が、証明書の発行を承認する必要があるから。そりゃ当然なわけ。
送信先は、ヘルプにかかれている。2種類あって、WHOISに書かれたメールアドレスと、登録しようとしているドメインに適当なアカウント名をくっつけたメールアドレス。
Email is sent to the following three registered contact addresses in WHOIS:
- Domain registrant
- Technical contact
- Administrative contact
Email is also sent to the following five common system administration addresses where your_domain is the domain name that you entered when you initially requested the certificate.
- administrator@your_domain
- hostmaster@your_domain
- postmaster@your_domain
- webmaster@your_domain
- admin@your_domain
で、エンタープライズな人たちなら特に問題じゃないわけだけど。。。
その検証Eメールを受信できる状態じゃないと、前へ進めない。
お名前.comなんかでドメインを取得すると、whoisへの情報登録を代行してくれる。
代行してくれた登録情報は、お名前.comの会社の情報になるので、whoisの情報には、自分個人の情報は含まれていない、ということ。
個人利用にはありがたい代行サービスなんだけど、今回だけは、それが微妙。
目的
ということで、
AWS Certificate Managerが送信する送信先をつくります。
やり方
同じくAWSのサービスの、SESを使って、メールを受信する。
例として、example.jp
というドメインを持っていて、そのサブドメインapp.example.jp
のSSL/TLS証明書を発行する。ために、admin@app.example.jp
を受信できるようにする。
SESはこの記事を書いている時点(2016/11/08)では、まだ日本に提供されていないっぽいので、リージョンは適当に選んで使う。
事前準備:Route 53 の設定
もしDNSを設定していない状態であれば、Route 53にexample.jp
を登録する。
とりあえずHosted Zoneにexample.jp
を登録するだけでOK。
(ということで、Route 53を使う前提で書きます。)
ドメインの登録
- 左ペインのDomainsを選ぶ。
- Verify a New Domainボタンを押す。
- Domainを入力する。
- 今回のケースで登録するドメインは、
app.example.jp
- 今回のケースで登録するドメインは、
- DNSの設定について書かれている画面に切り替わる。
- Use Route 53で先に進む。
- Domain Verification Record(TXTレコード) と Email Receiving Reocrd(MXレコード)どちらも登録したいので、両方チェックを入れて、Create Record Sets。
- 少し待つと、ドメインのステータスが
verified
に変わる。
受信設定
- 左ペインのRule Setsを選ぶ。(Email Receivingの下)
- View Active Rule Setボタンを押す。
- Create Ruleボタンを押す。
- Recepientは空のままNext Step。(今回の場合は。本当は絞ったほうが良いはず。)
- Add actionで、S3を選ぶ。
- S3のバケットとかは適当に。新しく作るなり、
- prefixは、必要に応じて。
app.example.jp/
みたいにアカウント名を入れておくと便利そう。 - 今回の場合は暗号化は不要。(本当は暗号化したほうが良いはず。)
- Next Stepで先に進む。
- Rule nameは適当に。
- 他、デフォルトのままで、Next Step。
- Create Rule。
テスト
- 左ペインのDomainsを選ぶ。(戻る)
- 登録したドメイン(例:
app.example.jp
)を選ぶ。 - Send a Test Emailを押す。
- メールの内容を適当に入力して、送信。
- Toアドレスを
admin@app.example.jp
みたいにしておくと、Certificate Managerが送信先に指定するメールアドレスみたくなる。
- Toアドレスを
- S3をチェック。
- Ruleで設定したバケット、prefixの場所にメールがあるか?
- メールの内容が先ほど適当に入力したメールの内容に一致するか?
後は
Certificate Managerであれこれするだけ。
ELBの資料を読んだメモ
自分が業務で使いそうな範囲でメモに起こす。
ELB = L4のロードバランサー(Classic Load Balancer = CLB) + L7ベースのロードバランサー(Application Load Balancer = ALB)
ELB
ELBは複数AZをまたいで負荷分散が可能。
ヘルスチェックは細かく指定可能。以下の表は引用。 ウェブアプリケーションで未熟な状態なら、PingパスでDBの接続とかあれこれチェックできる状態にしておくのも一つの手か?
項目 例 メモ Ping プロトコル HTTP 200が返るか? Ping ポート 80 Ping パス /index.html HTTP/HTTPS利用の場合 タイムアウト時間 20秒 ヘルスチェック間隔 30秒 異常判定までの回数 4回 正常判定までの回数 2回 正常との判定が遅いと追加したインスタンスが使える前に時間がかかる。 逆に異常との判定が厳しすぎても過負荷時に処理できるインスタンスを減らしてしまうことも。
Route 53以外でDNSを使うときは、CNAMEで設定してELBに向ける。
サーバー証明書はELBにアップロード。Let's Encryptを使うときはどうする?的な話は別途調べる。→AWS Certificate Managerを使用する。証明書に対しての料金がかからない理解。アップロード作業も不要。
サーバーへの接続のソースIPはELBのIPアドレスになるので、X-Forwarded-For
ヘッダーを見る。
ELBにもセキュリティグループを設定できるので、今までEC2に設定していたセキュリティグループはELBだけを受け付けるようにして、ELB側で制限をかける。
ALB
コンテクストベースルーティングで、ルールにURLのパスが使える。振り分け先にはターゲットグループ(バックエンドサーバーをまとめたグループ)を指定。
WebsocketやHTTP/2にも対応。
料金 ALBの使用時間と、Load Balancer Capacity Units (LCU) の使用量で課金。
LCU 以下の3つのディメンションを測定し、使用量が最も高いディメンションのみ請求。
とりあえず変なことしなければ、CLBよりちょろっと安く済ませられるらしい。
ディメンションの項目から考えると、HTTP/2にちゃんと対応したほうが安くなるのか?
Git(hub)でフォークしたリポジトリに、オリジナルリポジトリの変更を取り込む
いつも忘れて調べなおすことになるので、メモ。
ケース
例えば、こんなリポジトリ。
オリジナルのプラグインでほんのすこしだけカスタマイズしたいから、ちょっとだけ修正して使ってる、みたいな。
で、時間が経って、変更されているものもあるから取り込みたい。
というときの作業。
参照
結論、Githubのヘルプを見ればいいわけですね。はい、いつも見ます。いつもたどり着くのに時間がかかりますが。
https://help.github.com/articles/fork-a-repo/help.github.com
https://help.github.com/articles/syncing-a-fork/help.github.com
この記事のこの後の内容は、ヘルプの内容をただただ自分のためにメモしたものです。
作業
ざっくり書くとこんな感じでしょうか。
git clone ${forked_repo} ${forked_repo_dir} cd ${forked_repo_dir} git remote add upstream ${original_repo} git fetch upstream git checkout master # forked master git merge upstream/master
自分の(忘れた後の)理解のために、細かく書いていくと、、、
フォークしてカスタマイズしたリポジトリGitHub - sugilog/molokai: Molokai color scheme for Vimに、オリジナルのリポジトリGitHub - tomasr/molokai: Molokai color scheme for Vimの修正内容を取り込む。
自分のリポジトリをclone
。
git clone git@github.com:sugilog/molokai.git ~/workspace/molokai
cd ~/workspace/molokai
オリジナルのリポジトリをupstream
という名前でリモートブランチとして登録。名前はかぶらなきゃOK。
git remote add upstream https://github.com/tomasr/molokai.git git fetch upstream
自分のリポジトリのブランチをcheckout
。とりあえずmaster
。
git checkout master
最後に、オリジナルの内容をマージ。
git merge upstream/master
あとはコンフリクトを直すなりなんなり。
結論、マージ作業なわけです。
GithubのウェブUIからのプルリク作業に慣れてきった生活で、簡単なマージ作業でさえ忘れてしまう。。。
最後に
molokai、お世話になってます。
tmux 2.3のキーバインディングでちょっと困った
macでtmuxを使っていてエラーが出て解決してたら次の問題にハマって、ということがあったので一連の話をメモ。
タイトルにしたキーバインディングは結局ググってもよくわからずソースを見て解決した話。
流れ
macOS Sierra にバージョンアップ。そしたら変なWARNINGメッセージが出るようになった。
Qiitaのまとめどおり、tmuxをアンインストール&再インストールしてみた。
ちなみにこの作業をした時のHEADはDo not force symbols to width 1, from Yen Chi Hsuan. · tmux/tmux@178894b · GitHub。
この時点で、tmuxのバージョンが2.3に更新された。元のバージョンは忘れたので省略。
tmux2.3を起動したら、またもや変なエラーメッセージが出始めた。
このときの自分のtmux.conf
はdotfiles/.tmux.conf at 42f0b71a673aad45921912766acc963948d0027b · sugilog/dotfiles · GitHubこんな感じ。
ブログにまとめられているとおり、-t vi-copy
を-T copy-mode-vi
にしてあれこれして、使い始めた。
dotfiles/.tmux.conf at 33c847acf64889f012859e234576fc85d8e1d36c · sugilog/dotfiles · GitHub
で、本題
copy-mode
のときに、スクロールアップがうまくできない。正確には、
copy-mode
でのj
,k
でのカーソル移動でのスクロールはできる。copy-mode
でのCtrl+f
でのスクロールダウンはできる。copy-mode
でのCtrl+b
でのスクロールアップができない。
(バインディングはvi)。
ググっても情報が見つからないのでソースにあたる。。。と見つけたコミット。
Ctrl+b
はコンフリクトがあるから、初期設定するのやめよう、とのこと。なるほどね。
ちなみに自分は関係ない人なので、自分で追加しちゃいます。
ちなみに自分のtmuxで使うprefix
キーはCtrl+t
(C-t
)です。
解決!
お粗末さまでした。
git logをltsvにする
コミットの情報をもとにファイルチェックとかしてみよう、という感じからgitだとどうしようということでログから情報を取り出す。
subversionで、svn ls -v <URL>
してとれるような情報のイメージ。
ついでにプログラムから加工しやすいようにLTSVにする。
git log -n 1 --format="hash:%H%x09author_date:%at" <file>
分解して理解
git log
: 省略
-n 1
: とりあえず今回は、指定したファイルに対する最新のコミットを取得できればいいので、1つだけ。
--format
: ログのフォーマットを指定する。続く引数内で、%
なんとかみたいにすると情報を埋め込めたりする。くわしくは、git help log
内のPRETTY FORMATS
を参照。
hash:
: ここまでは単なる文字列。LTSVのキー。
%H
: コミットハッシュ。 %h
にすると省略形(7桁くらいになってるやつ)のコミットハッシュ。
%x09
: %x
はあとに続く16進数のコードに対応した文字を埋め込む。09
はタブ。故にLTSVの区切り文字。
author_date:
: ここも単なる文字列。LTSVのキー。
%at
: author dateをunix timestampで表示する。rubyからなら、Time.at
を使えばTimeオブジェクトに変換できる。comitter dateを使うかどうかみたいな話はここの主題ではないので省略。
使用上の前提条件というか、現在のこの記事の状況。
- リモートリポジトリの情報をfetchしたりするのは別途必要ということで。
- コミットメッセージ内にタブが含まれてたらどうしようとか思って、まだLTSV化するログの中にコミットメッセージを入れることは試していない。