Rubyの最も人気のあるアプリケーションであるRuby on Railsを取り上げようと思い、書き始めました。 予想してはいましたが、相当な分量になってしまいました。 そのため、何回かに分けて記事にすることにします。 また、対象となる読者のレベルをどうしようかと考えましたが、「徒然Ruby」が基礎的な内容から始まったことに鑑み、初心者レベルから始めることにしました。 Railsを仕事で使っているような方には面白くないかもしれませんが、ご容赦ください。
ドキュメント
定番のドキュメントを3つ挙げておきます。
- Rails Guide。日本語版もあります=>Railsガイド
- API reference
- Ruby on Rails チュートリアル=>最新版は有料。 第4版は無料だが、扱っているRailsのバージョンは5.1で古い。 (現時点でのRailsの最新版は7.0.4)
「Rails Guide」「API reference」「ソースコード」を理解すれば完璧ですが、初心者には難しいかと思います。 「Railsチュートリアル」(無料でもよい)から始めるか、または「Railsガイド」の第1章から読み始めると良いと思います。
インストール
RailsはRubyのgemです。 gemコマンドでインストールできます。
$ gem install rails
RailsではSqlite3データベースが標準です。 あらかじめインストールしておきます。 また、gitを使うので未インストールの場合はここでインストールしておいてください。
$ sudo apt install sqlite3 git
wordbookのRails版
本記事でRailsの例として作ろうと考えているのは、minitestのところで作った単語帳アプリwordbookのRails版です。 ただし、ウェブでの一般公開ではなく、ローカル(自分のPC)での使用を考えています。
wordbookはReadlineを使ったCUI(Character User Interface: 文字ベースのユーザ・インターフェース)でした。 これをGUI(Graphical User Interface: グラフィック画面ベースのユーザ・インターフェース)にしたいのですが、RubyのGUIはまだ定番がありません。 そこで、ウェブ・ブラウザ上のGUIを利用してwordbookを動かそうというのが狙いです。
newコマンド
Railsのnewコマンドは、ウェブ・アプリ開発に必要な材料を揃えてくれます。
$ rails new word_book_rails create create README.md create Rakefile ... ... ... ... ... ... run git init from "." Initialized empty Git repository in /ユーザディレクトリ・・・/word_book_rails/.git/ create app create app/assets/config/manifest.js ... ... ... ... ... ... run bundle install Fetching gem metadata from https://rubygems.org/........... Resolving dependencies....... Using rake 13.0.6 ... ... ... ... ... ... Bundle complete! 15 Gemfile dependencies, 72 gems now installed. ... ... ... ... ... ... $ ls Gemfile Gemfile.lock README.md Rakefile app bin config config.ru db lib log public storage test tmp vendor
newコマンドは沢山の仕事をします。
- word_book_railsというディレクトリを作成し、様々なファイルをそのディレクトリ以下に作成する
git init
によってそのディレクトリでgitが使えるよう初期化する- Gemfileを作成し、bundlerを起動して必要なgemをインストールする
- その他必要なことを行う
ディレクトリをリスティングすると様々なファイルとフォルダ(フォルダとディレクトリは同じ。Railsでは「フォルダ」ということが多い)が作成されています。
この段階でテンプレートのウェブを表示することができます。
$ bundle exec rails server => Booting Puma => Rails 7.0.4 application starting in development => Run `bin/rails server --help` for more startup options Puma starting in single mode... * Puma version: 5.6.5 (ruby 3.1.2-p20) ("Birdie's Version") * Min threads: 5 * Max threads: 5 * Environment: development * PID: 5144 * Listening on http://127.0.0.1:3000 * Listening on http://[::1]:3000 Use Ctrl-C to stop
「rails server」はローカルでサーバーを立ち上げるコマンドです。
このフォルダではbundlerでgemがインストールされているので、プログラムの起動には常に「bundle exec」をつけます。
「rails server」の短縮形「rails s」でも動作は同じです。
ローカル・ホストのポート3000(http://localhost:3000/
)をブラウザで見ると、テンプレートのウェブを見ることができます。
サーバを終了するには、コマンドラインから「CTRL-C」を入力します。
ここまでやったことがどういう意味を持つのかを次のセクションで説明しましょう。
ウェブサーバとクライアント
インターネットでは「サーバ」に対して「クライアント」という言葉を使います。 もしあなたがインターネットでウェブを見ているとしたら、そのあなたのPCがクライアントです。 また、ネット上のコンピュータは「ホスト」とも呼ばれます。
ネット上のサーバとクライアントを詳しく見ると、通信をしているのは、サーバコンピュータ内の「ウェブサーバーアプリ」とクライアントコンピュータ内の「ブラウザ」です。 コンピュータ同士ではなく、コンピュータ内のアプリケーション同士が繋がっていることに注意してください。
それに対して、前のセクションではRailsとブラウザがひとつのPC内にネットワークを作って接続されていました。
図では「puma」と「rails」がサーバ側でセットになっています。 pumaはサーバ機能を提供するアプリケーションです。 ひとつのコンピュータの中でサーバとクライアントが動いていて、ちょうどインターネット接続のようなことが行われています。
ひとつのPC内にネットワークを作ることに意味はあるのでしょうか?
アプリケーション作成においては多少の意味があります。 一般にアプリケーションにGUIインターフェースを持たせるのはかなり大変です。 特にRubyの場合はこれといったGUIの決定版がありません。 それに対するひとつの答えがブラウザのGUIを利用することです。 もちろんこれがベストだとは思いませんが、選択肢のひとつだとは思います。
もっと重要なのは、ウェブサービスアプリのテストを行えるということです。 これがローカルでサーバとブラウザを使う最大の意義だと思います。
さて、具体例に戻りましょう。
ブラウザが「http://localhost:3000
」にアクセスしました。
「localhost」はIPアドレスでは「127.0.0.0」で、そのPC自身を表します。
localhostの「ローカル」は自分(の場所)「ホスト」はPCのことです。
したがって、「ローカルホスト」は自分のPCのことを指しているわけです。
「3000」はポート番号を表します。 ポートとは、サーバ内の様々なサーバーアプリケーションに割り当てられる番号です。 この割当は、ある程度決まったものがあります。 そのごく一部を表にしました。
ポート番号 | サービス | 意味 |
---|---|---|
80 | HTTP | ウェブサービス |
21 | FTP | ファイル転送 |
110 | POP3 | メールサーバとクライアント通信 |
443 | HTTPS | 暗号化されたウェブサービス |
これらは、システムポート番号(0から1023まで)に属するポートです。
これに対して1024から49151はユーザポート番号といいます。 この範囲でも公式または非公式に決まった使い方があります。 3000はRuby on Railsの開発用ポート(非公式)ですが、他の用途に用いられることもあります。 49152から65535は決まった割当のない「動的・私的ポート番号」になっています。 (ウィキペディア「ポート(コンピュータ・ネットワーク」より)
http://localhost:3000
は自分のPCのrailsの提供するサービスを指しています。
ブラウザがそこをアクセスするとrailsとpumaがウェブ画面のデータを送ってきて、それが表示されたわけです。
ルーティング、コントローラ、ビュー
ルーティング
bundle exec rails serve
によってhttp://localhost:3000
はword_book_rails
以下のディレクトリに作られたrailsのウェブアプリケーションに割り当てられました。
同様にhttp://localhost:3000/abc.html
も同じウェブアプリケーションに対するリクエストになります。
このアドレスを2つの部分に分けて
http://localhost:3000
の部分はシステムによって(pumaと)railsのウェブアプリケーションに処理が任される/abc.html
の部分はrails内部でどのように処理するかを決める
このうち2番めの処理は、ルーティング、コントローラ、ビューに分かれます。
- ルーティングは「
abc.html
のようなアドレスの下位の部分」に対応する「コントローラ」へ処理を移す - コントローラは様々な処理の調整を行う
- ビューはブラウザに送るHTMLを組み立てる
ルーティングは/config/routes.rb
で設定します。
初期状態では設定は空の状態になっています。
Rails.application.routes.draw do # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html # Defines the root path route ("/") # root "articles#index" end
ルーティングはdoとendの間のブロック部分に書きます。
例えば、root
(これは/
と同じで、アドレスでhttp://localhost:3000/
に相当する)に対してWordsコントローラのindexアクションに対応させるには、
root "words#index"
と書きます。
また、/abc.html
に対してAbcコントローラのindexアクションに対応させるには、
get "/abc.html", to: "abc#index"
と書きます。
getはHTTPプロトコルのリクエスト・メソッドです。 HTTPはウェブサーバとクライアント(ブラウザ)が通信するためのプロトコル(手続き方法)です。 HTTPではクライアントがリクエストを送り、サーバがそれに応答するというパターンで通信が進みます。 このリクエストでよく使われるのがgetとpostというメソッドです。
- getはサーバのリソース(HTML文書など)を送れ、というリクエスト
- postはサーバへクライアントからデータを送るリクエスト。 例えば、テキストを書いたりチェックボックスを選択したりしたデータをサブミット(送信)ボタンをクリックして送るような場合
ルーティングの詳細はまた別の記事で説明します。
コントローラ
コントローラはデータの種類ごとにひとつずつ作ります。 例えばブログサービスのrailsアプリでは、ユーザ管理のコントローラUsers、記事管理のコントローラArticlesなどがあります。
今回作る単語帳は単語のコントローラWordsのみで十分です。 コントローラを作るにはrailsのgenerateコマンドが便利です。
$ bundle exec rails generate controller Words create app/controllers/words_controller.rb invoke erb create app/views/words invoke test_unit create test/controllers/words_controller_test.rb invoke helper create app/helpers/words_helper.rb invoke test_unit $
コントローラは大文字で書きはじめ、通常複数形にします。 複数形にする理由は、単語1個のデータだけでなく、複数の単語を扱うからです。 コントローラ名が2語以上からなる場合はキャメルケース(例えばWordBooks)を使います。
app/controllers/word_controller.rb
が、さきほど生成されたコントローラのファイルなので見てみましょう。
class WordsController < ApplicationController end
コントローラは、Ruby言語のクラス定義に相当します。 この中にインスタンスメソッドを定義して、コントローラの動作を記述します。 Railsではこのインスタンスメソッドを、コントローラの「アクション」と呼びます。
本格的にコントローラを書くのは後の記事になります。 ここでは、indexというアクションを書いてみましょう。
class WordsController < ApplicationController def index end end
空のメソッドindexを定義しました。
ルーティング(config/routes.rb)を次のように設定しましょう。
Rails.application.routes.draw do # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html # Defines the root path route ("/") # root "articles#index" root "words#index" end
コメント部分は取り去っても構いません。
これでhttp://localhost:3000
またはhttp://localhost:3000/
(末尾にスラッシュがある)はWordsコントローラのindexアクションにルーティングされます。
これを"words#index"と書きます。
ビュー
コントローラで特にHTMLを書き出す記述がなければ、対応するビューが呼ばれHTMLを出力します。
"words#index"のアクションに対応するビューはapp/views/words/index.html.erb
です。
このファイルはまだ作成されていません。
次のような内容で作成しましょう。
Hello, world.
これでブラウザ画面に「Hello, world.」が表示されるはずです。
読者の中には「HTMLデータにしては、ヘッダもボディタグもなくておかしいな」と思った方がいらっしゃるのではないでしょうか。
実は、このファイルはレイアウトファイルの中に埋め込まれるパーツなのです。
レイアウトファイルはapp/views/layouts/application.html.erb
と決まっています。
このファイルを見てみましょう。
<!DOCTYPE html> <html> <head> <title>WordBookRails</title> <meta name="viewport" content="width=device-width,initial-scale=1"> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> <%= javascript_importmap_tags %> </head> <body> <%= yield %> </body> </html>
このファイルの<% ... ... %>
と<%= ... ... %>
の部分はRubyコードの埋め込みです。
それ以外はHTML文書になっています。
<% ... ... %>
は単なるRubyコードの記述<%= ... ... %>
はRubyコードを実行した値をHTMLに埋め込む。 例えば、<%= 1+2 %>
は文字列の3をその部分に埋め込む。 ブラウザで表示すると、その部分に3が表示される
Rubyの埋め込みは全部で5つありますが、そのうちのはじめの4つの内容説明は省略します。
最後の<%= yield %>
の部分にapp/views/words/index.html.erb
の内容が埋め込まれます。
先程作ったファイルの場合は「Hello, world」が埋め込まれることになります。
動作確認
3つのファイルを変更、作成しました。
config/routes.rb
app/controllers/word_controller.rb
app/views/words/index.html.erb
これをテストしてみましょう。
$ bundle exec rails server
ブラウザでhttp://localhost:3000
を見てみましょう。
今度は左上に「Hello, world.」が表示されているはずです。
- ルーティング
- コントローラ
- ビュー
の順に処理がつながっていきます。 このことをまず理解してください。 今回は以上です。