新人SEの学習記録

14年度入社SEの学習記録用に始めたブログです。気づけば社会人3年目に突入。

学習記録:Scaffolding

[Ruby on Rails]学習記録

内容:3章 Scaffolding機能によるアプリケーション開発

Scaffolding
  • 前章ではCVMモデルの各ファイルをそれぞれ作成
  • Scaffolding
    • より手軽にCRUD(Create-Read-Update-Delete)機能を持つアプリケーションを構築
    • メンテナンスなど凝ったレイアウトを要求されないページを大量につくりたいときなどに有用
Scaffolding開発の手順
  • 一部のファイルを削除
    • rails destroy model book
    • rake db:drop
  • booksテーブルを操作する関連ファイルもまとめて生成
    • rails generate scaffold name field:type [...] [options]
$ rails generate scaffold book isbn:string title:string price:integer publish:string published:date cd:boolean
      invoke  active_record
      create    db/migrate/20140622105719_create_books.rb
      create    app/models/book.rb
      invoke    test_unit
      create      test/models/book_test.rb
      create      test/fixtures/books.yml
      invoke  resource_route
       route    resources :books
      invoke  scaffold_controller
      create    app/controllers/books_controller.rb
      invoke    erb
      create      app/views/books
...

f:id:uriku:20140622195913p:plain

    • New Bookリンクからデータを新規作成することが可能

f:id:uriku:20140622200227p:plain

indexアクション
  • /booksで呼び出すことのできるトップページ
    • books_controller.rb
    • @books = Book.all
  • テンプレートファイル

f:id:uriku:20140622200536p:plain

      • booksテーブルの中身がJSON形式で出力
  • index.html.erbテンプレート
(略)
        <td><%= link_to 'Show', book %></td>
        <td><%= link_to 'Edit', edit_book_path(book) %></td>
        <td><%= link_to 'Destroy', book, method: :delete, data: { confirm: 'Are you sure?' } %></td>
(略)
<%= link_to 'New Book', new_book_path %>
  • link_to(body, url [,html_options])
    • link_to 'Show', book: Showというリンクテキストで、urlとしてBookオブジェクトを渡す
    • 引数にオブジェクトが渡されると、オブジェクトを一意に表す数値(この場合book.id)を自動で取得
    • 結果的に/books/1のようなパスが生成される
showアクション
  • books#showアクションのコード

>|ruby|
# before_action
# show, edit, update, destroyアクションの前に必ずset_bookメソッドを実行させる
before_action :set_book, only: [:show, :edit, :update, :destroy]
# showアクション本体
# 何もしていない
def show
end
private
# set_bookメソッド
# URL経由で渡されたidパラメータの値を取得し、findで検索
def set_book
@book = Book.find(params[:id])
end
|

  • show.html.erbテンプレート
    • books#showアクションに対応するテンプレート
<p id="notice"><%= notice %></p>

<p>
  <strong>Isbn:</strong>
  <%= @book.isbn %>
</p>
...
new/createアクション
  • new.html.erbテンプレート
<h1>New book</h1>

<%= render 'form' %>

<%= link_to 'Back', books_path %>
    • formテンプレートを呼んでるだけ
    • newとeditでフォームは共通で良い(部分テンプレート
    • 部分テンプレートではファイル名の先頭に"_"が付く
  • _form.html.erb
<%= form_for(@book) do |f| %>
  <div class="field">
    <%= f.label :isbn %><br>
    <%= f.text_field :isbn %>
  </div>
...
  1. モデルに関連づいたフォームを定義
    1. form_for(model) do |f| ... end
  2. モデルのプロパティに対応した入力要素を設置
    1. f.label, f.text_field, f.date_select...
    2. form_forブロックで使用できるビューヘルパー
    3. それぞれモデルに関連づいたラベルやテキストボックスを生成する
    4. <%= f.text_field :isbn %>
    5. Bookオブジェクトを編集するフォームでisbnプロパティに対応するテキストボックスを生成
    6. 実際には
  def new
    @book = Book.new
  end
  def create
    @book = Book.new(book_params)

    respond_to do |format|
      if @book.save
        format.html { redirect_to @book, notice: 'Book was successfully created.' }
	format.json { render :show, status: :created, location: @book }
      else
        format.html { render :new }
        format.json { render json: @book.errors, status: :unprocessable_entity }
      end
    end
  end
...
  private
    def book_params
      params.require(:book).permit(:isbn, :title, :price, :publish, :published, :cd)
    end
...
    • new: フォームから入力された情報を格納するための器を作成
    • book_paramsメソッド: 入力値(ポストデータ)をまとめて取得
    • @book = Book.new(book_params):取得した入力値をモデルのコンストラクタに引き渡し
    • saveメソッド: データの保存と結果に応じた処理の分岐
      • データベース操作の結果をtrue/falseとして返す
    • 指定されたフォーマットがhtmlかjsonかで分岐
      • html: 詳細画面にリダイレクト、json: 登録結果を再描画
edit/updateアクション
  def edit
  end
...
  def update
    respond_to do |format|
      if @book.update(book_params)
        format.html { redirect_to @book, notice: 'Book was successfully updated.' }
        format.json { render :show, status: :ok, location: @book }
      else
        format.html { render :edit }
        format.json { render json: @book.errors, status: :unprocessable_entity }
      end
    end
  end
...
    def set_book
      @book = Book.find(params[:id])
    end
  1. 既存のオブジェクトを更新する
    1. update(attrs)
  2. headメソッドでヘッダのみを出力する
  • edit.html.erbテンプレートファイル
    • formテンプレートを呼び出すだけ
  • formテンプレート
    • form_forメソッドに渡されるオブジェクトの内容が空かどうかで出力内容が変わる
    • 上がnew, 下がedit
<form action="/books" class="new_book" id="new_book" method="post">
...
<form action="/books/1" class="edit_book" id="edit_book_1" method="post">
(略)
<input name="_method" type="hidden" value="patch"/>
  1. 送信先アドレスが変化
    1. 新規レコードである場合にはcreateへの、既存レコードである場合へはupdateアクションへのURLを生成
  2. HTTPメソッドの情報を追加
    1. 既存レコードの場合、_methodパラメータ(上の例ではpatch)が隠しフィールドとして渡される
    2. updateメソッドは本来HTTP PATCHで渡されるべきだが、通常のブラウザはHTTP PATCHに対応していない
    3. HTTP POSTで送信するが、実際にはHTTP PATCHとして処理するように、とRailsに伝えている