Shimane2008

Preview:

DESCRIPTION

Presentation of a seminar in Shimane Univ.

Citation preview

Ruby on RailsによるWebアプリケーション開発

島根大学2008-12-12

大場寧子株式会社万葉

大場光一郎伊藤忠テクノソリューションズ株式会社

1

自己紹介

•大場寧子•大場光一郎

2

RoR逆引きクイックリファレンス

•大場寧子•大場光一郎•久保優子

毎日コミュニケーションズ

3

今日の課題•掲示板システムの開発•TDD(テスト駆動開発)•Scaffoldを使わない•RESTful

4

必要な作業•プロジェクトの作成•データベースの作成•テストの書き方を覚える•モデル(掲示板記事)の実装

5

bbsプロジェクトの作成

•デフォルトではデータベースとしてsqlite3が選択される。-dオプションでmysqlを指定する

> rails -d mysql bbs

6

データベースを作る

> rake db:create

•※mysqladmin でbbs_developmentを作るのと同じ

•Rails 2.0 で追加された便利なタスク

7

要件を考える

•一種類だけの掲示板•上部に投稿フォーム•ポストした記事が新しい順に表示される

•指定した記事を削除できる

入力欄

投稿

8

モデル設計入力欄

投稿 記事(Entry)

•投稿者の名前•投稿日時•本文

9

モデルの作成(1)generateスクリプトでモデル、ユニットテスト、マイグレーションを作成(2)マイグレーションを実行

10

generateコマンドでモデルを作成する

モデルクラス、テストファイル、マイグレーションファイルが作成される

> ruby script/generate model Entry user_name:string body:text

11

マイグレーションとは

•データベースへの変更を、変更のたびにRubyコードで記述して保存しておく

•開発者全員で共有できる12

生成されたマイグレーションdb/migrate/20081212XXXXXX_create_entries.rb

class CreateEntries < ActiveRecord::Migration def self.up create_table :entries do |t| t.string user_name t.text body t.timestamps end end

def self.down drop_table :entries endend

投稿者を格納するuser_nameカラム

本文を格納するbodyカラム

バージョンアップ(テーブル作成)

バージョンダウン(テーブル削除)

13

マイグレーションの実行

•バージョンを上げる> rake db:migrate

•バージョンを下げて上げる(最後のマイグレーションファイルを実行しなおす)

> rake db:migrate:redo14

モデルが作成できたので

•次は実装(コードを書く)•本当に実装するまえに、満たすべき理想の動作(仕様)をテストに書く

15

Railsのテスト•3種類のテストがある•ユニットテスト•ファンクショナルテスト•インテグレーションテスト

16

テストの実行•テストDBを作成する> rake db:create RAILS_ENV=test

•ユニットテストを実行する> rake test:units

17

テストの成功

•tests - テストメソッドの数•assertions - アサーションの数•failures - 想定と違う結果になった数•errors - エラー(例外)発生数

1 tests, 1 assertions, 0 failures, 0 errors

18

アサーション•assertする=強く断言する•あるべき動作を記述•違反したら知らせてくれる

assert foofooはtrueのはずassert_equal 3, foofooは3のはず

19

デフォルトのユニットテストコード

require 'test_helper'

class EntryTest < ActiveSupport::TestCase # Replace this with your real tests. def test_truth assert true endend

必ず成功するダミーのテストが自動生成されている

test/unit/entry_test.rb

trueは必ずtrue常にアサーションどおり

20

Entryモデルの本当のテストを書こう

•満たすべき仕様•本文が空なら検証エラーとなること

21

検証とは•モデルがデータベースに登録される前に、属性(Attribute)の値が正しいかチェックすること

•検証エラーになったら、保存されない•Railsが便利な仕組みを提供

22

検証は保存前に自動的に行われる属性の代入

検証

保存

属性の代入

失敗falseを返す

save

成功trueを返す

23

Entryの検証•本文が空のとき検証エラーとなる•body属性の中身が’’ならsaveメソッドの返り値がfalseになること

entry = Entry.new( :user_name => "太郎 ", :body => "")entry.save # ←この返り値がfalseになってほしい

24

テストを書こう

require 'test_helper'

class EntryTest < ActiveSupport::TestCase # Replace this with your real tests. def test_truth assert true endend

デフォルトのテストコードを削除する

25

テストを書こうrequire 'test_helper'

class EntryTest < ActiveSupport::TestCase def test_empty_body entry = Entry.new( :user_name => "太郎 ", :body => ""); assert_equal false, entry.save endend

追加

26

テストの失敗

まだEntryの検証を実装していないので、このテストは failure となるはず。

つまり、bodyが空文字でもデータベースに保存できてしまっている。

1 tests, 1 assertions, 1 failures, 0 errors

27

テストが通るようにモデルの検証を実装しよう•bodyが空文字(またはnil)なら検証で失敗して保存されないようにする

class Entry < ActiveRecord::Base validates_presence_of :bodyend

28

実装したらもう一度テストを実行

•成功!1 tests, 1 assertions, 0 failures, 0 errors

29

テスト駆動開発新機能のテストを書く(失敗する)

新機能を実装する

テストが成功する

30

TDDのメリット•リズミカルな開発•コードをメンテナンスしやすい•コードを変更したとき、不具合が発生していないかチェックできる

•仕様(正しい動作)を理解しやすい31

掲示板を作ろう(続き)

•モデルは用意した•コントローラとビューを作ろう

32

コントローラの設計•なにごとも設計から•コントローラの設計は、URLの設計

•掲示板システムのあるべきURLとは?

33

掲示板のURL入力フォームと記事一覧/entries/index記事の投稿/entries/create・・・このスタイルはもう古い

34

HTTPメソッド•HTTPには4つのメソッドがある•GET•POST•PUT•DELETE

35

URL+メソッドGET /entries/3

記事3を取得する

DELETE /enrteis/3

記事3を削除する

PUT /entries/3

記事3を変更する

36

RESTful•URLは「リソース」を表す•例えば「記事」がリソース•HTTPメソッドは動詞を表す•美しいURL•統一的なI/F

37

RESTfulな掲示板システム

入力フォームと記事一覧GET /entries記事の投稿POST /entries

38

コントローラ・アクションとのマッピング

•Railsでは routes.rb に指定

ActionController::Routing::Routes.draw do |map|

map.resouces :entries

end

39

map.resources :entries

意味 HTTPメソッド URL アクション

一覧 GET /entries index

登録フォーム表示 GET /entries/new new

登録 POST /entries create

IDが17の記事を表示 GET /entries/17 showIDが17の記事の変更フォーム表示 GET /entries/17/edit edit

IDが17の記事を変更 PUT /entries/17 update

IDが17の記事を削除 DELETE /entries/17 destroy

コントローラ:EntriesController

40

URLの生成•map.resourcesによって、専用のURL生成メソッドが用意される

URL URLを生成する専用メソッド

/entries entries_path

/entries/new new_entry_path

/entries/17 entry_path(entry)

/entries/17/edit edit_entry_path(entry)

link_to "掲示板はこちら", :controller => "entries", :action => "index"

link_to "掲示板はこちら", entries_path41

我々の課題では意味 HTTP

メソッド URL アクション

一覧と登録フォーム表示 GET /entries index

登録 POST /entries create

IDが17の記事を削除 DELETE /entries/17 destroy

上記の範囲だけを意識して作っていきます42

コントローラの作成

> ruby script/generate controller entries index create destroy

記事を一覧、投稿、削除するためのコントローラをアクション付きで作成します

43

演習1.index アクションと画面を実装する2.create アクションを実装する3.destroy アクションを実装する(余裕がある人のみ)

44

参考URL•Rails APIリファレンス•http://api.rubyonrails.org/•Ruby リファレンス•http://www.ruby-lang.org/ja/man/

45

あとは•自由につくってかまいません•この後のヒントを参考にしてください•講師を呼んで聞いてください•やり方がわからない•エラーが出てわからない•何が分からないのか分からない•なぜ動いているのか分からない etc...

46

ヒント47

indexアクション•データベースからEntryモデルのリスト@entriesを投稿日時の新しい順に取得

•投稿フォームのための新しいEntryオブジェクトを@entryとして用意する

48

投稿日時順の取得

@entries = Entry.find(:all, :order => "created_at desc")

検索時に、:order オプションで順序を指定する。大きい順(降順)なら desc を指定する。

49

index.html.erb(一覧&投稿画面)

•HTMLとしての体裁•上部に@entryを利用した投稿フォーム

•下部に@entriesを利用した一覧の表示

50

index.html.erb の構造の例

<html> <body>

<% form_for :entry do -%> ...... 投稿フォーム ...... <% end -%>

<% for entry in @entries do -%> ....... 1件ずつ記事を表示 ....... <% end -%>

</body></html>

51

createアクション•ユーザー名・本文をリクエストから取得

•Entryオブジェクトを作成•データベースに保存(検証失敗なら保存されない)

•index画面にリダイレクト52

削除機能•index.html.erbで、削除アクションのためのリンクを記事ごとに張っておく

•destroyアクションで指定された記事を削除して、index画面にリダイレクト

link_to "削除", entry_path(entry), :method => :delete

53

まとめ•開発手法のひとつとしてTDDがある•Railsにはテストフレームワークが含まれている

•最近のWebアプリケーションではRESTfulという考え方がある

•RailsはRESTfulを強力にサポート

54