114
112

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Railsで更新も編集も削除も、全部indexページでやりたい

Last updated at Posted at 2015-01-29

RailsでScaffoldで画面を作ると、丁寧に新規・修正毎にViewができあがります。
ですが、できれば同じ1つの画面内で新規も修正もやりたいと思ったこと、ありませんか?

ということでindexページ内で全て新規登録も修正も完結するサンプルを作ってみました。

準備編

まずscaffoldでCRUD画面をちゃっちゃっと作りますね。

$ rails g scaffold User name:string age:decimal note:text

適当にテストデータを入れます。
Hashieとか使っているのは趣味です。

seed.rb
[
	{name: "Spike Spiegel", age: 27, birth: "2044-06-26", note: "SwordFish2"},
	{name: "Jet Black", age: 36, birth: "2035-12-03", note: "Hammerhead"},
	{name: "Faye Valentine", age: 77, note: "1994-08-14", note: "redtail"},
	{name: "Edward Wong Hau Pepelu Tivrusly 4", age: 13, birth: "2058-01-01", note: ""},
	{name: "Ein", age: 2}
].map{|row| Hashie::Mash.new(row) }.each do |data|
	User.create!(
		name: data.name,
		age: data.age,
		birth: data.birth,
		note: data.note
		)
end

indexページをルートに設定しておきます。

config/routes.rb
Rails.application.routes.draw do
  root "users#index"
  resources :users
end

新規登録編

_form.html.erbの中身をまずはガバっと貼り付けます。

users/index.html.erb

# -------------ここから----------------
<h1>Listing users</h1>

<%= form_for(@user) do |f| %>
  <% if @user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>

      <ul>
      <% @user.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :age %><br>
    <%= f.text_field :age %>
  </div>
  <div class="field">
    <%= f.label :note %><br>
    <%= f.text_area :note %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

# -------------ここまで----------------


<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Age</th>
      <th>Note</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @users.each do |user| %>
      <tr>
        <td><%= user.name %></td>
        <td><%= user.age %></td>
        <td><%= user.note %></td>
        <td><%= link_to 'Show', user %></td>
        <td><%= link_to 'Edit', edit_user_path(user) %></td>
        <td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New User', new_user_path %>

コントローラでform_forヘルパに渡すための@userオブジェクトを作成します。

app/controllers/users_controller.rb
def index
  @users = User.all
  @user = User.new   #追記
end

こんな見た目になります。

FormWithIndex.png

OK。表示はできました。
この状態でも更新できますが、users/:id/showへ遷移してしまうので更新後に元のindexページに戻るようにします。

redirect_to users_path

(今回はrootがusers#indexなので、root_pathでも同じですが。)

app/controllers/users_controller.rb
def create
  @user = User.new(user_params)

  respond_to do |format|
    if @user.save
      format.html { redirect_to  users_path, notice: 'User was successfully created.' }
      format.json { render :show, status: :created, location: @user }
    else
      format.html { render :new }
      format.json { render json: @user.errors, status: :unprocessable_entity }
    end
  end
end

"New User"をクリックしたときの遷移先も直しておきます。

_form.html.erb
<%= link_to 'New User', users_path %>

この状態でformからレコードを登録すると、パッと見はページ遷移ナシでリストにレコードが追加されたように見えます。

更新編

さて、これでindexページにformを追加して新規レコード作成ができるようにしてみましたが、
今度は編集まで行えるようにしてみます。

まずは、「edit」リンクを踏んだ先の遷移先を、/users/:id/editページではなく、同じくindexページのままで、formに編集対象のレコードの値が表示されるようにします。

更新対象のレコードを取得するため、users_pathにレコードのidを渡すようにします。

_form.html.erb
<td><%= link_to 'Edit', edit_user_path(user) %></td>
↓
<td><%= link_to 'Edit', users_path(id: user.id) %></td>

次はコントローラ側です。
paramsにidが含まれている場合は、そのIDから検索したUserオブジェクトを返すようにします。
User.findとやってもいいのですが、既にscaffoldで作成されたset_userメソッドが存在するのでそのまま使っています。

app/controllers/users_controller.rb
def index
  @users = User.all

  if params[:id].present?
    set_user
  else
    @user = User.new
  end
end

更新後には選択していたレコードの内容をそのままformに表示させておきたいので、
update後のリダイレクト先はusers_pathではなく、request.refererとしておきます。

app/controllers/users_controller.rb
def update
  respond_to do |format|
    if @user.update(user_params)
      format.html { redirect_to request.referer, notice: 'User was successfully updated.' }
      format.json { render :show, status: :ok, location: @user }
    else
      format.html { render :edit }
      format.json { render json: @user.errors, status: :unprocessable_entity }
    end
  end
end

削除編

削除は何も変えなくてOKですね。

その他

show/new/editアクションは使わないので、ルーティングから削除してcontrollerからも消しておいたほうが良いですね。

config/routes.rb
resources :users, expect: [:show, :new, :edit]

そんなこんなで完成です。
作ったサンプルは
https://github.com/jacoyutorius/form_with_index にありますので、もし良ければ参考にしてみてください。

FormWithIndex.png

114
112
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
114
112

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?