Skip to content

Instantly share code, notes, and snippets.

@hakatashi hakatashi/sig-web-04.md
Last active Jun 8, 2016

Embed
What would you like to do?

TSG 第4回Web分科会 カンペ

簡単なRailsアプリケーションを制作し、MVCモデルによる高度なウェブアプリケーションの仕組みを学ぶ。

RubyとRailsのインストール

Windows

RailsInstallerがオススメ。Ruby 2.2版がよさそう。

インストールしたらコマンドプロンプトで rails --version と打ち込んで、

Rails 4.2.5.1

みたいなのが表示されれば成功。

「'rails' は、内部コマンドまたは~として認識されていません。」とか言われる場合

インストール直後はPATHが通ってないのでrailsコマンドを呼び出せない。

再起動するか、以下のコマンドを打ち込む。

set PATH=C:\RailsInstaller\Ruby2.2.0\bin;%PATH%

「指定されたパスが見つかりません。」とか「The system cannot find the path specified.」とか言われる場合

最新版のRailsInstallerはどうもrailsコマンド諸々が壊れているらしい。(ひどい)

直すには、このファイルをダウンロードし、ZIPの中の「~.bat」というファイルを全部 C:\RailsInstaller\Ruby2.2.0\bin\ に上書きコピーする。

OS X

Ruby + Ruby on Rails4 開発環境の準備【Mac OSX Yosemite, Mavericks, MountaiLion 対応】

たぶんここに書いてあるHomebrewとrbenvを使う方法が簡単でのちのち便利そう。

RailsInstallerの OS X 版もあるけど、ちゃんと動くのかどうかは知らない。

ターミナルで rails --version と打ち込んでバージョンが表示されれば成功。

Linux

  1. rbenvをインストール
  2. ruby-buildをインストール
  3. rbenv install 2.2.5
  4. gem install rails
  5. ターミナルで rails --version と打ち込んでバージョンが表示されれば成功。

Rubyとは

東大の情報の授業で学ぶプログラミング言語。みんな完璧にマスターしてるよね? 日本人が作った中でおそらく世界中で最も広く使われているであろうソフトウェア。PerlやPythonの強力な後押しを得て、満を持して世に送り出された。以下の様な特徴がある。

  • 厳密かつ完全なオブジェクト指向
  • 表現の多様性
  • gemという強力な標準パッケージマネージャー

Ruby on Rails というヘヴィーオブジェクトが誕生したことにより世界中のウェブサーバーで動くプログラミング言語になってしまった。

プログラミング言語としての基礎的な記法は以下のとおり。

  • インデントは慣習的にスペース2つ。

  • セミコロンは不要。付けることもできるが普通は付けない。

  • 基本的な構文はカッコなしで書けるが、かわりに end というキーワードで閉じる必要がある。end地獄とも呼ばれる。

    if 1 == 2
      puts 'What?'
    end
    
    for i in 1..10
      puts i
    end
  • Rubyの全てはオブジェクトであり、メソッドの呼び出しを使って簡潔な記述ができる。例えば、「"hoge"を大文字にして前後をひっくり返して最後の文字を切り取った文字列」を求めるプログラムは次のように書ける。

    'hoge'.upcase.reverse.chop
  • 関数呼び出しの括弧は省略することができる。この書き方は可読性を失うとして避けられる場合も多い。

    puts(rand(10.gcd(15)))
    puts rand 10.gcd 15
  • 一部メソッドは do |a, b| ~ end もしくは {|a, b| ~} によって表されるブロックという引数をとることができる。これは「任意の処理」を表現するコードを受け渡したい時に使われる。

    10.times do |i|
      puts i
    end
    
    10.times {|i| puts i}
    
    0.upto(9) do |i|
      puts i
    end
  • 文字列とキーワードの中間の特徴を持つ、シンボルというリテラルが存在する。(語弊があるが)グローバルに使えるenumとでも思えばよい。連想配列のキーや種類が限定られる引数などに使用される。

    hash = {
      :hoge => 'fuga'
    }
    
    # 同じ意味
    hash = {
      hoge: 'fuga'
    }
    
    p hash[:hoge] #=> 'fuga'

不安な人はこのあたりを読むとよさそう。

Ruby on Rails とは

Rubyのメタプログラミングの柔軟性とMVCモデルという武器により世界中に瞬く間に広まった、ウェブアプリケーション・フレームワーク。今やRubyの用途の半分以上は Ruby on Rails であるとも言われる。Railsと略す。

小さなブログから大規模なSNSまで、かなり実用的なウェブサイトが構築できる。例えば以下のサイトはRailsで構築されている。

参考: 国内注目のWebサービスを支える言語・フレームワーク・アーキテクチャ一覧【2013年版】, あなたにも作れる!Ruby on Railsで作られたWebサービス5選!, 37 Sites You LOVE Built With Ruby On Rails

ウェブアプリケーション・フレームワークとは

あらかじめ定められた作法に従ってプログラムを記述することによって、ウェブアプリケーションの制作を簡単かつ構造的に行うことができるプログラムの枠組みのこと。

ウェブアプリケーション・フレームワークの例:

  • Ruby on Rails (Ruby)
  • Sinatra (Ruby)
  • CakePHP (PHP)
  • Zend (PHP)
  • Django (Python)
  • Angular.js (JavaScript)
  • React (JavaScript)
  • TreeFrog (C++)

ウェブアプリケーション・フレームワークは、アプリケーションの組み立て方によってある特定のデザインパターンに分類されることが多い。

デザインパターンの例:

  • MVC
  • MVVM
  • Flux
  • Redux

気をつけておきたいのは、このようなフレームワークを用いたアプリケーションでは、PHPなどのCGIや静的ウェブサイトと異なり、URLがファイルに対応しないことである。第1回Web分科会で解説したとおり、ウェブサーバーの本質とはブラウザが送信したHTTPリクエストに対して何かしらの応答(普通はHTML)を返すというものである。(語弊があるが)URLはHTTPリクエストに含まれるため、アクセスされたURLに対応するファイルが必ずしもディスク上に存在する必要はない。

ウェブアプリケーションは入力されたHTTPリクエストに対してHTMLを出力する関数である、と考えたほうがよい。前回前々回のPHPを用いた実習では、プログラムがCGI上で動いていたため上手いことそのあたりが隠匿されていたが、この辺りを理解していないとRailsではつまづくので注意が必要である。

MVCとは

Ruby on Rails が採用しているデザインパターン。Model-View-Controller の略。その名の通り、ModelとViewとControllerという3種類の要素でアプリケーションを構成する。

以下では特にRailsにおけるMVCについて解説する。

  • Model: アプリケーションが扱う「モノ」や「コト」と、それに対する操作を表現したもの。典型的な設計ではデータベースのテーブルと同じ数だけ存在する。
  • Controller: 入力(HTTPリクエスト)を受け取り、それに対して必要な操作をModelを通して実行し、その結果をViewに渡す。
  • View: Controllerから渡された結果をもとに出力(HTML)を生成する。

文章でわかるわけがないので、先人が作ったイラストをいくつか参照する。

もう少し詳しく書くとこんな感じになると思う。

このようにMVCモデルではModelとViewとControllerが同列に描かれることが多いが、ことRailsにおけるModelは明らかにViewやControllerとレイヤーが異なる。Modelはデータベースにおけるテーブルをラッピングし、それに付随する操作やビジネスロジックを内包した抽象的なクラスとそのインスタンスであり、「ブラウザ→Controller→View→ブラウザ」というデータの流れとは一線を画している。Modelの操作はControllerから行うのが望ましいためControllerから矢印が引かれるが、アプリケーションの一部として他とは独立した概念なので、実はアプリケーションのどこからでも利用することができる。

Modelがデータベースを扱う仕組みについては次回「ActiveRecord編」で詳しく話すため、今回は主にControllerとViewについてのみ扱う。

Railsで Hello, World!

まずはアプリケーションの / (ルートパス)にアクセスしたら “Hello, World!” と表示するプログラムを作る。

ターミナルから適当なフォルダに行き、

rails new hello

と打ち込むとそこに hello というフォルダが作られ、その下に特に何もない空っぽのRailsアプリケーションが生成される。appディレクトリの下にmodelとかviewとかcontrollerみたいなディレクトリがあるのがわかる。

この状態でもう起動することができる。まずはサーバー起動してアクセスしてみる。

cd hello
rails server

デフォルトだとlocalhostの3000番ポートにRailsサーバーが立ち上がる。ブラウザから http://localhost:3000/ にアクセスすると、Welcome aboard とかそんなことが書かれたページが現れると思う。

この時点で何か間違えても戻すことができるようにGitリポジトリにしておくことをおすすめする。

git init
git add --all
git commit -m "Initial commit"

まずはHelloという名前のControllerを作ってみる。

rails generate controller Hello

これによりHelloという空っぽのControllerとそれに付随するいろいろなものが一気に生成される。

Controller本体は app/controllers/hello_controller.rb に置いてある。これを開いて、以下のように編集する。

class HelloController < ApplicationController
  def show
    @message = 'Hello, World!'
  end
end

次にこのControllerからデータを渡されるViewを作成する。app/views/hello/show.html.erb というテキストファイルを作成し、次のように記述する。

<h1><%= @message %></h1>

ERBはテンプレートエンジンの1つである。PHPと似たようなものだと思ってよい。

最後に / からこのHelloというControllerにアクセスが届くようにルーターの設定を変更する。config/routes.rb を開く。

コメントが大量に書いてあるが、正直いらないのでごそっと削除して以下のように書く。

Rails.application.routes.draw do
  root 'hello#show'
end

これで「ブラウザ→routes.rb→Controller→View→ブラウザ」という一連のデータの流れが完成した。再びRailsサーバーを起動する。

(サーバーを伴うウェブアプリケーションは普通CGIと異なりアクセスごとにプログラムファイルの内容を読みこんだりしないので、プログラムを変更したら再起動する必要がある。ただしRailsのControllerやViewの場合は例外)

rails server

http://localhost:3000 にアクセスし、「Hello, World!」と表示されたら成功。

実習課題

前々回のPHP実習と同じく、Rubyの練習も兼ねて日付から曜日を計算するサイトを作ろう。

まずはHelloコントローラーにshow_daysとcalc_daysというメソッドを作る。(これは設計上非常に良くないが今回は実習なので仕方なし)

class HelloController < ApplicationController
  def show
    @message = 'Hello, World!'
  end

  def show_days
    render action: 'days'
  end

  def calc_days
    @year = params[:year].to_i
    @month = params[:month].to_i
    @day = params[:day].to_i

    # ここに何か書く

    @day_in_week = 'hoge曜日'
    render action: 'days'
  end
end

次に app/views/hello/days.html.erb というテキストファイルを作成し、次のように書く。

<h1>曜日計算機</h1>

<% unless @day_in_week.nil? %>
    <p>
        <%= @year %><%= @month %><%= @day %>日は<%= @day_in_week %>です。
    </p>
<% end %>

<p>日付を入力してください</p>

<%= form_tag do %>
    <%= hidden_field_tag :authenticity_token, form_authenticity_token %>
    <%= text_field_tag :year %><%= text_field_tag :month %><%= text_field_tag :day %><%= submit_tag '送信' %>
<% end %>

最後に config/routes.rb を次のように変更する。

Rails.application.routes.draw do
  root 'hello#show'

  get '/days', to: 'hello#show_days'
  post '/days', to: 'hello#calc_days'
end

Railsを再起動して、 http://localhost:3000/days にアクセスする。「曜日計算機」なる画面が表示されたらOK。

gemについて特に説明してないが、好きなgemを使って良い。

ヒント

  • 以降はおそらくControllerもしくはViewの変更になると思うので、Railsを再起動する必要はない。
  • 曜日はどうやって計算してもいい。
    • ツェラーの公式 - Wikipedia
    • Rubyにはdateという標準ライブラリが存在する。これはソースコードの先頭に require 'date' と書くと使えるようになる。

余力があったら

  • 数字以外が入力された場合の処理を書く
    • 小数の場合……
    • 存在しない日付の場合……
  • 干支を計算する
  • 星座を計算する
    • ついでに占っちゃう
  • 六曜を計算する
  • イスラム暦対応
  • その日から今日までの日数を計算する
  • CSSで見た目を改善する
  • その月のカレンダーを表示する
    • HTMLの<table>とか使ったらいいと思う

参考: Rubyで和暦・旧暦を扱うライブラリ (パースもできるよ!) - Qiita

実装例

class HelloController < ApplicationController
  def show
    @message = 'Hello, World!'
  end

  def show_days
    render action: 'days'
  end

  def calc_days
    @year = params[:year].to_i
    @month = params[:month].to_i
    @day = params[:day].to_i

    date = Date.new @year, @month, @day
    days = %w{日 月 火 水 木 金 土}
    dayname = days[date.cwday % 7]

    @day_in_week = "#{dayname}曜日"
    render action: 'days'
  end
end

次回予告

次回もRails。

  • ActiveRecord
  • Gem
  • Bundler
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.