ラベル rails の投稿を表示しています。 すべての投稿を表示
ラベル rails の投稿を表示しています。 すべての投稿を表示

2011年11月16日水曜日

Railsを使ったアプリケーション開発 (その4 応用編 認証機能の追加)


Railsを使ったアプリケーション開発 (その1 事前準備編)
Railsを使ったアプリケーション開発 (その2 基礎編)
Railsを使ったアプリケーション開発 (その3 応用編)

3回に渡ってRailsを使ってきた。4回目は、認証機能をフィルタを利用して実装させる。

一からログインユーザを管理するテーブルを作るのは手間なので、その3にて作成済みのusersテーブル(userモデル)を利用する。


フィルタを利用した認証機能
アクションの前に処理を実行させるbefore_filterを利用する。ApplicationControllerはすべてのコントローラの基底クラスになっているのでどのアクションにも事前に適用されることとなる。

# vi ./app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery
  before_filter :check_logined

  private
  def check_logined
    if session[:user] then
      begin
        @user = User.find(session[:user])
      rescue ActiveRecord::RecordNotFound
        reset_session
      end
    end

    unless @user
      flash[:referer] = request.fullpath
      redirect_to :controller => 'login', :action => 'index'
    end
  end
end


protect_from_forgeryメソッドというのが気になったかもしれない。目的はCSRF対策であり、以下で呼び出される。

# cat app/views/layouts/application.html.erb
<%= csrf_meta_tags %>

Railsでは自動でCSRF対策をしてくれるので3点だけ気に留めておけばよい。
● HTTP GETを使ってデータ操作は行わない
● データ操作のリクエストはビューヘルパー(form_for、form_tag、link_to)を利用する
● レイアウト変更時はcsrf_meta_tagsメソッドを呼び出す


さてこれで前回作った検索サイトにでもアクセスしてみたとする。
※実際にはまだアクセスはできない
http://x.x.x.x/store/search
初回のアクセスでは当然unless文をたどることになるので、
ログインページへとリダイレクトされるはずだ。
http://x.x.x.x/login/index

認証が通った場合は、リクエストしたページへ行く必要があるため、フラッシュ(flash)を使ってそのページを覚えさせておく。フラッシュとはいわゆるセッションなのだが、次のリクエスト先で自動で削除されるためセッションの管理の手間が省けるメリットがある。

テンプレート変数を使うことはできない。テンプレート変数は現在のコントローラでのアクションとビューのテンプレート間でしか共有できないからだ。renderと異なり、redirect_toはリダイレクトによる処理の委譲を意味するものである。クライアントにリダイレクト先URLを返却し、クライアントは再度そのURLにリクエストをあげるという動きを考えれば理解が得られるだろう。よってこのようなページまたぎには、一時的な変数としてフラッシュを使うのである。

ではこのlogin/indexページも作成しよう。
いつもの通りコントローラとビューを作っていけばいい。
ここでは先にビューを見た方が分かりやすいだろうか。

# vi app/views/login/index.html.erb
<p style="color: Red"><%= @error %></p>
<%= form_tag :action => 'auth' do %>
  <div class="field">
    <label>USER NAME:<br />
    <%= text_field_tag(:name, '', { :size => 20 }) %></label>
  </div>
  <div class="field">
    <label>PASSWORD:<br />
    <%= password_field_tag(:password, '', { :size => 20 }) %></label>
  </div>
  <%= hidden_field_tag :referer, flash[:referer] %>
  <%= submit_tag 'login' %>
<% end %>


indexページのコントローラは特に今回のサンプルでは不要であろう。formタグで指定したauthページはコントローラから別URLへリダイレクトさせるためビューは不要である。
また、このauthページは当然認証は不要であるためskip_before_filterを利用している。

# vi app/controllers/login_controller.rb
class LoginController < ApplicationController
  skip_before_filter :check_logined

  def index
   特に今回のサンプルでは不要
  end

  def auth
    user = User.authenticate(params[:name], params[:password])
    if user then
      session[:user] = user.id
      redirect_to params[:referer]
    else
      flash.now[:referer] = params[:referer]
      @error = 'username / password error'
      render 'index'
    end
  end

  def logout
    reset_session
    redirect_to '/'
  end
end


submitフォームからのPOST情報はparamsメソッドで受け取れる。paramsメソッドではURLの末尾に付与される情報や、ルートで定義されたパラメータ(例 /books/1 の1など)も取得できる。

ユーザ情報を引けなかった場合はelse文をたどるわけだが、そこでflash.nowを利用している。テンプレート変数(@~)を使わないのはなぜだろうか。それは"./app/views/login/index.html.erb"内ではhiddenタグ内にflashの結果を埋め込んでいるためである。flash.nowにしているのは、次のリクエストまでフラッシュを残しておく必要がないからだ。

ログアウト処理させるならlogoutメソッドを呼べばよい。


最後にUserモデルのメソッドをモデル内で定義しておく。
# vi app/models/user.rb
class User < ActiveRecord::Base
  def self.authenticate(name, password)
    where(:name => name,
      :password => password).first
      #:password => Digest::SHA1.hexdigest(password)).first
  end
end


以上

2011年11月15日火曜日

Railsを使ったアプリケーション開発 (その3 応用編)


Railsを使ったアプリケーション開発 (その1 事前準備編)
Railsを使ったアプリケーション開発 (その2 基礎編)
ときて、いよいよ3回目である。

いよいよ書籍を管理するアプリケーションを作る。

手動でコントローラ、ビュー、モデルを作成してきたがもっと楽な手段がある。
Scaffolding機能を使う方法である。コマンド一発で、特定のテーブルをCreate、Read、Update、Delete操作できる、簡易アプリケーションが作れてしまう。

この機能を利用して書籍管理アプリケーションを作ってみる。



テーブルの設計
実体と属性
()はrailsが自動で作成する。
赤は主キー、青は非主キーである。
*が外部キーを表す。

books
 (id) title price (created_at) (updated_at)

users
 (id) name password (created_at) (updated_at)

authors
 (id) name (created_at) (updated_at)

reviews
 (id) bookd_id* user_id* body (created_at) (updated_at)

books_authors
 book_id* author_id*



ER図もどき
    books 1 - N reviews N 1 users
       1
       |
       N
author_books
       N
       |
       1
    authors



Scaffoldingを利用して関連ファイルを一括作成

今はここにいる。
# pwd
/var/www/rails/bookapp

モデルクラス名は単数なので注意を。複数形にするのはテーブルだけである。
# rails generate scaffold book title:string price:integer

# rails generate scaffold user name:string password:string

# rails generate scaffold author name:string

# rails generate scaffold review book:references user:references body:text

# rails generate model authors_book book:references author:references

author_booksだけscaffoldで作らなかった。純粋な中間テーブルをCRUDに従った操作をする必要はないと判断したためである。もちろん作ってもかまわない。



マイグレーションファイルによるテーブルの作成
自動でマイグレーションファイルはできているが、主キー列、created_at列、updated_at列が不要な中間テーブルの作成前には一部編集が必要である。主キーを無効化し、かつタイムスタンプ列を削除する。

# vi db/migrate/20111113040505_create_author_books.rb
def change
  create_table :author_books, :id=>false do |t|
    t.references :book
    t.references :author
    t.timestamps ←削除
  end
  add_index :author_books, :book_id
  add_index :author_books, :author_id
end


テーブルを作成する。
# rails db:migrate RAILS_ENV=development



テストデータの流し込み
自動でテストデータが作られている。流し入れるデータを変えたければymlファイルを編集すればよい。

# vi test/fixtures/books.yml
book1:
 title: book1
 price: 1000

book2:
 title: book2
 price: 2000

book3:
 title: book3
 price: 3000

上記のように記載していくと手間がかかるためブロックを使った式をymlファイルに記載してもよい。
<% 1.upto(3) do |n| %>
book<%= n %>:
  title: book<%= n %>
  price: <%= n * 1000 %>
<% end %>


# vi test/fixtures/users.yml
<% 1.upto(3) do |n| %>
user<%= n %>:
  name: name<%= n %>
  password: password<%= n %>
<% end %>


# vi test/fixtures/authors.yml
<% 1.upto(3) do |n| %>
author<%= n %>:
  name: name<%= n %>
<% end %>


reviwesテーブルはカラムにbookd_idとuser_idをもち、それぞれbooksテーブル、usersテーブルの外部キーになっているはずである。しかしbook_id、user_idにidを入れて参照元のテーブルと紐づけるのは手間である。そこでラベル名で参照先を識別させることもできる。
# vi test/fixtures/author_books.yml
one:
  book: book1
  author: author2

two:
  book: book3
  author: author1


上と同じく、book_id、user_idは使わずラベル名を利用する。
# vi test/fixtures/reviews.yml
one:
  book: book1
  user: user2
  body: fantastic

two:
  book: book2
  user: user3
  body: interesting



ymlの試験データを元にデータをテーブルへ流し込む。
# rails db:fixtures:load FIXTURES=books RAILS_ENV=development

# rails db:fixtures:load FIXTURES=users RAILS_ENV=development

# rails db:fixtures:load FIXTURES=authors RAILS_ENV=development

# rails db:fixtures:load FIXTURES=reviews RAILS_ENV=development

# rails db:fixtures:load FIXTURES=author_books RAILS_ENV=development

同じコマンドを2回打っても追記はされない。ymlファイルに記載されているものだけが挿入される。既に存在している行があってもymlになければその行は削除される。


データベースを初期化するにはこうである。
# rails db:reset



ルーティングの作成
ルーティングも自動で入っている。
# cat config/routes.rb
(略)
  resources :reviews
  resources :authors
  resources :users
  resources :books
(略)


# rails routes
ヘルパー名    HTTPメソッド URLパターン                 ルートパラメータ
(略)
books       GET         /books(.:format)           {:action=>"index", :controller=>"books"}
            POST        /books(.:format)           {:action=>"create", :controller=>"books"}
new_book    GET         /books/new(.:format)       {:action=>"new", :controller=>"books"}
edit_book   GET         /books/:id/edit(.:format)  {:action=>"edit", :controller=>"books"}
book        GET         /books/:id(.:format)       {:action=>"show", :controller=>"books"}
            PUT         /books/:id(.:format)       {:action=>"update", :controller=>"books"}
            DELETE      /books/:id(.:format)       {:action=>"destroy", :controller=>"books"}
(略)


ヘルパーとはテンプレートファイルを記述する際に役立つメソッドの総称である。

パスヘルパー          得られるパス
books_path         /books/
book_path(id)      /books/:id
new_book_path      /books/new
edit_book_path(id) /books/:id/edit


<%= link_to 'Edit', edit_book_path(book) %>
<%= link_to 'New',  new_book_path(book) %>

XXX_path 部分を XXX_url に変えると相対パスから、絶対パスになる。


さて、RESTfulなインターフェースになっていることに気がつくだろうか。RESTfulであるとは一意なURLに対して、CRUD(Create、Read、Update、Delete)を使ってアクセスできるということである。CRUDをHTTPプロトコルにあてはめると、POST、GET、PUT、DELETEになる。URLを一意にすることでインターフェースを統一し、プロトコルにしたがってルートパラメータでリソースを制御するのである。



確認
テーブルを作成し、テストデータを流し込んだので以下にアクセスして確認してみる。
Create、Read、Update、Delete操作ができるので触ってみてほしい。
http://x.x.x.x/books
http://x.x.x.x/users
http://x.x.x.x/authors
http://x.x.x.x/reviews



ついでに検証機能もいれておこう。
モデルファイルの編集(検証機能の設定)
bookモデルに検証機能を入れる。
タイトルは必須、また長さは1~100。
価格はintegerのみで価格は100000以下。

# vi app/models/book.rb
validates :title,
          :presence => true,
          :length => { :minimum => 1, :maximum => 100 }

validates :price,
          :numericality => { :only_integer => true, :less_than => 100000 }


再度アクセスして、書籍を新規に登録してみよう。
http://x.x.x.x/books
検証機能に違反する操作を行うとエラーが出るはずである。


これはどうやってエラーを表示させているのであろうか。
# cat app/views/books/new.html.erb
<%= render 'form' %>
部分テンプレートになっている

# cat app/views/books/_form.html.erb
  <% if @book.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@book.errors.count, "error") %> prohibited this book from being saved:</h2>

      <ul>
      <% @book.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

CSSを変えたければ以下のファイルのfield_with_errorsを編集すればよい。
# cat ./app/assets/stylesheets/scaffolds.css.scss
.field_with_errors {
(略)
}


最後に、複数のオブジェクトモデル(リレーショナルテーブル)を作ったので
それらを連携させたアプリケーションを作成する。
http://x.x.x.x/store/search
にアクセスして書籍を検索できるサイトを作る。



モデルファイルの編集(アソシエーションの設定)
" テーブルの設計"で作成したER図を見ながら考える。
再掲

    books 1 - N reviews N 1 users
       1
       |
       N
author_books
       N
       |
       1
    authors



# vi app/models/book.rb ※下記コードを挿入
has_many :authors
has_many : author_books
has_many :authors, through: :author_books

# vi app/models/user.rb ※下記コードを挿入
has_many :reviews
has_many :books, through: reviews

# vi app/models/author.rb ※下記コードを挿入
has_many :author_books
has_many :books

# vi app/models/review.rb ※下記コードを挿入
# booksテーブルとusersテーブルのM:Nひもづけ用中間テーブル
belongs_to :book
belongs_to :user


純粋な中間テーブル用のモデルは不要である
# rm app/models/books_author.rb



コントローラとビューの作成
# rails generate controller store

# vi app/views/store/search.html.erb
<%= form_tag :action => 'scan' do %>
  <div class="field">
    <%= label_tag 'title', 'book title:'  %><br />
    <%= text_field_tag 'title' %>
  </div>
  <%= submit_tag 'search' %>
<% end %>


# vi app/controllers/store_controller.rb ※下記コードを挿入
def scan
  @books = Book.where('title = ?', params[:title])
  render 'list'
end


# vi app/views/store/list.html.erb
<% @books.each do |book| %>
<h1>TITLE : <%= book.title %></h1>
<hr />

<ul>
  <li>PRICE : <%= book.price %></li>
  <% book.authors.each do |author| %>
  <li>AUTHOR : <%= author.name %> </li>
  <% end %>
</ul>

<h1>REVIEW</h1>
<hr />
<ul>
<% book.reviews.each do |review| %>
<li><%= review.body %>(<%= review.updated_at %>)</li>
<% end %>
</ul>
<% end %>



ルーティングの編集
"http://localhost/bookapp/store/search"としてアクセスさせたい。RESTfulインターフェースにはsearch、scan、listのアクションはないので、自前で用意する。

# vi config/routes.rb
resources :store do
  collection do
    get 'search'
    post 'scan'
    get 'list'
  end
end

# rails routes
search_store_index GET    /store/search(.:format {:action=>"search", :controller=>"store"}
  scan_store_index POST   /store/scan(.:format) {:action=>"scan", :controller=>"store"}
  list_store_index GET    /store/list(.:format) {:action=>"list", :controller=>"store"}

collectionは複数のオブジェクトを扱うが、単一のオブジェクト、例えば、GET時に、/store/:id/hoge のようなルーティングを作りたければ、memberブロックを使う。

member :store do
  member do
    get 'hoge'
  end
end



サービス確認
書籍名に"book1"などを入れて検索結果が出てくれば成功である。
http://x.x.x.x/store/search


Next ⇒ Railsを使ったアプリケーション開発 (その4 応用編 認証機能の追加)




2011年11月14日月曜日

Railsを使ったアプリケーション開発 (その2 基礎編)


書籍を管理するアプリケーションを作ることを目的とする。

Railsを使ったアプリケーション開発 (その1 事前準備編)までは終わっているものとする。


コントローラの作成
これからはすべてbookappディレクトリ配下で作業を行う。
# cd /var/www/rails/bookapp

コントローラを作る。最初なのでコントローラ名はfirstとする。
複数のアクション(メソッド)をまとめたものがコントローラと考えていい。
# rails generate controller first
generateをdestroyにするとコントローラを破棄できる。

以下のファイルは既にできている。一部を修正するだけでよい。
# vi app/controllers/first_controller.rb
class FirstController < ApplicationController
  def index
    @msg = 'hello world!!'
  end
end



ビューの作成
# vi app/views/first/index.html.erb
<div id='main'>
<%= @msg -%>
</div>

ハイフン(-)を付与すると、後方のスペースや改行を除去できる。

<html>や<body>はレイアウト側で作られているため、
ビューのテンプレートに記載する必要はない。
ディフォルトのレイアウトとして次が使われる
# cat ./app/views/layouts/application.html.erb
<html>
<head>
(略)
<%= yield %> ← ここに埋め込まれる
(略)
</body>
</html>

レイアウトを変える場合はコントローラ内のアクションメソッドで指定する。
"app/views/layouts/layout.html.erb"が呼び出される。もちろん別テンプレートを使う場合は、自分で作成する必要がある。

def index
  render :layout => 'layout'
end



ルーティングの作成
:controllerと:actionはコントローラとその中のアクションメソッドであり、:idはアクションメソッドに渡されるパラメータである。丸括弧部分は省略可能である。
# vi config/routes.rb
get ':controller(/:action(/:id(.:format)))'

# rails routes



確認
http://x.x.x.x/first/index へブラウザからアクセスする。

hello world!!

と表示されれば成功である。

続いてモデルの開発を行うが、その前に備忘録。



備忘録
● ログについて
うまく表示されない場合はログを参考にエラー原因を特定する。
# tail -f log/development.log


● コントローラとビューについて
コントローラのアクションメソッドとビューのテンプレートを共に用意しなければならないのであろうか。

    コントローラのアクションメソッド ビューのテンプレート
(1) あり               あり
(2) なし               あり
(3) あり               なし

(1) 
これは上で作った通り、コントローラとビューを用意した場合である。リクエストの起点としてコントローラクラスのアクションメソッドが実行された後、対応するビューのテンプレートが検索され実行される。

(2)
アクションメソッドが存在しない場合、テンプレートファイルを直接見に行く。つまりビューだけでも問題ない。ただし、MVC(Model、View、Controller)は役割を分けることを目的としているため、意味もなくビューだけでアプリを完遂させるべきでないことは言うまでもない。

(3)
アクションメソッドが存在し、テンプレートファイルがない場合はエラーになる。ただし、次の場合を除く。

a. テキストスクリプトを出力する場合
# vi ./app/controllers/first_controller.rb
class FirstController < ApplicationController
  def index
    render :text => 'hello world!!'
  end
end


b. アクションメソッド内で、リダイレクトURIを指定している場合
# cat ./app/controllers/first_controller.rb
class FirstController < ApplicationController
  def index
    redirect_to 'http://example.com'   
  end
end


c. アクションメソッド内で、別のアクションメソッドを呼び出している場合
コントローラのアクションメソッドではなく、
ビューのテンプレートファイルが読み出されることに注意が必要である。

# vi ./app/controllers/first_controller.rb
class FirstController < ApplicationController
  def index
    @msg = 'hello world!!'
    render :action => 'index2'
  end
end


何度も言うが、actionとなっているが、ビューのテンプレートが読み出される。つまり、ビューのテンプレート"./app/views/first/index2.html.erb"が必要である。ディフォルトの"./app/views/first/index.html.erb"ビューテンプレートではなく、renderで指定したテンプレートを使う、とう意味である。renderの意味がレンダリングであることを考えれば混乱しないだろう。

ちなみに、HTMLの<form>タグではaction属性で、送信先プログラムのURIを指定できる。それは、普通にそのURIへの処理になる。あたりまえだが、Railsのアクションとは何も関係ない。

Rails的にはURIの処理過程で、コントローラのアクションメソッド、そしてビューのテンプレートファイルが読み出されるだけである。


● renderとは
renderの話が出たのでrenderの機能をまとめておく。描画するためのrendering処理であることを考えれば統一的な理解ができる。

render
・コントローラ内メソッドのからのビューのテンプレートの呼び出し
(1)の話である。

・コントローラ内メソッドでのテキストスクリプトの出力
(3)-a の話である

・ビューのテンプレートからの部分テンプレート呼び出し
ビューのテンプレートからでもrenderは使える。


● 部分テンプレートとは
部分テンプレートの話が出たのでそのことにも触れておく。
HTMLのヘッダやフッタとして使うテンプレートは異なるが、断片的な内容は同じである場合、コードを重複して書くことを避けるため、部分テンプレートを使う。

# vi ./app/views/first/index.html.erb
<div id='main'>
<%= render :partial => 'first/partial_form %>
</div>
:partialはなくてもよい

# vi ./app/views/first/_partial_form.html.erb
<div id='sub'>
<%= @msg %>
</div>

部分テンプレートファイル名の前につく'_'は必須である。これが部分テンプレートの宣言になる。



さて、話を戻そう。
モデルクラスの作成
モデルクラスを作成する。
SQLなどのデータベースでのリレーショナルモデルをアプリケーション側のオブジェクトモデルにO/R(Object/Relational)マッパーで橋渡しを行うことが目的である。

bookapp_developmentデータベースは既に作り終えている。

ある製品を管理するテーブルを作る。
実体属性は次とする。主キー属性に別色をつけている。

products
id name price sale

SQL的に表現すれば、products(製品群)テーブルにid、name(製品名)、price(価格)、sale(仕入れ日)のカラムがある。実際に製品を管理するには不十分な内容だが練習なのでこの程度でよしとしている。

では、モデルクラスを作る。
主キーとなるID、レコードの新規作成時用のcreated_at、レコードの更新日時のupdated_atは自動で作成されるためコマンド内に含める必要はない。

# rails generate model product name:string price:integer sale:date 

以下のファイルができる。
db/migrate/20111113031409_create_products.rb
app/models/product.rb
test/unit/product_test.rb
test/fixtures/products.yml


モデルとその関係ファイルを破棄する手順も残しておく。
# rails destroy model product



マイグレーションファイルによるテーブルの作成
"db/migrate/20111113031409_create_products.rb"というファイルを元にマイグレーションという機能を利用してテーブルを作成する。productsというテーブルができる。テーブル名が複数形なのは、テーブルの各行(モデルクラス的に表現すればオブジェクト)は
単数であり、テーブルはその集合だからである。複数形にするのはテーブルだけである。

# rails db:migrate RAILS_ENV=development
別のデータベースを使う場合はオプションを変更する。

RAILS_ENV=test
RAILS_ENV=production



テストデータの流し込み
テーブル内は空なので、"test/fixtures/products.yml"という自動で作成されるフィックスチャを元にテストデータを流し込んでおく。中を見ればわかるが2つの行(2つのオブジェクト)が投入される。流し入れるデータを変えたければymlファイルを編集すればよい。

# rails db:fixtures:load FIXTURES=products RAILS_ENV=development


フィックスチャ以外にも、シードファイルを使ってデータを入れることもできる。
# vi ./db/seeds.rb
Product.create(:name  => 'MyString3', :price => 3, :sale => '2011-11-11 09:00:00')

# rails db:seed



コントローラとビューの再作成
モデルも作ったのでそれを利用したコントローラとビューを作成する。
# vi app/controllers/first_controller.rb
class FirstController < ApplicationController
  def show
    @products = Product.all
  end
end


# vi app/views/first/show.html.erb
<table border="1">
  <tr>
    <th>NAME</th><th>PRICE</th><th>SALE</th>
  </tr>
<% @products.each do |product| %>
  <tr>
    <td><%= product.name %></td>
    <td><%= product.price %></td>
    <td><%= product.sale %></td>
  </tr>
<% end %>
</table>



サービス確認
ビューで定義したテーブルが表示できれば成功である。
http://x.x.x.x/first/show



Next ⇒ Railsを使ったアプリケーション開発 (その3 応用編)

2011年11月13日日曜日

Railsを使ったアプリケーション開発 (その1 事前準備編)

Rails4を利用して書籍を管理するアプリケーションを作ることを目的とする。


Ruby on Railsのインストール

# yum install ruby ruby-devel
# gem install rails



Apacheのインストール
# yum install httpd httpd-devel



SQLのインストール
● SQLliteを使う場合(今回は利用しない。インストールだけ)
# yum install sqlite sqlite-devel

● MySQLを使う場合

# yum install mysql mysql-server mysql-devel



バージョン確認

# ruby -v

# rails -v

# httpd -v

# sqlite3 -version

# mysql --version



Apacheの設定

Apacheに組み込むRailsアプリケーション実行モジュール(Passenger)をインストールしておく。

● Passengerのインストール

# gem install passenger

● Apacheモジュールとしてインクルード

# passenger-install-apache2-module

インクルードが成功するとApacheの設定ファイルに記載するコードが表示される。

LoadModule passenger_module /usr/local/share/gems/gems/passenger-5.0.7/buildout/apache2/mod_passenger.so
<IfModule mod_passenger.c>
  PassengerRoot /usr/local/share/gems/gems/passenger-5.0.7
  PassengerDefaultRuby /usr/bin/ruby
</IfModule>


<VirtualHost *:80>
   ServerName www.yourhost.com
   # !!! Be sure to point DocumentRoot to 'public'!
   DocumentRoot /somewhere/public
   <Directory /somewhere/public>
      # This relaxes Apache security settings.
      AllowOverride all
      # MultiViews must be turned off.
      Options -MultiViews
      # Uncomment this if you're on Apache >= 2.4:
      #Require all granted
   </Directory>
</VirtualHost>


● Apacheの設定

# vi /etc/httpd/conf.d/passenger.conf

# LoadModule、PassengerRoot、PassengerRubyは上記をそのままコピーする。

LoadModule passenger_module /usr/local/share/gems/gems/passenger-5.0.7/buildout/apache2/mod_passenger.so
<IfModule mod_passenger.c>
  PassengerRoot /usr/local/share/gems/gems/passenger-5.0.7
  PassengerDefaultRuby /usr/bin/ruby
</IfModule>


# 任意だがPassengerが追加するHTTPヘッダを削除するための設定をいててもよい。

Header always unset "X-Powered-By"
Header always unset "X-Rack-Cache"
Header always unset "X-Content-Digest"
Header always unset "X-Runtime"

# こちらも任意だが必要に応じてPassengerのチューニングのための設定を追加しておく。

# ※詳しくは Phusion Passenger users guide
PassengerMaxPoolSize 20
PassengerMaxInstancesPerApp 4
PassengerPoolIdleTime 3600
PassengerHighPerformance on
PassengerStatThrottleRate 10
PassengerSpawnMethod smart
RailsAppSpawnerIdleTime 86400
PassengerMaxPreloaderIdleTime 0

DocumentRootの指定先フォルダは後程作成する(そのためまだhttpdは起動しない)。

RailsEnvはdevelopment(開発)、test(試験)、production(本番)を指定できる。Railsの環境は3つを使い分けられるが、さしあたりdevelopmentでいいだろう。

RailsEnv development

<VirtualHost 192.0.2.1:80>
   ServerName bookapp.example.com
   DocumentRoot "/var/www/rails/bookapp/public"
   <Directory /var/www/rails/bookapp/public>
      AllowOverride all
      Options -MultiViews
   </Directory>
</VirtualHost>



アプリケーションの作成

書籍を管理するアプリケーションを作成していくとは述べたとおりである。
/var/www/rails/配下に、bookappというアプリケーションを新規に作成する。

mysqldをここで立ち上げておく。

# systemctl restart mysqld.service
# mysqladmin -u root password "***"

DocumentRootで指定したディレクトリを作成する。

# mkdir -p /var/www/rails/

Passengerはroot権限でRailsアプリケーションを動かせない仕様になっているので、
オーナーを変更しておく。
# chown -R apache.apache /var/www/rails/

# cd /var/www/rails/

ディフォルトで利用するSQLはsqliteなのだが、今回はmysqlを利用することにしよう。
そのため'-d'オプションでmysqlを付与している。
# rails new bookapp -d mysql

# cd bookapp

dbアクセス用のパスワードを記載するぐらいで、ディフォルトで使える。

# vi ./config/database.yml
〜snip〜
username: root
password: ***
〜snip〜

database.ymlファイルに基づいてデータベースを作成する。development、test、production用の3つができるはずである。どのデータベースを使うかは先に書いた通り、passenger.confのRailsEnvで指定する。
# rails db:create

個別に指定もできる。

# rails db:create RAILS_ENV=production
createをdropにするとデータベースを削除できる。

dbをのぞいて見る。

# rails dbconsole

これは下と同じである。

# mysql -u root

> show databases;
+---------------------+
| Database            |
+---------------------+
| bookapp_development |
| bookapp_test        |
| bookapp_production  |
+---------------------+

確かにできている。



(補足1)

今回作成するのアプリケーションで必要となるgemは同フォルダのGemfileで定義されている。bundlerと呼ばれるアプリケーションごとのパッケージ管理システムにより、アプリケーションごとにgemを管理できる。

パッケージ管理の一般的な利用例をまず見てみる。
$ vi test.rb
require 'hogepiyo'

$ vi Gemfile
source 'https://rubygems.org'
gem 'hogepiyo'

$ bundle install --path=vendor/bundle

$ ls vendor/bundle/ruby/gems/hogepiyo-x.x.x/

Gemfileを修正した場合は、bundleコマンドで読み直しさせること。
$ bundle update

実行する。
$ bundle exec ruby test.rb

イメージがついただろう。
アプリケーションを実行するrailsのバージョンを指定することもできる。
$ vi Gemfile
gem 'rails', '3,2,13'



◆ 確認

httpdを起動させる。
# systemctl restart httpd.service

ブラウザからアクセスして確認する。

http://x.x.x.x/
DocumentRootで指定した、/var/www/rails/bookapp/public 配下のindex.htmlが読み込まれる。

"Welcome aboard" と出ていれば成功である。
"About your application's environment" をクリックしアプリケーション環境に問題ないかも確認しておこう。



ここからコントローラ、ビュー、モデルと作成していくのだが、それはまた次回の

Railsを使ったアプリケーション開発 (その2 基礎編)で。