Rails で ToDo アプリをつくる⑦ (Rails 入門)

↓の続き

utouto97.hatenablog.com

今回やること

今回は、CRUDのU (Update) として、ToDoの内容の編集を実装していきます。
あらかじめ用意していたEditボタンに機能を実装していきます。

編集用フォームの準備

まずは、編集用のフォームを作ります。
ToDo一覧で、Editボタンを押すと、そのToDoが編集フォームに変わるようにします.

はじめに、ルーティングを設定します。
GETメソッドで/:idにアクセスした場合、通常通りToDo一覧を表示しますが、idに対応するToDoは編集フォームを表示します。

get '/:id' => 'todos#pre_edit'

対応するコントローラーのアクションを追加します。

def pre_edit
  @edit_id = params.require(:id)
  @todos = Todo.order(:created_at, :id)
  render :index
end

ここでやっているのは、id@edit_idに格納しているだけです。
あとは、通常のindexアクションと同じです。

最後にビューを編集します。
ToDoの一覧表示のためのループの中身を編集しています。
todo.id@edit_idが同じ場合は編集フォームを、異なる場合はToDoの内容を表示します。

<% @todos.each do |todo| %>
  <div class="card mx-auto w-50 mb-3">
    <h6 class="card-header <%= todo.status == 'In progress' ? 'bg-warning' : 'bg-success' %>">
      <%= todo.status %>
    </h6>
    <div class="card-body">
      <% if (defined? @edit_id) && (@edit_id.to_i == todo.id) %>
        <form action="/<%= todo.id %>" method="post" class="mb-5 w-50 mx-auto" name='user'>
          <input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>" />
          <div class="form-group">
            <label for="title">Title</label>
            <input type="text" class="form-control" name="title" placeholder="Title" value="<%= todo.title %>"/>
          </div>
          <div class="form-group">
            <label for="description">Description</label>
            <textarea class="form-control" name="description" placeholder="Description"><%= todo.description %></textarea>
          </div>
          <input type="hidden" name="status" value="<%= todo.status %>" />
          <button type="submit" class="mt-2 btn btn-primary">Send</button>
          <%= link_to 'Cancel', "/", method: :get, class: "mt-2 btn btn-secondary" %>
        </form>
      <% else %>
        <h5 class="card-title">
            <%= todo.title %>
        </h5>
        <p class="card-text">
          <%= todo.description %>
        </p>
        <%= link_to (todo.status == 'In progress' ? 'Complete' : 'Cancel'), "/#{todo.id}", method: :put, class: "btn btn-" + (todo.status == 'In progress' ? 'info' : 'secondary') %>
        <%= link_to 'Edit', "/#{todo.id}", method: :get, class: "btn btn-secondary" %>
        <%= link_to 'Delete', "/#{todo.id}", method: :delete, class: "btn btn-danger" %>
      <% end %>
    </div>
  </div>
<% end %>

ここまでで、編集用のフォームを表示できました。

f:id:utouto97:20210624215818p:plain

編集用アクションの追加

さきほど作ったフォームは/:idにPOSTします。
これを処理できるようにしていきます。

まずは、ルーティングを設定します。

post '/:id' => 'todos#change'

続いて、コントローラのアクションを追加していきます。
ここでは、前回やったストロングパラメータを活用しています。

def change
  @todo = Todo.find(params.require(:id))
  @todo.update(todo_params)
  redirect_to :action => 'index'
end

ここまでで、ToDoの内容を編集できるようになりました。
ToDo一覧のEditボタンを押し、内容を変更したあと、Sendボタンを押すと変更できます。
変更の際のエラーについては、現在は何も処理していません。

終わり