ruby + rails の最小構成

今回の最小構成は「ruby + rails」です。
rubyと言えば日本で開発されたPG言語としては初めて国際電気標準会議で国際規格に認証されたスクリプト言語です。
railsはrubyのフレームワークとしてはdefacto standardとしての地位を確立しているフレームワークで多くの機能が標準的に搭載されている、便利なフレームワークです。

# 構築ルール
これまで複数言語で最小構成の記事を書いてきたのですが、その記事を元に社内でハンズオンを行っておりました。
そこで「homebrewを使うと環境によってエラーが発生するので使わないで記事を書いてほしい」という要望があがってきたため今回は、homebrewを使用せず出来る限りどんな環境でも、環境構築するモジュールに依存したエラーが発生しないような環境構築記事を書いて行きたいと思います。

# 環境とIDE
* mac osx 10.9.5
* mysql 5.6.31
* Aptana studio 3 

# rbenvとruby-buildをインストール
rbenvとはrubyの各バージョン環境を一つのPCで構築する事が出来る便利なツールです。
今回は、ruby-buildを使って任意の環境を作って行きたいと思います。

rbenvのお作法は本来bandlerを利用して環境を汚さないようにする方法が一般的なようですが、その辺りの事が知りたい場合は下記のurlの記事を参照してみて下さい。今回なぜruby-buildを使って環境構築しようと思ったかについても書いてあります。
http://qiita.com/yu-sa/items/182b6ca89e9351468656

``` rbenvをcloneしてmake.
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$ cd ~/.rbenv && src/configure && make -C src
```

ruby-buildは`rbenv install`を行う際に呼び出されているモジュールです。
ruby-build自体独立したコマンドとして実行可能なモジュールです。

``` ruby-buildをcloneしてinstall.
$ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
$ cd ~/.rbenv/plugins/ruby-build
$ ./install.sh
```

# 各種path登録
rbenvコマンドを実行出来るようにpath登録しておきます。
bashに登録するのが嫌な方はexport部分のコマンドだけ実行する事で今回対応しているターミナル内だけの影響範囲で使用出来ます。

``` path登録.
# rbenvをpathに登録
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile

# ruby-buildをpathに登録
$ echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bash_profile 

# rbenvで選択しているruby環境をpath登録
$ echo 'export PATH="$HOME/.rbenv/shims:$PATH"' >> ~/.bash_profile  

$ source ~/.bash_profile
```

# rbenv と ruby-buildで各バージョン環境を構築
下記の方法が一般的なrbenvでの環境作成方法です。
rbenvコマンドを使用して環境を構築します。

``` rbenvに各バージョン環境構築.
$ rbenv install 2.2.5
$ rbenv install 2.3.1 
```

下記の方法はruby-buildを利用したrbenv環境構築方法です。
`ruby-build [installしたいrubyバージョン] [環境を配置したいpath]`
となっております。

rbenvの各環境はversionsフォルダ内に配置されています。
そのため、今回`~/.rbenv`にrbenvをinstallしたのでその中のversionsに環境を作るようなコマンドとなります。

``` ruby-buildを使ってrbenvに任意のバージョンの指定環境を構築.
$ ruby-build 2.3.1 ~/.rbenv/versions/2.3.1-rb_base
```

# 2.3.1-rb_base環境をglobalに指定
これから、railsプロジェクトを作成して行くために一旦今回作成した環境をrbenvのglobal環境に指定する。

``` rbenvのglobalを2.3.1-rb_baseにする.
$ rbenv global 2.3.1-rb_base
```

``` rbenvに作られている各環境を確認.
$ rbenv versions
  system
  2.2.5 
  2.3.1
* 2.3.1-rb_base
```

# 各種必要モジュールをインストール
まず、始めにbundlerをインストールします。
bundlerはgemパッケージ管理モジュールです。Gemfileに記載されているモジュールを一括でインストール、管理してくれる便利な代物です。

``` 指定環境にbundlerをinstall.
$ gem install bundler
```

`bundler init`でGemfileを作成して、作成されたモジュール内のgem railsのコメントを削除します。

``` Gemfile作成と修正.
$ bundler init
$ vi Gemfile
# frozen_string_literal: true
# A sample Gemfile
source "https://rubygems.org"

gem "rails"
```

Gemfileの更新が完了したら`bundler install`でrailsをインストールします。

``` bundlerinstallでrailsをインストール.
$ bundler install
```

# railsプロジェクトを作成
先ほどインストールしたrailsでプロジェクト作成。
作成する際に使用するDBの指定を行います。今回はmysqlを使用します。

``` railsのテンプレートを作成.
$ rails new rb_base -d mysql
```

# rb_baseプロジェクトに指定環境適応
rbenvの機能として指定のプロジェクトに対して環境を紐づける事が出来ます。
今回作成したプロジェクトに対して2.3.1-rb_baseの環境を紐づけます。

これによりglobalの環境を変更してもこのプロジェクトは2.3.1-rb_baseの環境を利用するようになります。

``` rb_baseプロジェクトを2.3.1-rb_base環境に紐づける.
$ cd rb_base
$ rbenv local 2.3.1-rb_base
```

# DB関連対応
まずはmysqlにdatabaseを作成します。

``` database作成.
$ rake db:create
```

Userというmodelを作成します。
modelが作成されますが、それと同時にmigrationも作成してくれます。

``` model（migration）作成.
$ rails generate model User uuid:string:unique name:string
```

作成したmodelのmigrationを実行して先ほど作成したmysqlのdatabaseにUserテーブルを作成します。

``` migration実行して作成したmodelのテーブルを作成.
$ rake db:migrate
```

# controller作成
modelの作成が完了したので、次は各APIの窓口となるcontrollerを作成します。
controllerを作成する際に一緒にactionも作成し、これまた一緒にroutingもしてくれます。

``` controllerとaction(create・getのroutesの設定も)を同時作成.
$ rails generate controller users create get
```

# User登録・取得APIの作成
controller作成の際に作られたファイルを少しいじってDBにUserデータを登録するAPIとDBのUserデータを取得するAPIを作成したいと思います。

``` rb_base/app/controllers/users_controller.rb 
class UsersController < ApplicationController
  def create
    n = params["name"]
    if not n then
      raise Exception
    end
    @user = User.create(name: n, uuid: `uuidgen`.chomp)
  end

  def get
    @users = User.all
  end
end
```

``` rb_base/app/views/users/get.html.erb
<h1>Users#get</h1>
<p>Find me in app/views/users/get.html.erb</p>

<% @users.each do |user| %>
[名前] <%= user.name %> [UUID] <%= user.uuid %><br />
<% end %>
```

``` rb_base/app/views/users/create.html.erb
<h1>Users#create</h1>
<p>Find me in app/views/users/create.html.erb</p>

[名前] <%= @user.name %> [UUID] <%= @user.uuid %><br />
```

# サーバ起動
サーバを起動させます。

``` server起動
$ rails server
```

まずは、http://localhost:3000/users/create/ にアクセスしてみましょう。
下図のようなエラーページが表示されます。

<img width="1103" alt="スクリーンショット 2016-08-22 16.56.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/98305/1f5eeb10-3b74-ea54-e97e-178a462edd93.png">

これは、先ほど編集したapplication_controller.rb内の

``` application_controller.rb
………
    n = params["name"]
    if not n then
      raise Exception
………
```

この部分でnameが指定されていない場合はraiseするようにしておいたため発生したエラーです。
そのため、下記のurlに変更してアクセスしてみましょう。

http://localhost:3000/users/create/?name=yu-sa
<img width="685" alt="スクリーンショット 2016-08-22 16.57.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/98305/a044f242-be64-e045-0d16-7475ee14b942.png">


これで、name yu-saがDBに登録されました。

それでは、登録されたデータを参照してみましょう。

http://localhost:3000/users/get/
<img width="687" alt="スクリーンショット 2016-08-22 16.57.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/98305/0187bd78-86b0-de1c-5907-c7918e0e7f32.png">

getのAPIにアクセスする事で登録されたUserの情報を取得する事が出来ます。

# github
上記対応を行ったソースコードをgithubにあげているので、興味がある方はcloneしてみて下さい。
https://github.com/yu-sa/rb_base

# まとめ
* defacto standardなだけあり、ほぼコマンドを叩くだけで簡単なAPIが作成出来てしまいます。
* modelの中を見てみると解るのですが、各tableのカラムの情報はDBから引っ張ってきているようなので、ソースコード内からはtableのカラムに何が存在するのかを目視で確認する事は出来ないようです。ある意味、これが純粋なオブジェクト指向の形にするためのものなのかな？と勝手に推測しているのですがどうしてなのか知っている人がいましたら教えて下さい。
* rbenvは便利なのだが、かゆい所に手が届いていないような気がします。是非virtualenvのようなモジュールが作られる事を祈ります。もしくは、時間を見てrbenvの更新に参加してみるのもありかなと思ったりしていますが、まずはOSSのお作法とか勉強しないとですね。