Ruby on Rails tutorial +alpha(8)ストップウォッチの実装
注意:この記事はメモなので、この記事に書いてあることをやっただけでは同じものができません。(大体の雰囲気は書いてあると思います。)
注意:全くのweb開発初心者なので、間違っているところなどがあるかと思いますが、教えていただけると嬉しいです。
ストップウォッチを使って生活記録をつけられるようにします。開始時刻はデータベースに記録され、画面を閉じてもう一回開いても開始時刻からの時間が表示されているようにします。
まず、普通のタイマーをjavascriptで作ります。コントローラtimerを作り、get '/timer', to: 'timer#show'をルーティングします。このビューにタイマーを作ります。
javascriptでストップウォッチを作ってみる。忘備録 - Qiita これを参考にしました。
starttimeとtimetoaddをuserごとにデータベースに保存すると良さそうです。一つずつしかないので、usersデータベースに保存してしまいましょう。
rails g migration AddTimerToUsers timer_start:datetime timer_add:integer rails db:migrate
routesにpost '/timer', to: 'timer#edit'を追加し、editでデータベースに記録します。
【Rails】Rails⇔JavaScript間で時間データを渡す方法 - Qiita ここら辺も参考にしました。
とりあえずこれでタイマー機能ができました。viewとcontrollerを載せておきます。
<html lang="en"> <head> <meta charset="UTF-8"> <title>ストップウォッチで記録をつける</title> </head> <body> <div id="timer">00時間00分00</div> <button id="start">start</button> <button id="stop">stop</button> <button id="reset">reset</button> </body> </html> <script> (function(){ 'use strict'; var timer = document.getElementById('timer'); var start = document.getElementById('start'); var stop = document.getElementById('stop'); var reset = document.getElementById('reset'); var startTime=<%=@user.timer_start ? @user.timer_start.to_f*1000 : 0 %>;//開始時刻を記録する var elapsedTime = 0;//経過時刻 var timerId;//タイマーを止める用のタイマーのid var timeToadd=<%=@user.timer_add ? @user.timer_add : 0%>; var started=false; <% if @user.timer_start then %> var started=true; countUp(); <% elsif @user.timer_add then %> elapsedTime = timeToadd; updateTimetText(); <% end %> function updateTimetText(){//ミリ秒を時間:分:秒に直す var h = Math.floor(elapsedTime / 3600000); var m = Math.floor(elapsedTime %3600000 / 60000); var s = Math.floor(elapsedTime % 60000 / 1000); //2桁ずつ表示させる h = ('00' + h).slice(-2); m = ('00' + m).slice(-2); s = ('00' + s).slice(-2); timer.textContent = h + '時間' + m + '分' + s; } //再帰的に使える用の関数 function countUp(){ timerId = setTimeout(function(){ elapsedTime = Date.now() - startTime + timeToadd; updateTimetText() countUp(); },1000);//一秒おきに実行 } //todo:timer_startにtime_startを、timer_addにtime_addを記録 function recordState(time_start,time_add){ $.ajax({ url: "timer", type: "POST", data: {timer_start:time_start,timer_add:time_add}, dataType: "html" }); } start.addEventListener('click',function(){ started=true; startTime = Date.now(); recordState(startTime,timeToadd); clearTimeout(timerId); countUp(); }); stop.addEventListener('click',function(){ if(started){//タイマーが止まっている時は何もしない clearTimeout(timerId); timeToadd += Date.now() - startTime; recordState("nil",timeToadd); started=false; }else{ console.log("stopの押し過ぎはやめてください") } }); reset.addEventListener('click',function(){ clearTimeout(timerId); elapsedTime = 0; timeToadd = 0; recordState("nil","nil"); updateTimetText(); started=false; }); })(); </script>
class TimerController < ApplicationController def show @user=current_user render "timer/show" end def edit params.permit(:timer_start,:timer_add) time=nil add=nil time=Time.at(params[:timer_start].to_i/1000).in_time_zone if params[:timer_start]!="nil" add =params[:timer_add].to_i if params[:timer_add]!="nil" current_user.update_attributes(timer_start:time,timer_add:add) end end
ここから、ログインしたユーザしか見られなかったり、生活記録を(今の時間-計測した時間)から(今の時間)までの長さでつけられるように書いていきます。
jQuery内からRailsのActionを叩く - Qiita 【Rails】ajax通信 -> 処理 -> redirect_toのやり方(remote: true/controller) - Qiita
これも参考にしました。
function postEvent(){ var title=document.getElementById("title_form").value; var eventtype=document.getElementById("eventtype_form").value; var time=elapsedTime; $.ajax({ url: "timer/new", type: "POST", data: {title:title,eventtype:eventtype,time:time}, dataType: "text", success: function(data) { alert("行動記録が作成されました!"); }, error: function(data) { alert("エラーにより行動記録が作成されませんでした。"); } }); } submit.addEventListener('click',postEvent);
def create_event time=(params[:time].to_i/1000).to_i params[:title]="睡眠" if params[:eventtype] == "1" params[:title]="食事" if params[:eventtype] == "2" params[:title]="服薬" if params[:eventtype] == "3" event_params={title:params[:title],eventtype:params[:eventtype],starttime:Time.now-time,endtime:Time.now} @event = current_user.events.build(event_params) if @event.save return "true" else return end end
params[:title]="睡眠" if params[:eventtype] == "1"をもう一回書いているのがとても頭が悪い感じですが…(あとでヘルパーか何かにまとめ流べき)
とりあえずこんな感じで完成です。 あとはテストを書けば終わりです。