コンテンツにスキップ

2014

LinuxにRuby on Railsをインストールする

Ruby on Railsを使ってみたいと思い、AWSにインストールした手順。

Ruby version 2.0.0 を RVMを使ってインストール

Linuxに最新のRubyをインストールするを参照

gemsetの作成

Rubyをインストールしたら、Railsのアプリケーションを実行するために必要な他のソフトウェア向けにシステムを構成する必要があります。通常、これはgemのインストールに関連します。gemとは自己完結型のRubyコードのパッケージです。バージョン番号の異なるgem同士がコンフリクトすることがあるため、一連のgemを自己完結的にまとめたgemsetというものを作成してバージョンを使い分けるのが便利です。 (引用: Ruby on Rails チュートリアル

以下のコマンドでgemsetを作成する。

$ rvm use 2.0.0@railstutorial_rails_4_0 --create --default

上のコマンドを実行すると、Ruby 2.0.0に関連付けられたrailstutorial_rails_4_0というgemsetを作成し (--create)、その場でgemsetを有効にし (use)、gemsetをデフォルトに設定 (--default) します。これにより、ターミナルウィンドウを開いたときに2.0.0@railstutorial_rails_4_0というRubyとgemsetの組み合わせが常に選択されるようになります。 (引用: Ruby on Rails チュートリアル

RubyGemsのインストール

AWSには始めからgemがインストールされていて、PATHは以下。

$ which gem
/usr/bin/gem

RVMでRubyをインストールするとPATHが上書きされる。

$ which gem
~/.rvm/rubies/ruby-2.0.0-p594/bin/gem

今回はチュートリアルに合わせてgemのバージョンを更新する

$ gem update --system 2.0.3

gemの設定ファイルである .gemrc に自動生成されるドキュメントである rirdoc の自動生成を抑制する設定をする

$ vim .gemrc
$ cat .gemrc
install: --no-rdoc --no-ri
update:  --no-rdoc --no-ri

Railsをインストールする

いよいよRailsをインストールする

$ gem install rails --version 4.0.5

インストール完了。 以下のコマンドで確認する

$ rails -v
Rails 4.0.5

Railsがインストールされたことを確認できた

参照

Ruby on Rails チュートリアル

Linuxに最新のRubyをインストールする

Ruby on Railsを使ってみたいと思い、調べてみるとRails4ではRubyのバージョンは1.9以降が必須のようである。

自分がさくらで借りているサーバーではRubyのバージョンが1.8.7だったのでこれを新しくしてみた。

RVMのインストール

新しいRubyをインストールする前にRVM(Ruby Version Manager)をインストールする。これはRubyをバージョンごとに管理するツール

$ curl -L https://get.rvm.io | bash -s

このコマンドで自分のホームディレクトリ以下に .rvm/ が作られ、ここにRVMがインストールされる。

そして .profile .bashrc .zshrc にPATHを通す記述が追加される。

また、 .bash_profile .zlogin にRVMをロードする記述が追加される。

RVMのインストールが完了したらロードする。ここではbashを使っているので以下のようにする。

$ source .bash_profile

Rubyのインストール

さくらのレンタルサーバーでの失敗

まずはRubyのインストールに必要なパーツを調べ、無ければインストールする。 以下のコマンドで必要なものをピックアップしインストールまで行ってくれる。

$ rvm requirements
/your/home/directry/.rvm/scripts/functions/support: line 314: rvm_debug: command not found
Checking requirements for freebsd.
Installing requirements for freebsd.
Updating system.
Installing required packages: automake, bison, readline, libyaml...
Error running 'requirements_freebsd_libs_install automake bison readline libyaml',

ここでErrorが発生。内容は必要なパッケージがインストールできなかったということ。 そこでFreeBSDのパッケージ管理コマンドである pkg コマンドを使ってインストールを試みる。

が、サーバーの設定的に自分でパッケージを追加することができなかったのでさくらのサーバーを断念してAWSに移行した。

AWSに移行

AWSに移行して $ rvm requirements までを実行する。(AWSは始めからRubyのバージョンが2.0.0だったが構わず実行) ここでも $ rvm requirements が転ける。

そこで今度はCentOSだったので yum を使ってインストールを試みる。以下のコマンドは $ rvm requirements が教えてくれる。Errorの原因が sudo で実行していなかったことなので sudo 付きで実行する。

sudo yum install -y patch libyaml-devel libffi-devel glibc-headers autoconf gcc-c++ glibc-devel patch readline-devel zlib-devel openssl-devel automake libtool bison

これで成功。

$ rvm requirements
Checking requirements for amazon.
Requirements installation successful.

$ rvm requirementsも成功。

このサーバーではすでにバージョン2.0.0のRubyがインストールされていたが、RVMの配下に新たにバージョン2.0.0のRubyをインストールする。

$ rvm install 2.0.0 --with-openssl-dir=$HOME/.rvm/usr

インストール完了。

参考

Ruby on Rails チュートリアル

MySQLにおけるNOT NULLカラムへのインサート時の挙動

MySQLでカラムにNOT NULLを指定した際、そのカラムに対するインサート操作による挙動が特殊なのでまとめる。

単列インサートと複数列インサートで挙動が変わる

NOT NULLを指定したカラムを含むテーブルへのインサートでは、一度に1行のみ挿入する単列インサートと、一度に複数行を挿入する複数列インサート(バルクインサート)で挙動が変わる。

MySQLマニュアルからの抜粋

Inserting NULL into a column that has been declared NOT NULL. For multiple-row INSERT statements or INSERT INTO ... SELECT statements, the column is set to the implicit default value for the column data type. This is 0 for numeric types, the empty string ('') for string types, and the “zero” value for date and time types. INSERT INTO ... SELECT statements are handled the same way as multiple-row inserts because the server does not examine the result set from the SELECT to see whether it returns a single row. (For a single-row INSERT, no warning occurs when NULL is inserted into a NOT NULL column. Instead, the statement fails with an error.)

単列インサートの場合はNOT NULLが指定されたカラムにNULL値が挿入されるとそのクエリはエラーとなって失敗するが、複数列インサートの場合は警告(warning)を発するものの、クエリは正常に受け付けられる。

その際、NULL値が指定された各カラムにはそれぞれのカラムのデータ型の暗黙的なデフォルト値が挿入される。(数値型なら0、文字列型なら空文字''、etc...)

検証

  • MySQLのバージョンは5.1.69
    • ただしマニュアルの該当箇所はバージョン5.7まで変更がないため、どのバージョンでも同じ挙動と思われる
  • テーブル定義は以下
CREATE TABLE `not_null_test` (
  `id` int(10) unsigned NOT NULL,
  `test_score` int(10) unsigned NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

単列インサート

mysql> insert into
not_null_test
(id, test_score, created_at)
values
(1, NULL, NULL);

ERROR 1048 (23000): Column 'test_score' cannot be null

複数列インサート

mysql> insert into
not_null_test
(id, test_score, created_at)
values
(1, NULL, NULL),
(2, NULL, NULL);

Query OK, 2 rows affected, 2 warnings (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 2 

mysql> select * from not_null_test;
+----+------------+---------------------+
| id | test_score | created_at          |
+----+------------+---------------------+
|  1 |          0 | 2014-10-18 13:35:10 |
|  2 |          0 | 2014-10-18 13:35:10 |
+----+------------+---------------------+
2 rows in set (0.00 sec)

※ timestampにテーブル定義で設定したデフォルト値'0000-00-00 00:00:00'ではなく、型のデフォルト値である現在時刻が入っている点に注意

RESTとはなにか

APIを実装することになり、今更ながらWebのアーキテクチャスタイルであるRESTとはなにか理解するためにまとめてみた。

Webのアーキテクチャスタイル

Webのアーキテクチャスタイルはクライアント/サーバーというスタイルを中心に、いくつかの制限(アーキテクチャ)を複合的に組み合わせたREST(Representational State Transfer)を理想としている

RESTはどのようなスタイルなのか

RESTは以下のスタイルを複合的に組み合わせたアーキテクチャである

  • クライアント/サーバー
  • ステートレスサーバー
  • キャッシュ
  • 統一インターフェース
  • 階層化システム
  • コードオンデマンド

クライアント/サーバー

WebではHTTPでクライアントとサーバーが通信する、クライアント/サーバーアーキテクチャを採用している。クライアントはサーバーにリクエストを送り、サーバーはそれに対してレスポンスを返す。

ユーザーインターフェースはクライアントに任せればよく、サーバーは処理に専念できるので様々なデバイス(PC・携帯電話・ゲーム機)に対応でき、サーバーの冗長化も容易である。

ステートレスサーバー

ステートフル/ステートレスという考え方があるが、サーバーがステートレスなやり取りを前提としていること。

ステートフル/ステートレスに関しては以下のエントリを参照

キャッシュ

一度取得したリソースをクライアント側である程度の期間保持して使い回すこと。

  • メリット
    • 同じリソースを取得するためにその都度クライアント/サーバー間で通信する必要がなくなる
    • これによりネットワークの帯域節約や処理の高速化を実現できる
  • デメリット
    • 適切に制御しないと意図せず古いリソースを参照してしまうことがある
    • 特に大規模なシステムではどこで何がキャッシュされているか正確に把握するのは容易ではない

統一インターフェース

リソースに対する操作を統一したインターフェースで行う。

HTTP/1.1ではリソースに対するメソッドが8つのみ定義されている。このようにインターフェースを限定することで様々なコンポーネントが生まれても統一された仕様としてリソースへの操作が行われ、それぞれの独立性が保たれることで多様性を受け入れることができる。

階層化システム

統一インターフェースを採用することにより、クライアント/サーバー間にプロキシなどのコンポーネントを設置してもクライアントはそのままリクエストを送ることができる。

これにより大規模システムではロードバランサーを導入したり、HTTPインターフェースを持たないコンポーネントに対してHTTPインターフェースをもつサーバーを返して処理をするなどの階層化が可能となる。

このようなアーキテクチャを階層化システムと呼ぶ。

コードオンデマンド

プログラムをサーバーからクライアントが受け取り、それをクライアント上で実行するアーキテクチャスタイル。JavaScriptやFlashがこれに該当する。

  • メリット
    • サーバーと都度通信することなくクライアント側のみで処理できることが増える
    • これによりユーザーのアクションに対する処理の速度が向上する
  • デメリット
    • クライアント/サーバー間でやり取りされるリソースが不明確になる
    • クライアント側の裁量が増える分、サーバーとやり取りされるリソースの内容が明確ではなくなる

RESTful

RESTの思想に忠実に設計されていることをRESTfulである、と言う。

RESTは上記の通り分散ネットワークを効率的に、可用性・冗長性高く利用するための理論であり、Webが理想とするアーキテクチャスタイルである。

この思想に則った設計がされることで多様なシステムの中にも仕様の統一感が生まれ、Webの世界が広がったと言える。

参考

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

ステートフル ステートレスとはどういうことか

コンポーネント間のやり取りにはステートフル/ステートレスという考え方がある。FTPではステートフルなやり取りが、HTTPではステートレスなやり取りが採用されいるが、それぞれの特徴についてまとめてみる。

セッション状態(アプリケーション状態)

システムにログインしてからログアウトするまでの一連の操作をセッションと呼ぶ。その一連の操作の中のそれぞれの状態をセッション状態と呼ぶ。

ステートフル

ステートフルなやり取りではサーバーはクライアントのセッション状態を保持している。

  • メリット
    • やり取りが完結に済む
    • それによりネットワークの帯域を節約できる
  • デメリット
    • クライアントの状態を都度把握しておかなければいけないのでクライアントが増えると負荷も増える
    • サーバーを複数台設置する場合にはそれぞれのサーバー間でクライアントの状態を同期しなければいけない
    • これらの理由によりスケールアウトには向かない

ステートレス

ステートレスなやり取りではサーバーはクライアントのセッション情報を保持しない。

  • メリット
    • クライアントのリクエストは状態に依存せず、常にリソースに対する操作に必要十分な情報となる
    • よってサーバーが増えてもそのままのリクエストでいつも同じリソースに対する操作ができる
    • このためスケールアウトに向いている
    • また処理がクライアントの状態に依らないので処理がシンプルになる
  • デメリット
    • やり取りが冗長になりがちである
    • またリソースへの操作が必要になる度にそのやり取りを繰り返す必要がある
    • これによりネットワークの帯域を消費し、処理も遅くなる
    • サーバーが状態を保持していないのでエラーが起きたときのハンドリングが複雑になりがちである

参考

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

reveal.jsを使ったプレゼンテーションの作成

YAPC::Asia 2014のLTに登壇させていただいた。その際、サクッとオシャレなプレゼンテーションを作ることができるということでreveal.jsを使って作ったのでメモ。

reveal.jsとは

htmlやmarkdown形式で簡単にリッチなプレゼンテーションを書くことができるjsやcssを中心としたライブラリ

reveal.jsの入手

GitHubのreveal.jsリポジトリからzipをダウンロードする。右下のDownload ZIPボタンを押すだけで完了。

プレゼンテーションの作成

基本的にindex.htmlを編集していく。特に以下の部分を編集していけば良い。

<div class="slides">
<!---...
ここを編集
...-->
</div>

デフォルトでは本家Demoの仕様となっている。

ページの追加

<section></section>タグを追加することで新しいページを追加することができる。新しいページは右側に追加されていく。

さらに<section></section>タグの中に<section></section>タグをネストすることで、縦方向にスライドを追加することができる。

スライドの動きの設定

<section>タグにdata-transitiondata-background-transitionを指定することでスライドの動きを設定できる。

デフォルトではスライドが回転するように動いていくが、例えば以下のように設定することで横方向にスライドが流れるようになる。

<section data-transition="linear" data-background-transition="slide">
  • data-transition
    • スライドに載っているコンテンツの動きを指定
  • data-background-transition
    • スライド自体の動きを指定

背景の設定

<section>タグにdata-backgroundを指定することでスライドの背景を設定できる。

<section data-background="#000000">  <!--背景色を指定-->
<section data-background="img.jpg">  <!--背景画像をパスで指定-->

コードブロックを設定

コードブロックを挿入するには<pre><code></code></pre>タグを挿入する。

<code>タグのclassに言語を指定することで適切なハイライトが適用される。

<section>
    <pre><code class="html">
        <body>
            <div class="example">
                test
            </div>
        </body>
    </code></pre>
</section>

スライド内コンテンツの動きの設定

スライドのページ内でいくつかの動きを設定したいときは

  • sectionタグのidにfragmentsを指定する。
  • ページ内のコンテンツのclassにfragmentを指定する。
<section id="fragments">
    <h2>example</h2>
    <ol>
        <li class="fragment">test1</li>
        <li class="fragment">test2</li>
        <li class="fragment">test3</li>
    </ol>
</section>

上記のように設定するとリストの要素が一つずつ出現する。

fragmentclassにはオプションを設定することができ、オプションによって動作をが変わる。

  • class="fragment current-visible": 要素が出現する(デフォルト)
  • class="fragment grow": 要素が大きくなる
  • class="fragment shrink": 要素が小さくなる
  • class="fragment roll-in": 要素が回転しながら出現
  • class="fragment fade-out": 要素が消える
  • class="fragment highlight-green": 要素が指定した色になる(red, blueなども指定可能)
  • class="fragment highlight-current-blue": 要素が指定した色で出現する(red, greenなども指定可能)

マークダウンでの記述

reveal.jsではプレゼンテーションをマークダウンで記述することもできる

  • sectionタグにdata-markdownを指定
  • <script type="text/template"></script>ブロック内に記述
<section data-markdown>
<script type="text/template">
    # ここにmarkdown形式で記述
    ```
    echo "you can also write code.";
    ````
</script>
</section>

コードブロック内でも</script>タグが出現するとマークダウンの終了と誤解されるので注意

参考

Amazon Linux AMIにagをインストールした手順

AWSでWebサーバーを借りた。このサーバーにagをインストールした際の手順。

agとは

ソースコードから特定のwordを検索する際に使うコマンドgrepがより賢く改良されたのがackコマンド。

このackをさらに改良し、検索を高速化させたのがagコマンド(正式名称:The Silver Searcher)である。

Amazon Linux AMIへのインストール

MacにはHomebrewを使ってbrew install the_silver_searcherとするだけで簡単に入れることができた。

AWSで借りたサーバーはAmazon Linux AMIという独自のイメージだったが、yumが使えるのでCentOSと同じ以下の手順で入れることができた。

ディレクトリの作成とソースのダウンロード

ソースをダウンロード、インストールするディレクトリを作成し、gitからagのソースを持ってくる

$ mkdir -p $HOME/local/source
$ cd $HOME/local/source
$ git clone https://github.com/ggreer/the_silver_searcher

ソースをmakeするための準備

対象のサーバーはまっさらな状態でコンパイラなどもなかったため、それぞれインストールする。

前述の通りAmazon Linux AMIではyumを使うことができる

$ sudo su -
yum -y groupinstall "Development Tools"
yum -y install pcre-devel xz-devel
exit

インストール

コンパイルしてインストールする

$ cd $HOME/local/source/the_silver_searcher
$ ./build.sh
$ sudo make install

パスを通す

$ cd
$ vim .bashrc
$ cat .bashrc
...
export PATH=$HOME/local/bin:$PATH
...
$ source .bashrc

これでagが使えるようになった

参考

AWSに複数のユーザーを設定した手順

AWSでサーバーを借りて複数人で共同開発することになった。 それに伴い、借りたサーバーに各々がアクセスできるようユーザーの設定をした際の手順メモ。

AWSでWEBサーバーを借りる

AWSのWebサーバーレンタルサービスはEC2と呼ばれる。 サーバーをレンタルするには様々あるサービス群からEC2を選択し、Launch Instance ボタンを押してInstanceの立ち上げを開始する。

  • AMI(Amazon Machine Image)の選択
    • 借りるマシンの種類を選ぶ。用途によって様々な種類がある(WordPressが既に設定されているものなど)
  • Instance Typeの選択
    • マシンのスペックを選ぶ。メモリやストレージのサイズなど
  • Instanceの詳細設定
  • Storageの設定
  • Instanceへのtag付け
  • Security Groupの選択
    • アクセスを許可するプロトコルやIPなどを指定してその設定をグループとして扱う

上記のほとんどの設定は後から変更できる。AMIの選択がしっかりできれば問題なさそう。

最後まで完了すると秘密鍵(hogehoge.pem)が発行される。これは絶対になくしてはいけない。

立ち上げたInstanceに複数ユーザーを設定する

立ち上げたInstanceにアクセスする。 今回はWebサーバーとして立ち上げるのでSecurity GroupにはHTTPとSSHでのアクセスを許可するよう設定しておく。

秘密鍵でアクセスする

まずはInstance立ち上げ時に発行された秘密鍵でアクセスする

[sojiro@local ~]$ chmod 600 hogehoge.pem  # 秘密鍵の権限を設定(厳しすぎても甘過ぎても使えない)
[sojiro@local ~]$ ssh -i hogehoge.pem ec2-user@xx.xx.xx.xxx  # ec2-userでログイン
  • ダウンロード直後の秘密鍵は権限が適切ではない可能性がある。その場合は600に設定する。
  • ssh-iオプションを使って秘密鍵を指定してログイン(秘密鍵を指定しないと~/.ssh/id_rsaが使われる)
    • 最初は初期設定されているec2-userというユーザーでログインする
    • コマンドはEC2のメニューバーからInstancesページに行き、Instanceを選択してページ上部のConnectボタンを押すと表示される

ユーザーの作成

Instanceにログインできたら早速ユーザーを作成していく

[ec2-user@ip-hogehoge ~]$ sudo su -  # rootユーザーになる
[root@ip-hogehoge ~] adduser sojiro  # ユーザー(sojiro)を作成
[root@ip-hogehoge ~] passwd sojiro   # sojiroにパスワードを設定
[root@ip-hogehoge ~] vim /etc/sudoers  # sojiroに権限を設定

ユーザーを作り、ユーザーに権限を付与する。今回は大雑把にrootと同じことができる権限を付与。

[root@ip-hogehoge ~] cat /etc/sudors
...
root    ALL=(ALL)       ALL
sojiro  ALL=(ALL)       ALL
...

公開鍵の登録

作成したユーザーにlocalからアクセスするための公開鍵を設定する。 (鍵のペアはlocalで予めssh-keygen -t rsaで作成しておく)

[root@ip-hogehoge ~] su sojiro
[sojiro@ip-hogehoge root]$ cd  # sojiroのホームディレクトリに移動
[sojiro@ip-hogehoge ~]$ mkdir .ssh
[sojiro@ip-hogehoge ~]$ vim .ssh/authorized_keys  # 公開鍵を置く(今回はlocalのid_rsa.pubをコピペした)
[sojiro@ip-hogehoge ~]$ chmod 700 .ssh
[sojiro@ip-hogehoge ~]$ chmod 600 .ssh/authorized_keys
  • 公開鍵を置くファイルの名前は.sshディレクトリ配下のauthorized_keysと決まっている
  • .sshディレクトリとauthorized_keysの権限にも気をつける

作成したユーザーでInstanceにログインできることを確認

[sojiro@local ~]$ ssh sojiro@xx.xx.xx.xxx  # ログインできればOK

localのrsa鍵でログインできることを確認できれば完了。

この操作で必要なユーザーを適宜作成する。

参考

新規に作成した鍵でEC2インスタンスにSSH接続する

OctopressにDISQUSのコメント欄を導入する

ブログにコメント欄を追加したい

本ブログにコメント欄を追加しようと思い立った。

DISQUSというコミュニケーションサービスが好評のようなので導入してみる。

  • DISQUSを使うための準備
  • OctopressでのDISQUS導入方法

DISQUSを使うための準備

DISQUSのアカウントを作成する

DISQUSのWebサイトからアカウントを作成。登録に必要なのはメールアドレスのみ。

自分のWebサイトをDISQUSに登録する

DISQUSのサイト登録ページから自分のサイトを登録する

登録が完了すると設定ページが表示されるので、ここで設定をしつつ、ページ中段に表示されているShortnameの文字列を確認する

OctopressでのDISQUS導入方法

configファイルへの記載

OctopressでのDISQUS導入はconfigファイルに先ほどDISQUSで取得したShortnameを記載するのみで完了する。

_config.ymldisqus_short_nameに自分のサイトのShortnameを指定する。

``` yml _config.yml

Disqus Comments

disqus_short_name: yoursitesshortname disqus_show_comment_count: false ```

これでブログの各ページの下部にDISQUSのコメント欄が表示されるようになる。

disqus_show_comment_count

disqus_show_comment_count はDISQUSコメント欄を導入するページのヘッダにコメント欄へのリンクを表示させるかどうかを指定する項目。

trueのとき

{% img /images/disqus/header_with_comment_link.png %}

falseのとき

{% img /images/disqus/header_without_comment_link.png %}

HUBOTを使ったirc-bot改修メモ #1 -noticeで発言させる-

こちらの記事でつくったirc-botの発言をnoticeにしたい。(botの発言内容に名前やALLなどの文字列が含まれると当人にmentionが飛んでしまうため)

HUBOT_IRC_SEND_NOTICE_MODE

環境変数 HUBOT_IRC_SEND_NOTICE_MODEtrue とすれば良い

実行ファイル(runhubot)に追記

#!/bin/bash

export HUBOT_IRC_NICK="bot_kun"
export HUBOT_IRC_ROOMS="#target_channel"
export HUBOT_IRC_SERVER="irc.hogehoge.local"
export HUBOT_IRC_SEND_NOTICE_MODE=true
#export HUBOT_IRC_PASSWORD="hoge"

bin/hubot -a irc --name myhubot

この実行ファイルからirc-botを起動すると当該irc-botの発言はすべてnoticeとなる。

処理の実体

HUBOT_IRC_SEND_NOTICE_MODEフラグが立っている場合は bot オブジェクトから notice メソッドが呼ばれる。

notice メソッドが呼ばれている bot オブジェクトの実体は new Irc.Client である。

参考: http://node-irc.readthedocs.org/en/latest/API.html