トップ画像イメージ

ajaxやaxiosでページ遷移なしで動的にページを更新するのもいいけど・・・

仕事でajaxによる動的なページの更新を結構していたのですが、よくよく仕様を整理していた時に、「ページ遷移せずに」に拘る必要がない事に気付いた時がありました。そういう時には、素直にRailsの機能を使って、viewに渡す変数だけ変えて、ページを再読み込みさせれば良い事を忘れていましたので自戒のために備忘録を残しておきます

どういう事かと言いますと、 例えば以下のような、テーブルをご想像ください。

table1

ここからは分かりにくいのですが、users 1 - * contentsのように、ユーザーに対して、複数のコンテンツがぶら下がっているようなテーブル構造になっています。

viewには、ユーザーに紐づいているcontentを一つ表示しており、view中の「次のコンテンツへ」ボタンを押す事で、紐づいている次のcontentを表示するような状況をご想像ください。

そんな時、非同期通信による動的なページ更新ばかりイメージしていると、jsとRailsの連携を意識してしまいますが、もし「ページ遷移なしで」という必要がない場合は、普通にRailsの機能だけで簡単に実装できます。

#controller

def sample
  @user = User.find(params[:id])
  @contents = @user.contents #ユーザーに紐づく複数のコンテンツが取れる
  @current_content_index = 0 #配列の要素番号と想定
end


<%= form_with url:'/hoge/hoge',local:true do |f| %>
  <btn>次へ</btn>
  <div>
    <%= @user.simei %>
    <p>現在のコンテンツ:<%= @contents[@current_content_index].meigen %></p>
    <%= hidden_field_tag 'current_content_index', @current_content_index %>
    <!-- なんかデータ更新用のtext_fieldとかがある -->
  </div>
<% end %>

次へボタンを押した時に、パラメータを持たせてsubmitさせるようにしておき、submit先のコントローラーのアクションで、dbの更新処理などを行なった後、このユーザーに紐づく次のコンテンツを表示させたい場合などは次のように処理することができます。

#controller
def hoge
  #何らかの処理
  #次のコンテンツを表示するように、viewに持たせる変数を用意
  user = User.find(params[:user_id])
  if user.contents.size < params[:current_content_index]
    next_content_index = params[:current_content_index] + 1
  else
    next_content_index = params[:current_content_index]
  end
  redirect_to action: 'sample',user: user,contents: user.contents,current_content_index: next_content_index
end

としますと、hogeアクションで何らかの処理を行った後、再度同じview内にリダイレクトする際に、次のコンテンツの情報を表示させることができます。

これが、この程度のコンテンツの量なら、それこそajaxなどを活用しても大丈夫ですが、ページ丸ごと置き換えるような処理であれば、redirect_toによるページ遷移で、viewに渡す変数を変えて、ページに再遷移させた方が簡単に実装できますね

まとめ

  • 非同期通信もいいけど、本当に非同期通信によるページの一部更新が適切か、redirect_toなどによる、ページごと再読み込みが適切か、考える意識を忘れないようにする
  • ページの一部をダイナミックに更新するなら、以前紹介した、部分partialをajaxで動的に更新する方法もある。