Code Serendipity

Keyword: Ruby, Python, javascript, RoR, heroku, AWS...

Code Serendipity

Keyword: Ruby, Python, wordpress, javascript, AWS...

【Rails, ajax】remote:true なリンクでデータベース操作とビューの書き換えをやる【noticeも出す】

f:id:serendipity4u:20170417172047p:plain

基本

  • 前提: users_controller.rbのactivate_userアクションにおいて、ajaxを使う
  • ajaxとは何か:WEBブラウザに実装されているJavaScriptのHTTP通信機能使って、Webページのリロードを伴わずにサーバーとデータのやりとりを行う処理。asynchronous JavaScript + XMLの略。

ajaxのメリット

  • 毎回application.js や application.css、共通画像などを読み込む必要がなくなるため、サーバー負荷に優しい。
  • ユーザーはページ遷移を意識せずにWebアプリを利用できるため、UXが高まる。

ajaxのデメリット

view

users/index.html.erb とか. usersディレクトリ配下ならどこでもいい.

<% @users.each do |user| %>
  <div id="user-<%= @user.id%>"> <!-- テンプレート書き換えがし易いように、idにレコードIDを付加しておく-->
  
  <%= user.name %>
  <%= link_to "有効化", activate_users_path, remote: true %> # remote: trueを忘れない

  </div> <!-- user-#{id} -->
<% end %>

users_controller.rb

Class UsersController < ...
...
def activate
  id = params[:id]
  @user = User.find(id) 
  if @user.update(approved: true)
    @message = "保存しました" // インスタンス変数, app/view/users/activate.js.erb及びそこで読み込んだテンプレートで利用可能
  else
     #as you like...
     @message = "保存に失敗しました"
  end
end

アクションに呼応した、js呼び出し用テンプレート users/activate.js.erb

$("#user-<%= @user.id %>").html("<%= j( render('activated_user') ) %>");  // ここで viewのIDが効いてくる セレクタの範囲において、activated_user.html.erbをrender する
$("#flash_messages").html("<%= j( render('shared/alert') ) %>"); // 通知機能「保存しました」

通知

app/view/layout/application.html.erb

<div id="flash_messages">
  <% flash.each do |name, msg| %>
    <div class="alert">
      <a class="close" data-dismiss="alert">x </a>
      <%= msg %>
     </div>
  <% end %>
</div>

viewの書き換え用テンプレート

users/activate.js.erbで呼び出す対象のテンプレート。

users/_activated_user.html.erb

<div id="user-<%= @user.id %>">
有効化されました!
</div>

shared/_notice.html.erb

<div id="flash_messages">

    <div class="alert">
      <a class="close" data-dismiss="alert">x </a>
      <%= @msg %>
     </div>

</div>

Railsの変数をJavaScriptで取得したい(ボクココより)

JavaScriptを書いていると、Railsの変数の値をJavaScriptで使いたい、というパターンが頻出する。これに対応する最も簡単な方法は、"display: none"なスタイルで変数をまとめたHTMLを書くことだ。

<div class="hidden">
  <span id="user_id"><%= @current_user.id %></span>
  <span id="status"><%= @current_user.status %></span>
</div>

//js parseInt($(“#user_id”).text()); ただ、この書き方で注意しなければなら無いのは、 悪意のあるユーザーがこのHTMLの内容を書き換えた後にJavaScriptを実行させる、ということもできてしまう 点にある。そのためRails側にリクエストを投げる時は必ずそのリクエスト内容が正しいかどうか検証するコードをお忘れなく。

参考

http://beck23.hatenablog.com/entry/2014/10/26/002858