LoginSignup
1
0

More than 1 year has passed since last update.

Railsの基礎を使って、メッセージ投稿アプリを作ってみた 【第1章】(1.アプリ作成〜2.CRUD処理まで)

Last updated at Posted at 2022-08-26

はじめに

Railsの基礎を一通り学び終わったのですが、自分自身理解が追いついてないところもあると思うので、記事を作成する中でアウトプットし、理解を深めていくことが目的です。

概要

今回はタイトルにもあるとおり、簡単なメッセージ投稿アプリを解説も交えながら作成していきます。
アプリの作成からCRUD処理でメッセージ投稿機能の実装、それからリファクタリング、フラッシュやバリデーションの設定、エラーの処理、表示、最後にBootstrapでスタイルを付けるという感じで進めていきます。
なので、今回は4章に分けて記事を作成します。

開発手順

  1. アプリの作成 (第1章)
  2. CRUD処理で簡単なメッセージ投稿アプリを実装 (第1章)
  3. リファクタリング (第2章)
  4. フラッシュの実装 (第2章)
  5. バリデーションの設定 (第2章)
  6. エラーの処理 (第3章)
  7. Bootstrapでスタイルをつける (第4章)

開発環境

  • Ruby 2.7.3
  • Rails 6.1.6.1
  • Postgresql

1. アプリの作成

ターミナル
rails new post_message_app -d postgresql -T
cd post_message_app
rails db:create
  • データベースは-d postgresqlPostgreSQLを指定
    • データーベースを指定した場合は rails db:create が必要になります。
  • -T で MiniTest のディレクトリを作成しないように設定

モデルとテーブルの作成

メッセージ投稿アプリなので、メッセージのタイトル(title)と内容(content)を投稿できるよう2つのカラムを用意し、モデルを作成します。
※ モデル名は必ず 単数形!

ターミナル
rails g model Post title:string content:text

上記コマンドによって2つのファイルが作成されます。

  • app/models/post.rb (モデル)
  • db/migrate/作成日_create_posts.rb (マイグレーションファイル)

この時点で Post モデルは作成されたが、テーブルは作成されていません。
ターミナルでrails db:migrateコマンドを実行することにより、先ほど作成されたマイグレーションファイルが実行され、データベースに posts テーブルが作成される。

マイグレーション実行後は、db/schema.rb で作成したテーブルの中身を確認できます。

schema.rb
 create_table "posts", force: :cascade do |t|
    t.string "title"
    t.text "content"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

コントローラの作成

下記コマンドでコントローラとビューファイルまでまとめて作成。
※ コントローラ名は必ず複数形!

ターミナル
rails g controller posts new create index show edit update destroy

今回のアプリでは下記3つのファイルは使用しないので、この時点で削除しておきます。

  • app/views/posts/create.html.erb
  • app/views/posts/destroy.html.erb
  • app/views/posts/update.html.erb

ここまでで、モデル、テーブル、コントローラ、ビューファイルなど初期設定が完了です。

2. CRUD処理

今回は簡単にRESTフルなアプリを作成するため、resources を使用しルーティングを設定。

※ RESフルとは、(Representational State Transfer)「ネットワーク上にあるリソース(データ)に対して、作成、表示、更新、削除などの操作を行う」というアプリケーションを作成する上で必要な概念となります。

RESTの機能を担当するのがルーティングであり、resources を使用することで、簡単にRESTフルなアプリを作成することが可能となります。

routes.rb
Rails.application.routes.draw do
  root "posts#index"
  resources :posts
end

root "posts#index"を追記することにより、トップページを投稿一覧ページに設定します。

リンクの作成

全てのページで 投稿一覧ページ、新規投稿ページのリンクが表示されるように application.html.erb に追記。

app/views/layouts/application.html.erb
<!-- 略 -->
  <body>
    <%= link_to "投稿一覧", posts_path %> <%= link_to "新規投稿", new_post_path %>
    <hr>
    <%= yield %>
  </body>
</html>

Prefix を使用したパス名は下記コマンドで確認可能です。

ターミナル
rails routes | grep posts

新規投稿機能( new, create )

ルーティングは resources で設定しているので、コントローラから作成します。

app/controllers/posts_controller.rb
class PostsController < ApplicationController

 def new
   @post = Post.new
 end

 def create
   post = Post.create!(post_params)
   redirect_to post_path(post)
 end 

# 略

 private

 def post_params
  params.require(:post).permit(:title, :content)
 end

end

createアクションでは変数に @ はつけず、また新規投稿後は、投稿詳細ページにリダイレクトするように実装します。

@ を付けると付けないの違いについては、付けたらその変数はアクションと紐づくビューファイルで使用できるが、付けなかった場合は、ビューファイルで使用できません。

今回 create.html.erb 使用しないので、@ は付けないようにしています。
private には Strong Parameter (post_params)を記述し、データベースに予期せぬ値が登録されないよう titlecontent のみに制限。

次に form_with ヘルパーメソッドを使用しビューファイルで新規投稿ページを作成します。

app/views/posts/new.html.erb
<h1>新規投稿</h1>
<%= form_with model: @post, local: true do |form| %>
  <div>
    <%= form.label :title, "タイトル" %>
    <%= form.text_field :title %>
  </div>
  <div>
    <%= form.label :content, "内容" %>
    <%= form.text_field :content %>
  </div>
  <div>
    <%= form.submit "送信" %>
  </div>
<% end %>

form_with でモデルオブジェクト(@post)が posts テーブルに存在するかを判定し、存在しなければ createアクション、存在すれば updateアクションに処理を自動的に振り分ける役割を持ちます。

詳細(show)

まずはコントローラの処理から記述します。

app/controllers/posts_controller.rb
class PostsController < ApplicationController
  # 略

  def show
    @post = Post.find(params[:id])
  end

  # 略

end

findメソッドで, [:id] に対応する投稿をデータベースから取り出し、@post に代入。
params[:id] はshowアクションを実行した際の URL posts/:id と対応しています。

投稿詳細ページのビューファイルは下記の通り記述し、投稿したタイトルと内容を表示するようにします。

app/views/posts/show.html.erb
<h1>投稿詳細</h1>
<p>タイトル <%= @post.title %></p>
<p>内容  <%= @post.content %></p>

これで新規投稿ページで投稿し、詳細ページにリダイレクトされるところまでの流れが出来上がりです。

この記事を見ながら同じように作成している方がいるのであれば、ここで一旦サーバーを起動し、新規投稿ページにアクセスし、投稿ができ、詳細ページにリダイレクトされるか確認することをお勧めします。
URL:http://localhost:3000/posts/new 

一覧表示(index)

投稿詳細ページでは、タイトルと内容が表示されるので、一覧ページではタイトルのみ表示する形とします。
まずはコントローラから

app/controllers/posts_controller.rb
class PostsController < ApplicationController

# 略

 def index
   @posts = Post.order(:id :asc)
 end

# 略

end

Post.order を使用した目的としては、Post.all だと編集した場合、順番が変わってしまうので、Post.order を使用し、id順で取得するようにします。

app/views/posts/index.html.erb
<h1>投稿一覧</h1>
<table>
  <thead>
    <tr>
      <th scope="col">No.</th>
      <th scope="col">タイトル</th>
      <th scope="col"></th>
    </tr>
  </thead>
  <tbody>
    <% @posts.each.with_index(1) do |post, i| %>
      <tr>
        <th scope="row"><%= i %></th>
        <td><%= post.title %></td>
        <td>
          <%= link_to "詳細", post_path(post) %>
          <%= link_to "編集", edit_post_path(post) %>
          <%= link_to "削除", post, method: :delete, data: { confirm: "削除しますか?" } %>
        </td>
      </tr>
    <% end %>
  </tbody>
</table>

今回は詳細・編集・削除のリンクが縦に並ぶように、table ダグを使用。
each メソッドを使い、タイトルのみ繰り返し処理を行います。
ここで注意したいのが削除のリンクで、
link_to を使用した場合、指定がない限りHTTPメソッドは GET が使用されます。
しかし削除の場合は、DELETE なので指定してあげる必要があります。
また data: { confirm: "削除しますか?" } を記述することで、削除ボタンをクリックした際にダイアログを表示することができます。

削除機能(destroy)

先ほどの投稿一覧ページで削除のリンクは作成済みのため、コントローラの設定のみ行います。

app/controllers/posts_controller.rb
class PostsController < ApplicationController

# 略

 def destroy
   post = Post.find(params[:id])
   post.destroy!
   redirect_to root_path
 end

end

ビューファイルは削除済みなので、ここでも変数は @ は付けないようにします。

編集機能(edit, update)

この編集機能ができれば、CRUD処理は完成です。
長くなり、疲れも溜まってきたところですが、最後がんばりましょう!

まずはコントローラから

app/controllers/posts_controller.rb
class PostsController < ApplicationController

# 略

 def edit
   @post = Post.find(params[:id])
 end

 def update
  post = Post.find(params[:id])
  post.update!(post_params)
  redirect_to post_path(post)
 end

# 略

end

編集機能も削除機能と似た感じで、投稿データの id を飛ばして、コントローラで受け取り、update メソッドを実行し、投稿詳細ページにリダイレクトする形とします。

app/views/posts/edit.html.erb
<h1>編集</h1>
<%= form_with model: @post, local: true do |form| %>
  <div>
    <%= form.label :title, "タイトル" %>
    <%= form.text_field :title %>
  </div>
  <div>
    <%= form.label :content, "内容" %>
    <%= form.text_field :content %>
  </div>
  <div>
    <%= form.submit "送信" %>
  </div>
<% end %>

ここは新規投稿機能(new.html.erb)とほぼ同じです。
form_with でデータベースに存在するかを判定し、今回は存在するので、updateアクションに自動的に振り分けてくれます。

これで完成となるので、サーバーを起動し、一通りの操作が可能か確認してみましょう。

次回は今回作成したCRUD処理で実装した部分を、リファクタリングし、フラッシュメッセージの設定、バリデーションの追加と進めていきます!

お疲れ様でした!

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0