Blogaomu

WEBアプリケーション開発とその周辺のメモをゆるふわに書いていきます。

buffbuff をgem化するにあたってのメモ

概要

buffbuff をgem化しました。

github.com

当初は clone してそのまま利用するという作りにしていたのですが、gem としてインストール(from GitHub)できるように修正を行いました。この作業でハマった点や気付いた点などを書き残しておきます。

メモ

Kanazawa.rb meetup #76 に参加しました #kzrb

DMM.com 金沢南町営業所のイベントスペースをお借りして開催でした。広くて画面がでかくてよいですね。

f:id:TAKAyuki_atkwsk:20181215133410j:plain

kzrb.doorkeeper.jp

今回は年末恒例のLT大会回でした!参加者全員発表だよ、わいわい!

話したこと

少し前から作っていた Buffer への投稿ツールの話をしました。

github.com

LTではツールを作るモチベーションのところと実際のコマンドについて話しました。当初話の内容を考えているときは、どういうライブラリを使っていてとか作っていてこう思ったとかということも含めようとしていたのですが、練習で喋ってみると優に5分をオーバーしたので泣く泣く削ることにしました。なので、技術的な話というよりも問題をどう解決するのがいいかなっていうところを話の中心に据えたイメージです。

ということで、削ってしまった部分の作って思ったところをいくつか紹介します。

ツールを作った感想

  • bundle gem コマンドで gem のひな形を作ってくれるので、最初からこれを利用すれば良かった
    • 久しぶりにRubyでプロジェクト作ったのですっかり忘れていた...
    • require でlib以下のソースコードを参照するのに上手くいかない箇所があった
    • 自力では解決できなさそうなので、他のgemを参考にしようとした
    • いろいろ調べていたら以下の記事が参考になった
    • https://tech.crevo.jp/entry/2018/10/02/150430
  • VSCodeで開発してみた
    • 今まではVimだったけど
    • オススメプラグインあれば教えてください><
  • Thor ライブラリ便利だった
    • ANSIカラー表示とかYes/Noインタラクションを簡単に実装できる
    • シェルスクリプトで実装しようとするとまあまあだるいのでありがたい
  • Arrayタイプのオプション指定方法が好みじゃない
    • オプション値の切れ目が分かりづらい
    • command <Arrayタイプのオプション> <引数> という方法でコマンド実行すると引数もオプションの値としてパースされる
    • docker run--env みたいなのが好み
      • ex.) docker run --env VAR1=value1 --env VAR2=value2 ubuntu bash

今後はgemとしてインストールできるようにする(おそらくテンプレートディレクトリが上手く読めなくなるはず)というところが直近の修正ポイントになります。 @kiyohara さんも早速使いたいと言ってくれたので良かったです!

懇親会

ピザを食べつつ技術や組織、就職、転職、スプラトゥーン(自分はついていけなかったけど)などの話をしてました。ピザの量、調整するの難しいですね!注文時はテンションが上がってどうしても多めに頼んでしまうw

f:id:TAKAyuki_atkwsk:20181215171227j:plain

今年も Kanazawa.rb お疲れさまでした。また来年もゆるゆるやっていきましょう。

Kanazawa.rb meetup #75 に参加しました #kzrb

今回はDMM.com 金沢事業所をお借りして開催!

kzrb.doorkeeper.jp

当初は自分含めて2人しか参加表明してなくて不安でしたが最終的には11人の参加になりました。わいわい。

Scala関西Summit 2018に行ってきた話

www.blogaomu.com

↑の話をベースに写真も追加したスライドを作って発表しました。コンセプトとしてはScala関西Summitに行った気になれる、だったんですが、いろいろ詰め込みすぎてだいぶ時間を取ってしまいました(すいません)。Scalaは可愛いを広めることができてよかったです。

Bufferを操作する

Kanazawa.rb告知用のSNS投稿をBufferで行っているとのことで、これをCLIでやれたらいろいろ捗るのでは?という考えから今回のもくもくタイムではBuffer APIを触ってみました。

APIを触る前にBuffer自体を使ったことが無かったのでアカウントを作っていろいろ試して概念を理解するところから始めました。

  • 1アカウントに対して複数のSNSアカウントをひもづけられる。ひもづいたSNSアカウントのことをProfileと呼んでいる
  • 投稿はQueueというものに格納され、特定の時刻になったらSNSアカウントを通して接続先のSNSに投稿される
    • 投稿時にQueueに入れる(Add to Queue)、即時にSNS投稿する(Share now)、任意の日時に投稿する(Schedule post)、の3つから選択できる
    • Queueに入った投稿は1件ずつ時刻(Posting times)が割り振られ、その時刻になると接続先のSNSに投稿される

投稿に関する概念はざっとこんな感じだと思います。詳しくはこの辺を見ると良さそう。 Managing your Queue - Buffer FAQ

概念を理解したところで、プログラムからBuffer APIを呼ぶ場合には公式のgemがあるのでこれを利用すると良さげです。

github.com

Buffer APIを利用する場合、先にアプリケーションの登録をサイト上で行う必要があります。画面に従って入力していけばOKです。ここで発行されたAccess tokenを使用します。

buffer.com

先ほど発行されたAccess tokenを環境変数 BUFFER_ACCESS_TOKEN に入れておいて、replでいろいろ操作してみます。

> require 'buffer'
> client = Buffer::Client.new(ENV['BUFFER_ACCESS_TOKEN'])
# Profileの取得
> profiles = client.profiles
=> [{"_id"=>"5bef956a4b1be7784607d225",
  "avatar"=>
   "http://pbs.twimg.com/profile_images/835761987728502784/QMKQ3UYI_normal.jpg",
  "avatar_https"=>
   "https://pbs.twimg.com/profile_images/835761987728502784/QMKQ3UYI_normal.jpg",
  "can_see_content_library"=>false,
  "counts"=>
   {"sent"=>4, "drafts"=>0, "daily_suggestions"=>25, "reminders"=>0, "pending"=>0},
  "cover_photo"=>
   "https://d3ijcis4e2ziok.cloudfront.net/default-cover-photos/blurry-blue-background-iii_facebook_timeline_cover.jpg",
  "created_at"=>1542428010,
  "default"=>true,
  "disabled"=>false,
  "disabled_features"=>[],
  "disconnected"=>false,
  "formatted_service"=>"Twitter",
  "formatted_username"=>"@TAKAyuki_atkwsk",
  "id"=>"5bef956a4b1be7784607d225",
  "is_analyze_enabled"=>false,
  "is_on_business_v2"=>false,
  "locked"=>false,
  "paused"=>false,
  "paused_schedules"=>[],
  "preferences"=>{},
  "reports_logo"=>nil,
  "schedules"=>
   [{"days"=>["sun"], "times"=>["09:55", "14:25", "16:44", "19:32"]},
    {"days"=>["mon"], "times"=>["09:55", "14:25", "16:44", "19:32"]},
    {"days"=>["tue"], "times"=>["09:55", "14:25", "16:44", "19:32"]},
    {"days"=>["wed"], "times"=>["09:55", "14:25", "16:44", "19:32"]},
    {"days"=>["thu"], "times"=>["09:55", "14:25", "16:44", "19:32"]},
    {"days"=>["fri"], "times"=>["09:55", "14:25", "16:44", "19:32"]},
    {"days"=>["sat"], "times"=>["09:55", "14:25", "16:44", "19:32"]}],
  "service"=>"twitter",
  "service_id"=>"77184067",
  "service_type"=>"profile",
  "service_username"=>"TAKAyuki_atkwsk",
  "shortener"=>{"domain"=>"buff.ly"},
  "statistics"=>{"followers"=>785},
  "timezone"=>"Asia/Tokyo",
  "timezone_city"=>"Tokyo - Asia",
  "user_id"=>"5bef953a4b1be777074c2b05",
  "utm_tracking"=>"disabled",
  "verb"=>"tweet"},
  ...]

# 投稿をQueueに入れる
> client.create_update(
*   body: {
*     text: 'お腹吹田',
*     profile_ids: [profiles.find {|profile| profile.service == "twitter" }.id],
*   }
* )
=> {"updates"=>
  [{"_id"=>"5befaff6dd5072291b2a9b93",
    "client_id"=>"5befa27c4b1be72ec04037b3",
    "created_at"=>1542434806,
    "day"=>"Today",
    "due_at"=>1542450720,
    "due_time"=>"7:32 pm",
    "id"=>"5befaff6dd5072291b2a9b93",
    "is_video_processing"=>false,
    "library_update_id"=>"",
    "needs_approval"=>false,
    "organization_id"=>"5bef953a4b1be777074c2b07",
    "perm_approvable"=>false,
    "perm_editable"=>true,
    "pinned"=>false,
    "profile_id"=>"5bef956a4b1be7784607d225",
    "profile_service"=>"twitter",
    "shared_now"=>false,
    "status"=>"buffer",
    "text"=>"お腹吹田",
    "text_formatted"=>"お腹吹田",
    "text_md5"=>"e01909236cf97670e3f23a95e52c7072",
    "type"=>"text",
    "updated_at"=>1542434806,
    "user_id"=>"5bef953a4b1be777074c2b05",
    "via"=>"api"}],
 "buffer_percentage"=>20,
 "buffer_count"=>2,
 "success"=>true,
 "message"=>"One more tweet in your Buffer. Keep it topped up!",
 "code"=>false}

# 複数のProfileで投稿する
> client.create_update(body: {text: "こんにちは", profile_ids: profiles.map(&:id)})
=> (略)

# 特定の日時に投稿されるようにする
> client.create_update(body: {text: 'hogehoge', profile_ids: [profiles.find {|profile| profile.service == "twitter" }.send(:id)], scheduled_at: "20181117T19:00:00+09:00"})
=> (略)

ひとまず複数の投稿形式を試して思った通りに動作しました。 profile_ids を取ってくるところで少しハマりましたが、後はAPIパラメーターを調べつついけました。このあとはCLIとして操作できれば良いなと考えているのでthorと組み合わせて実装してみようと思っています。

懇親会

www.hotpepper.jp

www.hotpepper.jp

一次会は手羽先食べ放題コース!過去にいくつかの食べ放題に勝ってきたkzrb勢も手羽先には勝てなかった...。

二次会は安定の丸二。唐揚げがでかいぜ!

懇親会で、作業部屋のCO2濃度を計測して可視化およびアラートを出す仕組みを作りたいと相談したところ、まともな濃度センサーはお高いらしく中国から輸入するのが良さそう?とのことでした。また、Withingsの体重計でCO2濃度も測れるやつがあるらしく、可視化ならこれでもいいのではという話も。

次回のKanazawa.rbは年末恒例のLT大会です!

Scala関西Summit 2018に参加しました #scala_ks

大阪にて行われたScala関西Summit 2018の1日目に参加してきました。私自身にとっては初の参加で、Scalaの集まりとしても久しぶりに顔を出しました。

2018.scala-kansai.org

プラチナスポンサーがZOZOテクノロジーズだったので一番大きなホールの名称がZOZOホールになっていました。

私が聞いたトークセッションについて軽くメモ

http4sとcats-effectで可愛らしい、関数型らしいアプリケーションを書こう!٩(๑^o^๑)۶

https://speakerdeck.com/dysangelist/tagless-final

  • 発表者のダーシャは仕事でお世話になってるのと「可愛らしい」ってどういうこと?というのが気になって聞くことにした
  • Scalaの特徴を可愛さに例えているのが良いポイントでした
    • 簡潔さ、高レベルでの抽象化、論理的、型システムで安心などなど
  • Tagless Finalという手法?の紹介
    • うまく理解できなかったけど、実装を良い感じに分離できるとかそういう良さがあるのだろうか?

アニメーションで理解するAkka StreamsとAkka HTTP

https://youtu.be/NBKpr7bL22M

  • これまでAkka Streamsを触る機会があってドキュメントを読んだりもしたけどふわっとした理解だったので聞くことにした
  • アニメーションで概念が理解しやすかった
    • 爆発シーンが最高
  • Akka HTTPがAkka Streamsで構成されてるのは興味深かった

Format things with scalafmt

https://speakerdeck.com/tanishiking/format-things-with-scalafmt

  • 共感を覚えた意見
    • 人によって暗黙的にしたがっているスタイルが存在しているので、人が増えるとカオスになる
    • 瑣末な議論を減らして、本質的なものの議論に重きを置きたい
  • ScalafmtはScalametaというものでScalaを解析しているそう(コンパイラとは別の実装)、すごい
  • 既存のコードベースからdiffの少ない設定を生成するやつ

Scala-erにも影響ありそうなJavaの現状まとめ

https://www.slideshare.net/linecorp/summary-of-the-state-of-java-that-will-affect-scalaers

  • JavaはOpenJDKとしてオープンソースコミュニティで開発
  • Javaのビルドはいろいろなプロバイダーが提供している(Oracle, AdoptOpenJDK, クラウドベンダー等)
  • リリースサイクルが変わったことは知っていたけども、サポートポリシーや各種ビルドについて知らないことばかりだった

Akkaを分散トレーシングで見てみよう

http://nbviewer.jupyter.org/format/slides/github/grimrose/scala-kansai-summit-2018/blob/master/slide.ipynb#/

  • Scalaに限らずマイクロサービスにも通ずる話題だったし、分散トレーシングという概念は今後ものにしておきたいトピックだった
  • Kamonを使っているけどもJVMメトリクスの取得に使っていたので、トレーシングの方も調査したい
  • OpenTracingという統一した仕様を策定している(CNCFプロジェクト)
    • 実装はそれぞれのライブラリで異なる
  • Jaegerのロゴが可愛い(gopherっぽい)
  • 途中で発表者のドリンクタイムを入れていたのが良かった(Pyconの発表であったのを取り入れたらしい)
    • 聞く側も一段落できて良い

DatabricksとSparkではじめる [データ分析/機械学習] 実践入門

https://speakerdeck.com/smdmts/databrick-and-spark-with-data-analyze-and-ml-for-newbie

  • Databricks便利っぽい
    • AWS上に実行基盤を構築可能で、Web UIもある
    • Web UI上のNotebookで開発できる
  • ここからはScalaの世界観で、ここからはPythonの世界観という風な言い回しが特徴的だった
  • Sparkが基盤になっているとScalaを使う場面も出てくるのか、なるほどと思った

Json codec を楽しもう、現場で役立つ circe

http://labs.septeni.co.jp/entry/2018/09/18/090727

  • 「キルケ」派が多い?(「サース」って呼んでた)
  • library versionの書き方面白かった .map(_ % version) 的な
  • 私も使っていますが今のところJsonライブラリとしては最も使い勝手が良い感じ
    • Encoder/Decoderの自動導出(サポートされている型の多さ、case classにも対応)
  • forProductN知らなかった

実践GraphQL on Scala

https://speakerdeck.com/petitviolet/real-world-graphql-on-scala

  • 思い切ってGraphQLを導入(フロントエンドはElmだそうです)
  • 型システムを持っているものとScalaは相性がよいと再認識
  • 参照系と更新系でアプリケーション内の層を分けているのは興味深かった

良かった点

  • 写真公開NGの人を明示的に区別できていた(名札の色で判断できる仕組み)
  • 写真撮影用スタッフがいた
  • フリーコーヒー
  • 快適なwifi
  • 椅子のみではなく机がある
  • 学生スタッフが結構いた
  • アンカンファレンスのScala酒場(参加できなかったけけど、ツイッターで流れてきた画像を見て良さそうと思った)

懇親会

懇親会は会場変わって、大阪駅から直ぐのさくらインターネット。オープンスペースにはバーカウンターがあってオシャレ空間だった。お料理も美味しかったです!

発表者に質問してみようかなとか思ってたんですが、話に割って入るのが個人的にはハードル高いので聞けずじまいに終わってしまいました。でも初めましての方とも話すことができて良かったです。金沢から来ましたーと言うとかなりの確率でびっくりされましたw (関西勢と東京勢が多かった)

その他の様子

スタッフの皆様、参加者の皆様、楽しい空間をありがとうございました!はるばる金沢から参加して良かったです!

あと、早朝のサンダーバード乗るのしんどかったので来年は前乗りしようかなと思いますw

Kanazawa.rb meetup #74 に参加しました #kzrb

kzrb.doorkeeper.jp

今回は和室での開催。入り口からして開発合宿感が漂っていました(合宿ではない)。金沢勤労者プラザというところが会場だったのですがインターネットが無いのだけ除けば満足できる施設でしたよ!

ブログ記事を書いた

前日に参加していたJAWS-UG金沢もくもく会の記事を書きました。とりあえず進捗出せた。

www.blogaomu.com

プログラミングElixir 20章

「マクロとコードの評価」というテーマの章でした。

  • 関数が使えるなら、マクロは使ってはならない、という教訓
  • defmacro quote unquote
  • あるモジュールでマクロを定義して、使う側ではそのモジュールを requrie する
  • マクロに渡されたパラメータは評価されない
  • quote に渡されたもの(ブロック)は評価されずに内部表現を返してくれる
  • unquoteしたコードは quote ブロックが実行されてコードが生成されたときに実行される
  • unquote_splicing はリストを展開してくれる
Code.eval_quoted(quote do: [1, 2, unquote([3, 4])])
#=> {[1, 2, [3, 4]], []}
Code.eval_quoted(quote do: [1, 2, unquote_splicing([3, 4])])
#=> {[1, 2, 3, 4], []}

if をマクロで実装してみようという例でしたが、まだしっくり理解できず。練習問題もやりながら理解していきたいですね。。

プログラミングElixir

プログラミングElixir

懇親会

居酒屋 さかなや道場 金沢駅店
〒920-0031 石川県金沢市広岡1-9-25 アクロスキューブ金沢駅西口2F
3,000円(平均)850円(ランチ平均)
r.gnavi.co.jp

retty.me

2件目は安くて程よく雑な雰囲気で穴場開拓した感がありましたね。「本日の男汁」というメニューがあったのが印象的でした。

JAWS-UG金沢 #35 に参加しました(Terraform独習メモ4日目) #jawsug

jawsug-kanazawa.doorkeeper.jp

今回はもくもく会で6人参加でした。私はTerraform独習の続きを、その傍ら次回の発表ネタ出しなどをみんなで行いました。

www.blogaomu.com

2018-10-19

  • 今回はALBを作ってみようと思う
  • 久しぶりなのでいろいろ忘れている
    • terraform version したらprovider.awsのバージョンも出てきたので、そもそもどうやってインストールしたんだっけ?となった
$ terraform version
Terraform v0.11.8
+ provider.aws v1.6.0
resource "aws_lb" "memo_lb" {
  name               = "memo-lb"
  internal           = false
  load_balancer_type = "application"
  subnets            = ["${aws_subnet.public-a.id}", "${aws_subnet.public-b.id}"]

  enable_deletion_protection = true
}
  • ALB用のセキュリティグループを作る
  • 現状一つのtfファイルで管理しているのでごちゃっとしてきた
    • まとまり毎にファイル分割したいなあ
  • 〆のグラフ
    • terraform graph > graph/$(git rev-list --max-count 1 HEAD).dot && dot -T png graph/$(git rev-list --max-count 1 HEAD).dot -o graph/$(git rev-list --max-count 1 HEAD).png
    • 中央付近にlbが増えている f:id:TAKAyuki_atkwsk:20181020135808p:plain

その他

@_kentaro_m さんのLT練習(AWS運用周りの話)をみんなで聞いていて、サービスや組織の規模によってこういう構成をとるのかーと新たな発見があって面白かった。小規模ならそれに適した構成も取れるし、なんだかんだ言うてAWSサービス全体としても柔軟なんだなあと思いました。

懇親会

【閉店】がブリチキン。 金沢武蔵店 - 北鉄金沢/居酒屋 [食べログ]

3人でDB設計やらコンテナやらの話をしていました。コンテナを使ったアプリケーション運用の話を聞きたいということだったので、そのうち喋ることになりそうです。唐揚げ美味しかった。

次回

2018-11-23(金・祝)にOpsJAWSとの共同イベントを行います(私は参加できない)。みんな悩みがちな運用周りの話がいろいろ出てくるようなのでぜひご参加くださいませ〜〜。

jawsug-kanazawa.doorkeeper.jp

Kanazawa.rb meetup #73 に参加しました #kzrb

kzrb.doorkeeper.jp

7年目に突入して最初のもくもく会です。今回はいつものElixir本ではなく、違うことをしていました。

告知用文言生成のスクリプト

Kanazawa.rb では meetup を開催するときに予め各種 SNS で告知を行うのですが、毎回手で文言を作成するという話をメンバーから聞いたので、ある程度自動的にできればいいなあと思いスクリプト化の検討を行いました。文言の構成は毎回同じようなのでテンプレートを作成して変数を流し込むという処理で良い感じにできそうです。rbの名が付いているので erb 使う?と思ったのですが、そこまで複雑なことは行わないので logic-less と謳っている mustache を使ってプロトタイプを作ることにしました。一通りのプログラミング言語に対応しています。まずは手っ取り早くシェルでお試し。

github.com

macOSなら以下のようにインストール可能です。

curl -sSL https://git.io/get-mo -o mo
chmod +x mo
mv mo /usr/local/bin/

以下のようなテンプレートを用意して

Kanazawa.rb meetup {{SERIES_NO}} を{{DATE}}に開催します。内容は「{{TITLE}}」。{{DESCRIPTION}}場所は{{PLACE}}。詳細はこちら。

https://kzrb.org/meetup/{{SERIES_NO}}/

#kzrb

環境変数を渡して実行すると以下のように出力されました。

$ SERIES_NO=73 DATE=2018-09-15 TITLE=意識高いもくもく会 DESCRIPTION=各自で目標を設定する自主勉強会です。 PLACE="ITビジネスプラザ武蔵 研修室2" mo template.txt

Kanazawa.rb meetup 73 を2018-09-15に開催します。内容は「意識高いもくもく会」。各自で目標を設定する自主勉強会です。場所はITビジネスプラザ武蔵 研修室2。詳細はこちら。

https://kzrb.org/meetup/73/

#kzrb

まあ、なんか良さそう。今後は実用化に向けて、GitHub Issueと絡めて上手くmeetup準備フローに組み込めないかなと考えております。以下当日書いていたメモ。

LTした

以下の内容で話しました。今回は Dropbox Paper でばーっと書いてプレゼンテーションモードで見せる、という発表方法にしたのですがブログに載せるときにはスライドとして作るという作業が必要そうですね...


batコマンドのご紹介

https://github.com/sharkdp/bat

A cat(1) clone with wings.


  • catコマンドのクローン
    • バッチファイルの類いではない
    • Rustで実装されている
  • チームメイトから教えてもらって良さげだと思ったので紹介
    • brew install bat

  • bat README.md


  • catにない特徴
    • シンタックスハイライト
    • gitとの連携(差分表示)
    • ページング
    • デフォルトで行番号表示(catには行番号表示オプションあり)

  • ヘルプがカラー対応、ナウい
    • bat --help

  • シンタックスハイライトは多くの言語、ファイルタイプに対応
    • bat --list-languages

  • テーマを変えることができる
    • bat --list-themes

  • プレーンな表示だと見づらいファイルを見ながら作業したいとき
    • 例えばREADME, JSON, yaml, Dockerfile
    • 今まではvimを開いて見ていた
    • batで十分な場面がほとんどなので役立ちそう

懇親会

www.hotpepper.jp

retty.me

5人でこじんまりとわいわい飲みました。今回初めて参加した方は、東京の会社に属して金沢でリモートワークしているとのこと。リモートワーク事例じわじわ増えてきてますね。二次会ではガリ酎飲んでガリ〆鯖を食べるというガリ三昧を体験してきました。