Rubyのobject_idからobjectを取得する
備忘録です
[1] pry(main)> hoge = "foo" => "foo" [2] pry(main)> hoge.object_id => 70163083352460 [3] pry(main)> ObjectSpace._id2ref(70163083352460) => "foo"
yeah!
Elixir ApplicationをGAEにデプロイ
GAEの説明を見る限り、メジャー言語しか対応してなさそうに見えたのですが、 Docker (Custom Runtimes) を選択すれば何でも動かせるそうです。
EBSもGAEもDockerさえ使えばどんなRuntimeでも使える => Elixirも動かせる!!!
ということでGAEにElixir製のbotをデプロイしてみました。
deploy
https://cloud.google.com/appengine/docs/flexible/custom-runtimes/quickstart を参考に。
Dockerfile
Dockerfileの設定はこんな感じです。
Elixir製Hubot風BotフレームワークのHedwigでSlack Botを作る - Memento memo. で作成したbotをデプロイしました。
FROM msaraiva/elixir-dev MAINTAINER shotat RUN mkdir /app COPY . /app/ WORKDIR /app RUN mix do deps.get, compile CMD ["mix", "run", "--no-halt"]
app.yaml
runtime: custom vm: true env_variables: ELIXIR_BOT_TOKEN: xxxxxxxxxxxxxx
token系については、実行時に環境変数で渡すのが良いみたいです。 ここに設定していいのかは若干謎ですが、Dockerfile内にべた書きするよりマシなので一旦これで。
deploy
事前にprojectの作成 & SDKのインストールの設定が済んでいれば、以下のコマンドを実行するだけでdeployできます。
$ gcloud app deploy
以上です。
Elixir製Hubot風BotフレームワークのHedwigでSlack Botを作る
Hubotに飽きたので、HedwigというElixir製のFWでbotを作ってみようと思い立ちました。
Hedwig
Adapter baseのHubotっぽいBotフレームワークです。Elixirです。
公式のAdapterでSlack対応してます。
Setup
mixでprojectを適当に作ります。supervisor (--sup
)つきで。
$ mix new hoge --sup $ cd hoge $ vi mix.exs # 以下の設定を記述 $ mix deps.get
mix.exs
ファイルの設定
... def applications do [applications: [:hedwig]] end ... defp deps do [{:hedwig, github: "hedwig-im/hedwig"}] end ...
Bot作成
以下のコマンドでインタラクティブにBotの設定ができます。AdapterとBot名を決めるだけです。
$ mix hedwig.gen.robot
lib/hoge.ex
内でsupervision treeにbotを登録します。
worker(Xxxx.Robot, [])
以上です。
Botの起動
mix run --no-halt
で起動できます。今回のbot名は Neko
にしてます。
❯ mix run --no-halt Compiling 2 files (.ex) Generated foobot app Hedwig Console - press Ctrl+C to exit. The console adapter is useful for quickly verifying how your bot will respond based on the current installed responders ### ここからコンソール shotat> Neko ping Neko> shotat: pong shotat> Neko help Neko> Neko help - Displays all of the help commands that Neko knows about. Neko help <query> - Displays all help commands that match <query>. Neko: ping - Responds with 'pong'
Responderの登録
ここからが本番です。pingとhelpだけできても意味がないので、諸々追加していきましょう。
以下のようなファイルを <app>/lib/responders/hello.ex
に作ります。
defmodule Foobot.Responders.Hello do # Foobotはアプリ名 @moduledoc false use Hedwig.Responder @greet [ "Hello", "ねむい", "にゃー" ] @usage """ hello """ hear ~r/hello/i, msg do send msg, random(@greet) end respond ~r/yo/i, msg do reply msg, random(@greet) end end
hear, respondでワードを拾って、send, replyで返事をします。それぞれメンションの有無で2パターンあります。9割くらいHubotと同じですね。
randomも最初から使えます。
あとは作ったresponderをconfigファイルに登録します。
config :foobot, Foobot.Robot, adapter: Hedwig.Adapters.Console, name: "Neko", aka: "cat", <= alias responders: [ {Hedwig.Responders.Help, []}, {Hedwig.Responders.Ping, []}, {Foobot.Responders.Hello, []} # <= new! ] ...
akaにbotの別名も登録できます。Neko a.k.a. cat。
もう一度動かす
こんな感じになります。
shotat> cat yo Neko> shotat: にゃー shotat> Hello Neko> Hello
Slackで動かす場合
Adapterを設定すればいけます。deps
mix.exs
に以下を設定
def application do [applications: [:hedwig_slack]] end def deps do [{:hedwig_slack, github: "hedwig-im/hedwig_slack"}] end
設定例
config :foobot, Foobot.Robot, adapter: Hedwig.Adapters.Slack, # <= adapterはSlack name: "shotat-machine", aka: "<@UXXXXXXX>", # <= debug logからuser id確認 token: "xxxxxxxxxxx", # <= tokenは適当に rooms: [], responders: [ {Hedwig.Responders.Help, []}, {Foobot.Responders.Hello, []}, {Hedwig.Responders.Ping, []} ]
これでslackで動きました。
注意点として、aka欄にuser idを設定しないとメンションに反応してくれません。 user idはdebugコンソールに出てくるので、それを設定しておきましょう(他に調べる方法もある気もしますが。。。)。
まとめ
Hubotに飽きたらHedwigに乗り換えましょう。楽しいElixir。
- 作者: Dave Thomas,笹田耕一,鳥井雪
- 出版社/メーカー: オーム社
- 発売日: 2016/08/19
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
Concurrent Rubyで並行処理プログラミング
Rubyで並行処理を書きたかったのですが、自前でスレッドセーフなプログラムを書ける気がしないのでgemを探して来ました。
Concurrent Ruby
Be an 'unopinionated' toolbox that provides useful utilities without debating which is better or why
と書いてあるので、諸々の並行処理の実装があるみたいです。スレッドセーフらしいです。 READMEを読むとActorやらChannelやら書いてあります。
とりあえず今回は一番basicっぽいAsyncを使って並行でHTTPリクエストを投げる処理を実装してみます。
Async
Async: A mixin module that provides simple asynchronous behavior to a class. Loosely based on Erlang's gen_server.
らしいです。
とりあえずDocumentを読みつつコードを書いてみました。
1秒のレイテンシがあるmock serverに5回リクエストを投げる処理です。
通常の直列処理では5秒かかってる処理が、 Async使った並行処理では1秒で終わっています。
実装ポイント
- Concurrent::Async をincludeする
- initializerメソッドで
super()
をコールする .async
をメソッドチェインに挟んで非同期処理をdispatchする.wait
で処理の終了を待つ(ブロッキングなメソッド).value
で結果を取り出す
まとめ
結構手軽に並行処理が書けて良さげです。
HTTPリクエストの並列化自体は Faraday + Typhoeus なんかでも簡単に書けるんですが、 Concurrent Rubyの方が汎用的ですね。
ActorとかChannelあたりはまだ触れてないので後日触ってみようと思います。
- 作者: Rubyサポーターズ,すがわらまさのり,寺田玄太郎,三村益隆,近藤宇智朗,橋立友宏,関口亮一
- 出版社/メーカー: 技術評論社
- 発売日: 2013/08/10
- メディア: 大型本
- この商品を含むブログ (22件) を見る
- 作者: Paolo Perrotta,角征典
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/10/10
- メディア: 大型本
- この商品を含むブログ (2件) を見る
NeovimでGolangを書く環境を整える
Dockerの勉強を始めたのでGolangもついでにやります。
- 作者: 松尾愛賀
- 出版社/メーカー: 翔泳社
- 発売日: 2016/05/11
- メディア: Kindle版
- この商品を含むブログを見る
GoのInstall & 環境設定
$ brew install go
GOPATHを設定しないといけないらしいので、 使ってるshellの設定に以下を記述します。
$ export GOPATH=$HOME/go $ export PATH=$PATH:$GOPATH/bin
開発に必須なバイナリを入れる
補完エンジンのgocodeとLinterのgolintを入れます。
$ go get -u github.com/nsf/gocode $ go get -u github.com/golang/lint/golint
Neovimの設定
plugin managerはdein.vimで
call dein#add('Shougo/deoplete.nvim') call dein#add('zchee/deoplete-go') call dein#add('benekastah/neomake') call dein#add('fatih/vim-go')
だいたいこんな感じでぬるぬる開発できるようになります。
npm installで依存関係エラーが出る場合の対処
eslint周りで色々installしていたら依存関係でエラーを吐いてどうにもならなくなりました。
結論としては、npmのversionを最新化したら直りました。
npm installが失敗した時に試したい3つのコマンド - Qiita にもありましたが、以下のコマンドで最新化できます。大抵の場合これでいける気がします。
$ npm update -g npm
ついでですが、以下のようにversion指定してあげることもできます。
$ npm install -g npm@3.10.3
Node.js周りは、nvm, node, npmそれぞれにversionがあってややこしいですね。
パーフェクトJavaScript (PERFECT SERIES 4)
- 作者: 井上誠一郎,土江拓郎,浜辺将太
- 出版社/メーカー: 技術評論社
- 発売日: 2011/09/23
- メディア: 大型本
- 購入: 24人 クリック: 588回
- この商品を含むブログ (12件) を見る
Gemfileとpackage.jsonでみるバージョン指定の読み方
セマンティック・バージョニング(SemVer)によると
バージョンナンバーは、メジャー.マイナー.パッチとし、バージョンを上げるには、
SemVerはバージョニングのルールみたいなものですね。
Gemfile(Ruby)やpackage.json(Node.js)等で依存関係を記述する時、 チルダ(~)やキャレット(^)を使って指定するかと思いますが、自分の中での解釈が曖昧だったのでまとめます。
Gemfile
Rubyの場合は ~>
の記法が使われます。
これはpessimistic operator(悲観的バージョン演算子)というそうです。
解釈は以下のようになります。
- 指定バージョンの一番右の数字を取り除く
- 次に、一番右の数字をインクリメントしたものを上限とする
# e.g. gem 'hoge', '~> 5.1.1' # 次と等価 gem 'hoge', '>= 5.1.1', '< 5.2.0'
参考: Ruby's Pessimistic Operator
package.json
package.jsonではチルダ(~)とキャレット(^)を使います。
参考: semver | npm Documentation
Tilde Ranges
Allows patch-level changes if a minor version is specified on the comparator. Allows minor-level changes if not.
とのことで
- 基本的にはマイナーバージョンまで固定
- マイナーバージョンが指定されてない場合はメジャーバージョン固定
です。
e.g. ~1.2.3 := >=1.2.3 <1.(2+1).0 := >=1.2.3 <1.3.0 ~1.2 := >=1.2.0 <1.(2+1).0 := >=1.2.0 <1.3.0 ~1 := >=1.0.0 <(1+1).0.0 := >=1.0.0 <2.0.0
Caret Ranges
Allows changes that do not modify the left-most non-zero digit in the [major, minor, patch] tuple. In other words, this allows patch and minor updates for versions 1.0.0 and above, patch updates for versions 0.X >=0.1.0, and no updates for versions 0.0.X.
- 基本的にはメジャーバージョン固定(メジャーバージョンが0でない場合)
- メジャーバージョンが0の場合マイナーバージョン固定
- メジャー・パッチバージョンが0の場合はアップデートしない
^1.2.3 := >=1.2.3 <2.0.0 ^0.2.3 := >=0.2.3 <0.3.0 ^0.0.3 := >=0.0.3 <0.0.4
大抵の場合はメジャーバージョン固定のCaret(^)指定で問題ないかと思います。
- 作者: 大川ぶくぶ
- 出版社/メーカー: 竹書房
- 発売日: 2015/12/07
- メディア: コミック
- この商品を含むブログ (7件) を見る
プログラマのためのDocker教科書を読み始めた
Dockerを使いこなせないと会社で人権がないので プログラマのためのDocker教科書を読み始めました。
プログラマのためのDocker教科書 インフラの基礎知識&コードによる環境構築の自動化
- 作者: WINGSプロジェクト阿佐志保
- 出版社/メーカー: 翔泳社
- 発売日: 2015/11/19
- メディア: Kindle版
- この商品を含むブログ (3件) を見る
プログラマのための、というタイトルから、 "Dockerの使い方だけ紹介" みたいな雰囲気があるんですが、 想定以上に諸々しっかり書いてありました。
序盤にインフラ・仮想化・コンテナ技術の歴史と概要についてしっかり書かれていて、 非常に参考になりました。定期的に読み直したい内容です。
以下、適当にDocker周りの備忘録を適当にまとめていきます。
Docker の Install(Mac)
Docker for Macがリリースされているのでこちらを使います。 (数ヶ月前にちょっと触った時はまだプライベートベータでした)
$ brew update && brew upgrade $ brew cask install docker
あとは適当にDocker.appでsetupします。
いろいろ試す
docker pull
超軽量Linux Distributionの"Alpine Linux"を使います。
とりあえず docker search
してみます。
$ docker search alpine NAME DESCRIPTION STARS OFFICIAL AUTOMATED alpine A minimal Docker image based on Alpine Lin... 1475 [OK] anapsix/alpine-java Oracle Java 8 (and 7) with GLIBC 2.23 over... 151 [OK] ...
docker pull
でイメージを落とします
$ docker pull alpine Using default tag: latest latest: Pulling from library/alpine c0cb142e4345: Pull complete Digest: sha256:ca7b185775966003d38ccbd9bba822fb570766e4bb69292ac23490f36f8a742e Status: Downloaded newer image for alpine:latest
Imageの確認
docker images
で一覧確認します。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE rails latest 9df3ff98cd15 9 days ago 840.6 MB nginx latest ba6bed934df2 2 weeks ago 181.4 MB alpine latest ee4603260daa 2 weeks ago 4.803 MB msaraiva/elixir-dev latest 6287638223f3 3 months ago 52.54 MB
いろいろ試しに入れてたので余計なものも出てきてますが、alpineのdocker imageだけ圧倒的に軽いですね。
個別に中身を見たい場合は inspect
を使います
$ docker inspect alpine ... "Architecture": "amd64", "Os": "linux", "Size": 4802964, "VirtualSize": 4802964, ...
hello world
基本型は
docker run <dockerイメージ名> <コマンド>
です。
$ docker run alpine /bin/echo 'hello world' hello world
dockerイメージがローカルに見つからなければ勝手にpullしてくれます。
tag
イメージにtagを付けて管理することができます。
例
$ docker tag alpine:latest shotat/alpine:foo $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE alpine latest ee4603260daa 2 weeks ago 4.803 MB shotat/alpine foo ee4603260daa 2 weeks ago 4.803 MB
コンテナのshellを起動する
単体でshellを起動したい場合は以下のようなコマンドを使います。
$ docker run -it --rm alpine /bin/sh
オプションについて
-it --rm
のオプションを見ていきます。
$ docker run --help | grep -E '(?:--tty|--interactive|--rm)' -i, --interactive Keep STDIN open even if not attached --rm Automatically remove the container when it exits -t, --tty Allocate a pseudo-TTY
-i
: 標準入力を開く-t
: 疑似ttyを割り当てる--rm
: exit後にコンテナを破棄する
-it
を付けないと対話shellをうまく扱えないので必ずつけましょう。
/bin/echo 'hoge'
みたいなことしかしない場合は不要です。
マスコットキャラクターの名前
Dockerのクジラのキャラクターの本名は "Moby Dock" というそうです。
白鯨 - Moby-Dick; or The White Whale - を文字ってるみたいですね。( 白鯨 - Wikipedia )
npm scriptsを並列実行する
npm-run-all を使う
使い方
npm i --save-dev npm-run-all
でinstallします。
直列・並列実行コマンドの run-s
, run-p
が使えるようになります。
package.jsonのscripts部を以下のように設定してみます。
"scripts": { "dev": "run-p stub watch", "stub": "stubcell", "build": "webpack", "watch": "run-p watch:*", "watch:js": "watch 'npm run build' ./src/scripts" },
この状態で npm run dev
とすると、stubサーバとjavascriptのwatch & buildが同時に走るようになります。
楽ちんですね。
Node.jsのversionをプロジェクト毎に設定する
Rubyの場合は .ruby-version
にバージョン指定すればプロジェクト毎にversion指定できるのですが、
Node.jsの場合どうすればいいのか分からなかったので備忘録。
大きく分けて2パターンありました。
avn を使う
.node-version
でversion指定すればディレクトリ移動したときに自動でversionが切り替わるみたいです。
nodeのversion指定するために別コマンドいれるの微妙な気がしたので今回は使ってません。
nvm useを使う
.nvmrc
にversionを記述して、nvm use
を実行します。
rbenvみたいに自動で切り替わらないのかな?と思ったのですが、以下のissueを見るに切り替わらないっぽいです。
zshのhook使って自動的にnvm use実行する、みたいなのも見ました。個人的にはavn使うよりこっちの方がスマートな気がします。
- 作者: 掌田津耶乃
- 出版社/メーカー: マイナビ
- 発売日: 2014/03/25
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る