Hit the books!!

プログラミング学習記録

Sinatraを使って簡単なメモアプリを作る

先日書いたSinatraを使ってメモアプリを作るという課題をやったので記録。

ud-ike.hatenablog.com

環境:macOS Catalina / Ruby 2.7.1

要件

  • メモを作成できるアプリをSinatraを使って作成する
  • デザインは自由(Bootstrapなどのフレームワークを使ってもOK)
  • 追加はPOSTメソッド、編集はPATCHメソッド、削除はDELETEメソッドで実装すること
  • データはDBを使わずにファイルに保存すること(DBを利用するバージョンは次回の課題)
  • 出来上がったらGitHubにPublicリポジトリを作りアップする

これ、パッと見ただけでやることが盛りだくさん...。しかもアプリを作成するという一連の開発の流れを経験するような課題ははじめて。もちろん苦労しました!!(ドヤ)

完成までの道のり

これだけやることがある...

  • URI設計の復習

  • Sinatraの使い方を理解する

  • CSSの復習

  • データを保存するファイル形式とその扱いを理解する

  • GitHubの復習

CSSもGitも勉強したけどすっかり忘れてたし、機能はシンプルなんだけど本当にやることいっぱいあるな〜という感じだった。

苦労したのは、全体の作業の進め方とかJSONデータの扱いとかSinatraのルーティングとかCSSとか...ほとんど全部かな。

今回はSinatraのルーティングのところに絞って書く。

設計

ディレクトリ構成

memo.rb
    views/
        - layout.erb
        - memos.erb
        - new.erb
        - details.erb
        - edit.erb
    memos/
        - memos.json
    public/
        - public.css

メモの保存はJSON形式で行うことにした。最初1つのメモにつき1つのjsonファイルを作成する処理にしようとしたがうまくいかず、1つのファイルにすべてのデータを保存する形にした。

JSONじゃなくyaml形式のファイルを使っている人もいたしテキストファイルで実装している人もいた。

URI設計

Method Path Discription
GET /memos メモ一覧を表示する(ホーム画面)
GET /new メモ作成画面を表示する
POST /memos メモを保存する
GET /memos/:id メモの詳細を表示する
GET /memos/:id/edit メモの編集画面を表示する
PATCH /memos/:id/edit メモを編集する
DELETE /memos/:id/delete メモを削除する

TwitterURI設計の課題を踏まえて設計した。

ud-ike.hatenablog.com

実装

完成図

こんな感じで作りました。

f:id:ud_ike:20200916223029p:plain

私はCSSフレームワークを使わず作成した。

上の「メモ帳」という字はホーム画面(/memos)にリンクしており、全ページ共通のレイアウトとしてlayout.erbに記述してある。

メモ一覧画面(ホーム画面)

"memo.rb"

get '/memos/?' do
  # 保存用のjsonファイルが存在しなければファイルを作成する処理
  # jsonファイルを読み込む処理
  erb :memos
end

/memosのあとに/?をいれることで、http://localhost:4567/memos/のように最後にスラッシュが入っていても/memosにアクセスできるようになる。

"memos.erb"

<form method="get" action="new">
  <p><% @json_data['memos'].reverse_each do |js| %>
  <p><a href="/memos/:<%= js['id'] %>"><%= js['title'] %></a></p>
<% end %>
  </p>

  <div class="btn-area">
    <input type="submit" value="作成">
  </div>
</form>

こちらは"views/details.erb"の中身。HTMLのフォームで指定できるメソッドはGETとPOSTだけであるためこのように記述する。

<form method="post" action="<%= @id %>/delete">
  <input type="hidden" name="_method" value="delete">
  <% @json_data['memos'].each do |js| %>
    <% if js['id'] == @id.to_i %>
      <% @title = js['title'] %>
      <% @content = js['content'].gsub(/\r\n/, '<br>')  %>
      <h2><%= @title %></h2>
      <p><%= @content %></p>
    <% end %>
  <% end %>

  <div class="btn-area">
    <input type="reset" value="編集" onclick="location.href='<%= @id %>/edit'"><input type="submit" value="削除">
  </div>
</form>

ちなみにgsub(/\r\n/, '<br>')は、メモの内容を改行するために置換している。

"memo.rb"の削除のルーティング↓

delete '/memos/:id/delete' do
  id = params[:id].delete(':')
  old_json = Memo.read
  Memo.fetch_delete(id, old_json)
  Memo.write

  redirect '/memos'
end

こんな感じでやってたらできた。 課題はOK出ましたが、まだ完成度は求められていないしあまりマネするのはオススメしません。

でも完成したときはうれしかった〜。