読者です 読者をやめる 読者になる 読者になる

MySQL 徹底入門 第 3 版を読んだ

読書メモ 日記

『MySQL 徹底入門 第 3 版』を読みました。

MySQL徹底入門 第3版 ~5.5新機能対応~

MySQL徹底入門 第3版 ~5.5新機能対応~

  • 作者: 遠藤俊裕,坂井恵,館山聖司,鶴長鎮一,とみたまさひろ,班石悦夫,松信嘉範
  • 出版社/メーカー: 翔泳社
  • 発売日: 2011/08/26
  • メディア: 大型本
  • 購入: 9人 クリック: 82回
  • この商品を含むブログ (9件) を見る

なぜ読んだか

  • 特定の DB プロダクトについての知識がなかった
  • Web サービス開発の仕事に転職して、開発のために MySQL の操作をするようになったけど、知識が少ないので時間がかかる

こういうとき、幅広く薄く体系的にとっかかりとなる知識があると、頭のなかにインデックスができて調べやすくなるかなと考えました。入門系の本を何冊か Amazon で見て、よさそうなのを選んだ記憶があります。2011 年初版で「5.5 対応」と書いてあり、それほど新しい本ではないけれど、基本的な機能の学習には影響がそれほどないだろうと判断しました。

Vagrant で CentOS 7 の VM を立ち上げて MySQL をインストールし、それを触りながら読んでました。

感想

3 章でクライアント ( mysql ) を通じた操作の基本がだいたいわかり、4 章で周辺ツール( mysqladmin, mysqldump など)やユーザ管理、サーバ設定、ログなどについての基本がだいたいわかりました。このへんは求めていたことだったのでよかったです。

ストレージエンジンの説明やコマンドのオプションも載っていますが、わりとさらっとしてるので、このあたりは素直にマニュアルを読もうと思いました。

おわりに

MySQL の基本的な使いかたを体系的に把握することはできた本でした。あとは公式のリファレンスマニュアルを参照する生活を過ごしたいと思います。

Web 上のリソースとその表現

Web

RSpec で request spec を書くとき、get "/users/:id.json" と書くかわりに get "/users/:id" と書くとエラーになりました。

ActionController::UnknownFormat:
  UsersController#show is missing a template for this request format and variant.

リソース /users/:id に対して拡張子で指定しないならば、HTTP リクエストのヘッダに Accept: application/json をつけて、クライアントが利用したいデータ形式を指示する必要があります。

そもそもなぜこういうふうになっているのかを整理しました。

リソース

リソースとは Web 上に存在する情報そのものであり、URI (Uniform Resource Indicator) で指し示せます。たとえば次のようなリソースが考えられます。

  • 人のプロフィール
    • URI 例:http://example.com/users/john
  • ブログ記事
    • URI 例:http://example.com/entries/2017/01/01

わかりやすい URI でリソースを指定することで、どのような情報なのかが人間にとってわかりやすくなります。なお、ここでは、その情報がどのような見た目(表現)になっているかについては言及していません。

また、リソースに対して、HTTP のメソッド (GET, POST, PUT, PATCH, DELETE) を使うことで CRUD をはじめとする各種操作が実行できます。

リソースの「表現」

「表現」という言葉はリソースがどのような形式のデータになって、サーバ/クライアント間で通信されるかを指しています。表現には次のようなものがあります。

  • メディアタイプ
    • HTML, XML, JSON, JPEG, PDF など
  • 言語
    • 日本語、英語、中国語など
  • 文字エンコーディング
    • UTF-8, Shift_JIS など

リソースは複数の「表現」をとれる

あるリソースは次のように複数の「表現」をとりえます。

  • 人のプロフィールが HTML, JSON, PDF で表現できる
  • ブログ記事が日本語、英語で表現できる

リソース表現の指定方法

HTTP を介したサーバとのやりとりにおいて、リソースの表現をどう指定するかについては次のような方法があります。

  • クエリ文字列
    • GET http://example.com/users/john?format=json で人のプロフィールの JSON 表現を得られる
  • 拡張子
    • GET http://example.com/entries/2017/01/01.en でブログ記事の英語表現を得られる
  • コンテントネゴシエーション
    • GET http://example.com/users/john のリクエストヘッダに Accept: application/pdf を利用するとプロフィールの PDF 表現を得られる
    • ほかには Accept-LanguageAccept-Charset など

リソースと表現を分離する利点

リソースと表現の関係を疎にして、リソースが複数の表現をとれるようにすると、さまざまなクライアントが求める形式のデータを統一された HTTP のインタフェースで提供できるようになります。また、拡張性の面でも利点があります。

参考資料

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

Rails 5.0.1 で rails new するとできる Gemfile の git_source ブロックの意味

Rails

Rails 5.0.1 で rails new したときに作成される Gemfile の先頭に次のブロックが挿入されるようになっていました。

git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end

これの意味

Gemfile の中で :github オプションをつけた gem について、HTTPS 経由で GitHub から取得します。

git_sourceBundler で定義されているメソッド で、引数のオプション(ここでは :github)が付いた gem の取得先 URL をブロック内で指定できます。

やる理由

Bundler が持つ :github オプションは Git プロトコルで通信するのでセキュアでなく、さらに Bundler 1.13 以降は :github オプションを使っていると警告が出ます。公式ドキュメントでも :github オプションを使うのを避けるよう明記してあります。

このコードを入れておくと、HTTPS 経由で GitHub から gem を取得できるので警告が出ずにすみます。ちなみにデフォルトの Gemfile では web-console:github オプションを使っていますね。Bundler 2.0 ではこの点が対策されるようで、それまでの対処ということです。

入ったプルリクはこちらです。

github.com

参考資料

Yokohama.rb Monthly Meetup #76 に参加した

Ruby 日記

2017-01-14(土)の Yokohama.rb Monthly Meetup #76 に参加したので、メモを書きます。1 週間たってしまった。

yokohamarb.doorkeeper.jp

Ruby レシピブック

今回はレシピ 244 から 247 まで読みました。システム寄りの話題が中心です。

レシピ 244

スレッドファイバの扱いかたについてです。

スレッドを使うときに気をつけるべき点は次のようなところでしょう。

  • あるスレッドが別のスレッドの変数を操作しないように、Thread#fork の引数としてスレッド固有のローカル変数を渡す
  • メインスレッドが勝手に終了するのを防ぐため Thread#join でスレッドが終了するのを待つ

ファイバは軽量スレッドのようなものです。スレッドは自動で他スレッドに制御が移りますが、ファイバが持つコードを実行するには Fiber#resume を実行し、制御を呼び出し元に戻すには Fiber#yield を実行する必要があります。Enumerable#each など内部イテレータをジェネレータのような外部イテレータに変換するコードとともに紹介されていました。

ちなみに、Ruby 1.9 以降では組み込みの Enumerator をジェネレータとして使うことができます。

sentence =<<EOF
lorem ipsum
hoge fuga fizz bazz
EOF
enumerator = sentence.each_line  # Enumerator を返す
loop { p enumerator.next }
# => "lorem ipsum\n"
# => "hoge fuga fizz bazz\n"

また、レシピのサンプルコードで Object#__send__ というメソッドが使われていました。これは、send という名前が一般的で再定義されやすいことから定義された Object#send の別名ということです。

レシピ 245

プロセスのフォークについてです。

レシピ内では fork して exec するサンプルコードが紹介されていました。この用途なら Kernel.#spawn でもよいという話がありました。子プロセスの終了を待つなら Process.waitpid2 を使う必要があります。

pid = spawn('job')
exitpid, status = *Process.waitpid2(pid)  # 'job' が終了するまで待つ

レシピ 246

プロセスがシグナルを受けたときの動作を設定するシグナルハンドラについてです。

有名な SIGINT などの他に SIGUSR1, SIGUSR2 というはシグナルがあって、これはユーザ定義用のものだそうです(参照:シグナル (ソフトウェア) - Wikipedia)。

Pry など REPL 上で Singal.trap(:USR1) { puts 'USR1' } などとして、killSIGUSR1 を送ると、シグナルハンドラが動作していることが確かめられます。

レシピ 247

プロセスをデーモン化する方法についてです。

注意点として、デーモンの場合、必ず Kernel.#exit! で終了するようにします。exit!ensure 節など後処理も飛ばしてプロセスを終了します。これを使わないと stdio ライブラリのバッファが 2 回フラッシュされてしまうなどの問題が起きるそうです。

そもそもなぜデーモンなのか? nohup ではだめなのか?という話に展開して、次のページを皆で見ていました。

もくもく

後半はもくもく会でした。僕は swagger-docsSwagger UI を使って、Rails で作った API のドキュメント化を試していました。

懇親会

miyohide さん誕生日おめでとうございました。


次回は 2017-02-18(土)です。次のリンクから申し込めます。

yokohamarb.doorkeeper.jp

冪等な更新処理の API エンドポイントでは PUT を使うとよさそう

API

結論

  • star や like を付与するような、冪等性を持つアクションのための API エンドポイントでも POST はよく使われる
  • が、HTTP メソッドの意図を考慮すると、冪等な更新処理の API エンドポイントにアクセスするときの HTTP メソッドは、POST より PUT がよりよさそう

何をやったか

Twitter の like や GitHub の star を付与するようなアクションを、API エンドポイントとしてどのように表現すればよいのかというのを考えていました。

データを編集する操作なので POST, PUT, PATCH のいずれかで、さらに新規に like を表すリソースを作ると考えると、POST か PUT かなと思いました。この二つのどちらがよさそうか、既存 Web サービスの公開 API を見ながら調べてみました。

調査結果

POST

Twitter や Instagram の like は POST でした。

Twitter だと、リソース favorites/create を POST で作成するエンドポイントとなっています。

POST https://api.twitter.com/1.1/favorites/create.json

データを編集するための HTTP メソッドには POST はよく使われます。今回のような操作でも POST が使われている場合が多いようです。ただ、POST は送信したデータを指定 URI に従属させることを意図しています*1。たとえば

POST /v1/users

users の配下に新しくユーザのリソースを作成するようなパターンです。

なので、Twitter の API のように、直接リソース favorite/create を URI で指定するのは、POST の本来の意図とは若干異なってくるのかなと感じました。

PUT

GitHub API v3 の star は PUT でした。

リポジトリに対する star では、PUT で user が持つ starred/:owner/:repo というリソースを作成するエンドポイントとなっています。

PUT /user/starred/:owner/:repo

また、Gist に対する star では、PUT で star を作成するエンドポイントとなっています。

PUT /gists/:id/star

PUT を使う場合の要件として

  • 冪等性を担保すべき*2
  • URI でリソースを直接指定すべき*3

があります。

よって、次の理由

  • 一般に star や like は一度付与したら何度付与しても増えたりしない(冪等な処理である)
  • リソース (:repostar) を URI 内で直接に指定している

から、今回のようなエンドポイントでは POST よりも適しているのかなと思いました。

参考資料

Web API: The Good Parts

Web API: The Good Parts

次の Qiita 記事がかなり参考になりました。

qiita.com

*1:『Web API: The Good Parts』2.3.2 節参照

*2:http://stackoverflow.com/questions/630453/put-vs-post-in-rest

*3:『Web API: The Good Parts』2.3.3 節参照