Skip to content

board_001

irisAsh edited this page Jan 14, 2018 · 2 revisions

その1- 簡単な一覧画面と詳細画面を作成する

概要

このセクションで行うことは以下である。

  • Thread モデルの作成
  • Thread のデータ一覧参照画面、データ登録画面、データ詳細参照画面の作成

Thread モデルの作成

migrate ファイルの作成

作成する Thread モデルのとりあえずの構成は以下とする。

Column Type Note
id integer スレッド ID。
title string スレッドのタイトル。
user_id integer スレッドの作成者
created_at datetime スレッドの作成日時
updated_at datetime スレッドの更新日時

以下の 通りにrails generate modelを利用して モデルを作成する。id, created_at, updated_atはモデル作成時に自動で作成されるので、 コンソールからの指定は不要である。

$ bin/rails g model board_thread title:string user_id:integer
  invoke  active_record
  create    db/migrate/20180102125048_create_board_threads.rb
  create    app/models/board_thread.rb

db/migrate/20180102125048_create_board_threads.rb の中身を 見てみると、

class CreateBoardThreads < ActiveRecord::Migration[5.1]
  def change
    create_table :board_threads do |t|
      t.string :title
      t.integer :user_id

      t.timestamps
    end
  end
end

となっている。rails generate model時にカラムの 設定を忘れた等場合、このファイルを編集すれば後からモデル構成を変えることができる。t.string :titleのようにt.型 :カラム名 の形式で編集追加を行えば良い。

migrate を実行し、DB にテーブルを作成する

作成した migrate ファイルから実際に DB にテーブルを作成する。

$ bin/rake db:migrate
== 20180102125048 CreateBoardThreads: migrating ===============================
-- create_table(:board_threads)
  -> 0.0063s
== 20180102125048 CreateBoardThreads: migrated (0.0064s) ======================

Postgresql から実際に確認する

$ psql -U postgres

postgres=# \c learnrails_develop
learnrails_development=# \d
learnrails_development=# \d board_threads

migrate を間違った場合

migrate の内容を間違えた場合は、bin/rake db:rollbackをすることでbin/rails migrateの実行前の状態に戻すことができる。
あるいは、bin/rake db:migrate:resetを実行すると DB を初期化して migrate を実行し直すことができる。

動作確認用データの作成

データ一覧参照画面を作成した時に 表示確認のためのデータを作成しておく。Postgresql から登録しても良いが、練習のためrails consoleからデータ登録してみる。

$ bin/rails c
> BoardThread.create(title: 'Rails を学ぶ', user_id: 1)
> BoardThread.create(title: 'Ruby を学ぶ', user_id: 2)
> BoardThread.all

BoardThreadモデルのcreateメソッドを利用するとデータの Insert が行える。またBoardTheadモデルのallメソッドでテーブル内の全データを select できる。

コントローラーの作成とルーティングの設定

コントローラーの作成

rails generate controllerを利用してコントローラーを作成する。同時にアクションを作成できるが、後から作成できるので指定していない。アクションを作成する場合はrails generate controller コントローラー名 アクション名 アクション名 ...とすれば作成される。 ここでは、掲示板のコントローラーをサブディレクトリに分けるためにboard::と namespace を指定しているが、必要がなければ省いて良い。

$ bin/rails g controller board::threads
  create  app/controllers/board/threads_controller.rb
  invoke  haml
  create  app/views/board/threads

ルーティングの設定

config/routes.rbを編集してルーティングを設定する。 Rails には規則として決まったアクションが存在する。以下の通りである。

action Note
index データ一覧画面
create データ作成処理
new データ作成の入力画面
edit データ更新画面
show データ詳細画面
update データ 更新処理
destroy データ削除処理

ルーティングでは必要なアクション 分のものだけを用意すればいいが、resourcesを利用すれば一度に全アクションを追加できる。試しにconfig/routes.rbに追加してみる 。

config/routes.rb

Rails.application.routes.draw do

  namespace :board do
    resources :threads
  end

end

コンソールからルーティングを確認してみると、

$ bin/rake routes
           Prefix Verb   URI Pattern                       Controller#Action
    board_threads GET    /board/threads(.:format)          board/threads#index
                  POST   /board/threads(.:format)          board/threads#create
 new_board_thread GET    /board/threads/new(.:format)      board/threads#new
edit_board_thread GET    /board/threads/:id/edit(.:format) board/threads#edit
     board_thread GET    /board/threads/:id(.:format)      board/threads#show
                  PATCH  /board/threads/:id(.:format)      board/threads#update
                  PUT    /board/threads/:id(.:format)      board/threads#update
                  DELETE /board/threads/:id(.:format)      board/threads#destroy

と全てのアクションに対してのルーティングが設定されている。

参考

このままでもよいが、ここでは個別にルーティングの設定を行うことにする。

config/routes.rb

Rails.application.routes.draw do
  namespace :board do
    get     '/threads'          => 'threads#index'
    post    '/threads'          => 'threads#create'
    get     '/threads/new'      => 'threads#new'
    get     '/threads/:id'      => 'threads#show'
  end
end

コントローラー作成時に namespace を設定しなかった場合は、namespace :board doは不要である。 ルーティング設定の順番には注意が必要である。newの ルート設定をshow の 次の行に記述すると/threads/new とブラウザから入った時に、/new/:idと認識されshowの画面が表示されてしまう。

ルーティングの確認

ルーティングが設定されたかコンソールから確認してみる。

$ bin/rake routes
           Prefix Verb URI Pattern                  Controller#Action
    board_threads GET  /board/threads(.:format)     board/threads#index
                  POST /board/threads(.:format)     board/threads#create
board_threads_new GET  /board/threads/new(.:format) board/threads#new
            board GET  /board/threads/:id(.:format) board/threads#show

アクションの作成

app/controllers/board/threads_contorller.rbにアクションを追加する。

app/controllers/board/threads_controller.rb

class Board::ThreadsController < ApplicationController

    def index
    end

    def create
    end

    def new
    end

    def show
    end
end

とりあえず追加したアクションはindex, create, new, showである。

一覧画面の作成

indexアクションを編集する。

app/controllers/board/threads_controller.rb

def index
    @threads = BoardThead.all
end

モデルの allメソッドを利用し、 全データを取得しインスタンス変数に 詰めておく。

次にビュー側を作成する。ビューは app/views/board/threads 配下にファイルを用意する。 デフォルトであれば、erb テンプレートを利用するが、今回は haml というテンプレートエンジンを利用する。

erb の場合は以下のようにファイルを作成する。

app/views/board/threads/index.html.erb

<h1>掲示板</h1>
<h2><%= link_to 'スレッドを作成する', board_threads_new_path %></h2>
<h2>スレッド一覧</h2>
<ul>
  <%= @threads.each do |thread| %>
    <li><%= link_to thread.title, board_path(thread.id) %></li>
  <% end %>
</ul>

ここでは、haml を利用するので以下のようにファイルを作成する。

app/views/board/threads/index.html.haml

%h1 掲示板
%h2= link_to 'スレッドを作成する', board_threads_new_path
%h2 スレッド一覧
%ul
  - @threads.each do |thread|
    %li= link_to thread.title, board_path(thread.id)

link_toを利用するとページへのリンクを用意できる。board_thread_new_pathとあるのは/board/threads/newの URL ことである。パスの表記は、bin/rake routesで表示されるPrefixの末尾に_pathを付与すればよい。

参考

登録画面の作成

「スレッドを 作成する」リンクからの遷移先画面を用意する。ルーティングは設定済みなのでコントローラーの用意と ビューの用意をする。

app/controllers/board/threads_controller.rb

ef create
    @thread = BoardThread.new(thread_params)
    @thread.save
    redirect_to board_threads_path
end

def new
    @thread = BoardThread.new
end

private

    def thread_params
        params.require(:board_thread).permit(:title, :user_id)
    end

データ作成処理を行うcreateアクションとデータ入力画面のnewアクションを編集する。

createについて、thread = BoardThread.new(thread_params)で入力画面からもらった内容でスレッドのモデルオブジェクトを作成する。thread_paramsはプライベートメソッドで、セキュリティのためにtitleuser_idのみを受け付けるようにしている。下記参考の URL に詳しく解説されている記事があった。
次に、@thread.saveでモデルオブジェクトをもとに DB に保存する。保存後は一覧画面に遷移する。

newについて、入力画面で入力した内容を格納しておくためのオブジェクトを用意する。あとはビュー側で入力データを格納すればよい。

app/views/board/threads/new.html.haml

%h1 スレッドの作成
= form_for @thread do |f|
  %div.input
    = f.label :title, 'タイトル'
    = f.text_field :title
  = f.hidden_field :user_id, value: 1
  %div.button
    = f.submit '作成'

フォームの作成はform_forメソッドを利用して実装する。このメソッドを利用すれば、様々なフォームを用意することができる。 今回はf.text_fieldを利用してテキストボックスを、f.submitを利用して送信ボタンを用意している。
user_idはまだ色々と準備ができていないので、とりあえず 1固定で登録されるようにしている。今回利用したフォームはこれだけだが、利用できるフォームは色々のでいずれまた使う機会を設ける。下記参考によく使うフォームの説明があるので参照するとよい。

以上で登録画面の作成は完了である。実際に入力画面よりデータ登録が行えるか動作確認を行なっておくとよい。

参考

詳細画面の作成

一覧画面からスレッドタイトルのリンクをクリック した時の遷移画面を作成する。

#### Post モデルの作成

rails generate model コマンドを使って投稿情報を保存するモデルを作成する。

$ bin/rails g model board_post user_id:integer body:text board_thread:references
  invoke  active_record
  create    db/migrate/20180104142519_create_board_posts.rb
  create    app/models/board_post.rb

$ bin/rake db:migrate
== 20180104142519 CreateBoardPosts: migrating =================================
-- create_table(:board_posts)
  -> 0.0147s
== 20180104142519 CreateBoardPosts: migrated (0.0147s) ========================

Thread モデルを用意したように、Post モデルも用意する。 board_thread:referencesで Thread の ID を外部キーとして設定しています。Migration ファイルをみてみると、

class CreateBoardPosts < ActiveRecord::Migration[5.1]
  def change
    create_table :board_posts do |t|
      t.integer :user_id
      t.text :body
      t.references :board_thread, foreign_key: true

      t.timestamps
    end
  end
end

となっており、foreign_key: trueが付与されている。 マイグレーション後にschema.rbに反映された内容をみると、

create_table "board_posts", force: :cascade do |t|
    t.integer "user_id"
    t.text "body"
    t.bigint "board_thread_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["board_thread_id"], name: "index_board_posts_on_board_thread_id"
end

また、 モデルファイル board_post.rbは、

class BoardPost < ApplicationRecord
  belongs_to :board_thread
end

と、belongs_toboard_threadに従属関係ができているのがわかる。

app/controllers/board/threads_controller.rb

def show
    @thread = BoardThread.find(params[:id])
    @posts = BoardPost.where(board_thread_id: params[:id]).order('created_at DESC')
end

モデルのfindメソッドを使用して、スレッドの ID からスレッド情報を取得する。さらに Post データはモデルのwhereメソッドを使用して、スレッド ID が一致する投稿データを全て取得する。また、orderメソッドを利用して最新の投稿が画面トップに表示されるように並び替えている。

app/views/board/threads/show.html.haml

%h1= @thread.title
- @posts.each do |post|
  %p= "No.#{post.id} #{post.created_at.strftime('%m/%d/%Y(%a) %H:%M:%S')} ID:#{post.user_id}"
  %p= post.body
  %hr/

ビュー側はコントローラーで取得した投稿データをeachでループして1件毎に表示している。

Clone this wiki locally