Version 2014-02-24-1
永遠に書きかけ、日々是更新、無常迅速、時人を待たず
Now information Alpha
Advise you have information Alpha
rails.png

Ruby on Rails with PostgreSQL for MacOSX

Don't expect scaffolding
to replace the need for you
as a programmer just yet (or ever).
---- David Heinemeier Hansson

ようするに

(0) Rails のデータベースのトレンドは PostgreSQL

(1) データベースは rails が作る。

  PostgreSQL のコマンド createdb や psql シェルを使わない。
    Ruby on Rails の設計思想として、
    データベースを隠蔽したい、SQL を使わないで済ませたい。
  PostgreSQL のコマンド createuser -d だけは必要。
    Rails Application の名前で
    PostgreSQL user (role) を登録しておく必要はある。
    あとは rails が全部やってくれる。

(2) scaffold がみそ。

  scaffold には model のタイプを指定する。
  指定する model のタイプはとりあえず Product や Post で。
  rails generate scaffold すれば
  model と view と controller がすべて generate される。

(3) データベースはいつだれが作るのか?

  rake db:setup が作る。
    とにかくラッパーコマンド createdb は使わない。
    データベースを作るのは rails の仕事。

(4) rake db:migrate はなにをするのか?

  db/schema.rb を作る。

(5) rake db:migrate はいつすべきか?

  rake db:setup したあと。

(6) rake db:setup はいつすべきか?

  rails generate scaffold したあと。
  すでに createuser -d していること。

(7) createuser -d はいつすべきか?

  rake db:setup するまえでいいけれど、
  rails new するまえがタイミングとして美しい。

(8) rake db:setup と rake db:migrate のどちらがさき?

  rake db:setup がさき。

ざっくりまとめ

Install Rails
% sudo port -v selfupdate
% sudo port install ruby19
% sudo gem1.9 install rails

Install the driver for PostgreSQL
% sudo gem1.9 install pg

Create the demo application without database
% mkdir ~/work
% cd ~/work
% rails new demo
% cd demo
Let's start with the controller.
% rails generate controller welcome index
% vim app/views/welcome/index.html.erb
% rails server
See http://localhost:3000/welcome/index

Create the blog application with scaffold 'Post' model
% sudo su postgres -c 'createuser -d blog'
% cd ~/work
% rails new blog --database=postgresql
% cd blog
% rails generate scaffold Post title:string body:text
% rake db:setup
% rake db:migrate
See http://localhost:3000/posts

Create the depot application with scaffold 'Product' model
% sudo su postgres -c 'createuser -d depot'
% cd ~/work
% rails new depot --database=postgresql
% cd depot
% rails generate scaffold Product Admin
% rake db:setup
% rake db:migrate
See http://localhost:3000/products/admin

Use a rake command to run the migration
% vim config/database.yml
% rake db:migrate

Rails のインストール: gem (RubyGems) を使う

MacOSX (Mountain Lion) に ruby と gem はシステムとして \(^o^)/ 入っていますが rails までは入っていません。 gem は Ruby のパッケージ・マネージャーですね。 gem で rails を入れてみたら、

% sudo gem install rails
ERROR:  Error installing rails:
	activesupport requires Ruby version >= 1.9.3.
% ruby -v
ruby 1.8.7 (2012-02-08 patchlevel 358) [universal-darwin12.0]

ruby が古くて断られました。 ruby を 1.9.3 以上にしてみます。

Ruby のインストール: port (MacPorts) を使う

BSD ユーザーなら MacPorts ですね。 Not just for little boys ですね。 まず port をインストールします。 port は /opt/local/ へ入ります。

Grab MacPorts

すでに port が入っていた場合はアップデートしておきます。

% sudo /opt/local/bin/port -v selfupdate

では port で ruby を 1.9.3 以上にしてみます。

% sudo /opt/local/bin/port install ruby19

最新の port は +nosuffix が廃止されているようなので +nosuffix オプションはつけなくてかまいません。

RubyGems のインストール

Ruby 1.9.3 以降では RubyGems もいっしょにインストールされます。

以上で、ruby1.9 と gem1.9 が /opt/local/bin に入りました。 システムの ruby (1.8) と gem (1.8) は /usr/bin です。 システムの ruby と gem はそのままでかまいません。 消してもいいですが、べつに消す必要もありません。 古い Ruby は Ruby Security Vulnerability; CVE-2013-4164 が報告されています。

Rails のインストール、リトライ

/opt/local/bin/gem1.9 を使って Rails を入れてみます。

% sudo /opt/local/bin/gem1.9 install rails 
% /opt/local/bin/rails -v
Rails 4.0.2

コマンドパスを /opt/local/bin へ通しておきます

% cp -p ~/.cshrc ~/.cshrc.old
% echo 'setenv PATH /opt/local/bin:${PATH}' >> ~/.cshrc

ふつうに呼べるようにリンクしておきます

% cd /opt/local/bin
% sudo ln -s gem1.9 gem
% sudo ln -s ruby1.9 ruby
Postgres Elephant.tiff

PostgreSQL のインストール

BSD ユーザーなら PostgreSQL ですね。 MacOSX も BSD ですから MacOSX Server のデフォルト・データベースは PostgreSQL ですね。 最新 Rails のトレンドは MySQL ではなく PostgreSQL だそうで助かります。 MacOSX Server には PostgreSQL がすべてインストールされていますが、 スタンダード版の MacOSX にインストールされているのは PostgreSQL のクライアントだけです。

Grab PostgreSQL

PostgreSQL をインストールする方法が 6通りあって迷います。 Building from source, pgAdmin, Postgres.app, Fink, MacPorts, Homebrew です。 マイ・サーバー (Mac mini) の PostgreSQL は Building from source なのですが、 今回は the binary distribution でラクしてみます。 MacOSX なら Homebrew が easy way でしょうか。 most easiest way は Postgres.app のような気がします。

Ruby を MacPorts で入れたので、PostgreSQL も MacPorts で入れてみます。

% sudo port install postgresql92-server

なんという簡単さでしょう! あとはセットアップと初期化と実行だけ。

PostgreSQL の起動

データベースシステム自身を起動するために、デフォルトのロール postgres がスーパーユーザーとして用意されています。データベースの起動にはユーザー postgres になる必要がありますので sudo を使います。データベース・システムに属するファイルのオーナーも postgres でなければなりません。 The files belonging to this database system will be owned by user "postgres". This user must also own the server process.

% sudo mkdir -p /opt/local/var/db/postgresql92/defaultdb
% sudo chown postgres:postgres /opt/local/var/db/postgresql92/defaultdb
% sudo su postgres -c '/opt/local/lib/postgresql92/bin/initdb -D /opt/local/var/db/postgresql92/defaultdb'
% sudo su postgres -c '/opt/local/lib/postgresql92/bin/pg_ctl -D /opt/local/var/db/postgresql92/defaultdb -l /opt/local/var/log/postgresql92/postgres.log start'

PostgreSQL ユーザーアカウントの作成
createuser - define a new PostgreSQL user account

新しいロールを作る場合、「ロール」の名前と「オペレーティングシステムのユーザー」の名前を一致させておくと便利です。 「自分は joe、自分に postgres ロールを与えたい」なら:

% sudo su postgres -c '/opt/local/lib/postgresql92/bin/createuser -s -e -U postgres joe'
CREATE ROLE joe SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN;

-s は The new user will be a superuser で、 -U username は User name to connect as (not the user name to create) です。 ふつう、ロールの作成には -U postgres を使いません。そんな権限を与えるのは危険だし、必要ないからです。 自分に -U postgres しておけば postgres 権限が必要なコマンドを(sudo せず)そのまま実行できるので便利にはなりますがちょっと危険にもなります。

PostgreSQL データベースの作成
createdb - create a new PostgreSQL database

% sudo su postgres -c 'createdb my_db'

PostgreSQL データベースの一覧
psql - PostgreSQL interactive terminal

けっこう盲点です。 psql で \l です。list の l です。 ていねいに書くと psql template1 または psql -U postgres で psql ターミナルに入って、メタ・コマンド \l です。 テーブルの一覧は \d です。 ユーザーの一覧は \du です。 ようするにデータベースの一覧のラッパーコマンドはありません。 ラッパーコマンドで createdb と dropdb はあるのに listdb がない理由は知りません。 listdb とか listtable とか listuser というラッパーコマンドはあれば便利かもしれませんが 「ラッパーコマンドとしてそれらは存在することが美しくない」 から用意されないのだろうと思います。

% psql -U postgres
psql (9.2.6)
Type "help" for help.

postgres=# \l
                                List of databases
   Name    |  Owner   | Encoding | Collate |    Ctype    |   Access privileges   
-----------+----------+----------+---------+-------------+-----------------------
 postgres  | postgres | UTF8     | C       | ja_JP.UTF-8 | 
 template0 | postgres | UTF8     | C       | ja_JP.UTF-8 | =c/postgres          +
           |          |          |         |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | C       | ja_JP.UTF-8 | =c/postgres          +
           |          |          |         |             | postgres=CTc/postgres
(3 rows)

PostgreSQL の停止

% sudo su postgres -c '/opt/local/lib/postgresql92/bin/pg_ctl -D /opt/local/var/db/postgresql92/defaultdb stop'

コマンドパスを PostgreSQL へ通しておきます

% echo 'setenv PATH /opt/local/lib/postgresql92/bin:${PATH}' >> ~/.cshrc

Rails と PostgreSQL をつなぐ

さて、ここから本番。動き出した PostgreSQL サーバーと Rails と連携させます。 Rails の PostgreSQL ドライバをインストールするだけでいいはずです。

ドライバ pg のインストール
Install the pg driver

% sudo /opt/local/bin/gem1.9 install pg

Rails Application の作成
rails new

Rails でのアプリケーションって何? ようするにディレクトリ。コマンド rails new で作られるのは必要最低限のディレクトリとファイルだけ。 rails new でディレクトリをまず作ってから、ちゃんとした中身をコマンド rails scaffold で作るわけですね。

'pg' ドライバをインストールした後はもう PostgreSQL のことは忘れていいはずです。 そうでないと Rails 使っている意味がありません。 新しいデータベースを作るのも PostgreSQL の createdb を使わずに Rails の rake を使うわけですね。 SQL をまったく知らない人でもデータベースをアクセスする web アプリケーションを作れてしまうフレームワークを目指して Rails は設計されたわけでしょうから。 とにかく「データベースを作ったりテーブルを定義したりというルーチンから解放されたい」から Rails を使うわけですから。

では、PostgreSQL のデータベース blog をアクセスする Rails application を作ってみたいと思います。 ようするにコマンド rails new は the application generator (script) であり、 カレント・ディレクトリにプロジェクト・ディレクトリを作るというわけです。

Rails application called 'blog' を作ってみます。 アプリケーション 'blog' とはつまり、プロジェクト 'blog' でありディレクトリ 'blog' です。

% mkdir ~/RailsProjects
% cd ~/RailsProjects
% sudo su postgres -c 'createuser -d blog'
% rails new blog --database=postgresql

rails new は bundle install もします。そのとき sudo のパスワードを要求されるかもしれません。 rails new はデータベースのおおまかな設定書 config/database.yml も作ります。

Rails Scaffold の作成
rails generate scaffold

generate scaffold はアプリケーションの足場を作ります。 具体的には Controller, Model, View をまとめていっきに作ります。 Controller, Model, View はそれぞれ個別に作ってもいいのですが、 scaffold でどかっと作ってとにかく実働させてから永久に修正し続ける というスタイルが筋です。 まさにアジャイル。エンドレス。 アジャイルに完成というか公開レベルという概念はない。

% cd blog
% rails generate scaffold Post title:string body:text

'Post' モデルで scaffold を generate せよ、というコマンドです。 scaffold にはいろんなモデルタイプ (Product, Post, Page, etc...) を指定できますが、ここでは 'Post' を指定しました。

generate scaffold はいろいろ作ってくれます。 そのなかにデータベース設定のための migration file が db/migrate/ にあります。 たとえば 20140224033947_create_posts.rb という名前になっているファイルです。 これはデータベースのテーブルの設定書です。 このファイルは rake db:setup が使います。 データベースにテーブルを作るのは rake db:setup です。

rails generate scaffold のあと rake db:setup して rake db:migrate して rails server すれば http://localhost:3000/posts で記事の編集ができるようになり、とりあえずのアプリケーション完成です。

アプリケーション 'blog' を一発で作るスクリプト blog.sh を作ったらこうなるでしょう。ほんとにこのスクリプトいっぱつで web アプリケーションが稼働します。

% cat blog.sh 
#!/bin/sh
rails new blog --database=postgresql
cd blog
rails generate scaffold Post title:string body:text
rake db:setup
rake db:migrate 
rails server

データベースの設定書
config/database.yml

rails new が config/database.yml を作ります。 config/database.yml はデータベースのおおまかな設定書です。 これはデータベースのテーブルの設定書ではありません。

アプリケーション 'blog' ならこのようになっているはず。

% cat config/database.yml
development:
  adapter: postgresql
  encoding: unicode
  database: blog_development
  pool: 5
  username: blog
  password:

test:
  adapter: postgresql
  encoding: unicode
  database: blog_test
  pool: 5
  username: blog
  password:

production:
  adapter: postgresql
  encoding: unicode
  database: blog_production
  pool: 5
  username: blog
  password:

データベースのテーブルの設定書
a database migration file inside the db/migrate/

rails generate scaffold が a database migration file を作ります。 これはデータベースのテーブルの設定書です。 rails generate scaffold はいろいろ作ります。 db/migrate/ には a database migration file を作ります。 rake db:setup はこの migration file を読んでデータベースにテーブルを作ります。 テーブルを実際に作るのは rake db:setup です。

migration file はこのようになってるはず。

% cat db/migrate/20140224060319_create_posts.rb
class CreatePosts < ActiveRecord::Migration
  def change
    create_table :posts do |t|
      t.string :title
      t.text :body

      t.timestamps
    end
  end
end

データベースの作成
rake db:setup

% rake db:setup

rake db:setup は config/database.yml を読み、ユーザー blog (ロール blog) として blog_development と blog_test というデータベースを作り、それぞれに schema_migrations テーブルを作ります。

データベースのテーブルの作成
rake db:migrate

% rake db:migrate

rake db:migrate は db/schema.rb を作ります。

データベースのスキーマの設定書
db/schema.rb

rake db:migrate が db/schema.rb を作ります。これは rails server が読みます、

db/schema.rb はこのようになっているはず。

% cat db/schema.rb
ActiveRecord::Schema.define(version: 20140224060319) do

  create_table "posts", force: true do |t|
    t.string   "title"
    t.text     "body"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

end

This file is auto-generated from the current state of the database. Instead of editing this file, please use the migrations feature of Active Record to incrementally modify your database, and then regenerate this schema definition.

Note that this schema.rb definition is the authoritative source for your database schema. If you need to create the application database on another system, you should be using db:schema:load, not running all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations you'll amass, the slower it'll run and the greater likelihood for issues).

It's strongly recommended that you check this file into your version control system.

migration file ってなに? いつだれが作るの?

いつ: rails new のあと。
だれ: rails generate が作ります。
migration file はデータベースのテーブルの設定書です。 rails generate scaffold が migration file を作ります。 rake db:setup が migration file を読んでデータベースにテーブルを作ります。

migration file があればいつでも(なんどでも)テーブルを設定できます。 migration file の名前にはタイムスタンプが含まれているので、 テーブルの設定をある時の状態に戻したい(undo)ときには、 その時の migration file を使えばよいわけです。 だから migration file はずっと残しておくべきものです。

データベースはいつだれがつくるの?

いつ: rails generate scaffold のあと。
だれ: rake db:setup がデータベースを作ります。

データベースのテーブルはいつだれがつくるの?

いつ: rake db:setup のあと。
だれ: rake db:migrate がデータベースのテーブルを作ります。

既存のデータベースのテーブルを使うにはどうするの?

(この項目はまだ書けてません)

データベース関連コマンド

# Create the database, load the schema, and initialize
# with the seed data (use db:reset to also drop the db first)
rake db:setup

# Display status of migrations
rake db:migrate:status

# Migrate the database (options: VERSION=x, VERBOSE=false).
rake db:migrate
rake db:migrate VERSION=xxxx

# Execute migrations in another environment
rake db:migrate RAILS_ENV=development
rake db:migrate RAILS_ENV=test
rake db:migrate RAILS_ENV=production

# If you need to create the application database on another system,
# you should be using
rake db:schema:load

# Drop the database
rake db:reset         

See also

http://guides.rubyonrails.org/getting_started.html

Tips

Auto launch by LaunchDaemons:
% sudo launchctl load -w /Library/LaunchDaemons/org.macports.postgresql92-server.plist
To tweak your DBMS: 
consider increasing kern.sysv.shmmax
  by adding an increased kern.sysv.shmmax ..
    to /etc/sysctl.conf

Bible

Agile Web Development with Rails は must-have です。 買うなら原書で。

Links

Ruby on Rails Guides
http://guides.rubyonrails.org/ とにかくここ。ここだけでいい。

PostgreSQL
http://www.postgresql.org/
http://www.postgresql.org/docs/manuals/

Keeping Up-to-Date

Show the version
% rails -v
% ruby -v
Ruby Security Vulnerability; CVE-2013-4164
You should see something like one of the following, 
depending on the version of Ruby:
ruby 1.8.7p375 (2013-11-22 revision 375)
ruby 1.9.2p321 (2013-11-22 revision 321)
ruby 1.9.3p484 (2013-11-22 revision 43786)
ruby 2.0.0p353 (2013-11-22 revision 43784)
Keeping up-to-date
% sudo gem update rails

topic: macosx
first posted: 2014-02-17 20:00:53
last modified: 2014-02-24 16:11:58