Ruby on Rails tutorial +alpha(7)睡眠表の表示
注意:この記事はメモなので、この記事に書いてあることをやっただけでは同じものができません。(大体の雰囲気は書いてあると思います。)
注意:全くのweb開発初心者なので、間違っているところなどがあるかと思いますが、教えていただけると嬉しいです。
fullcalender.ioだと印刷する時にうまくいかないので、表を表示して画像をダウンロードするか印刷できるようにしたいなあと思いました。
どういうものを目指しているかというと、Googleで「睡眠表」を検索すると出てくるようなやつです。そのまま病院などに持って行ってもある程度使えるようにしたいです。(そのためには睡眠の段階をもっと細かく分けて、最低でも「横になっている」「ぼんやりしている」「うとうとしている」「熟睡している」を分けないといけないですが…とりあえず今の状態でグラフを表示してみます。)
ところで入力がめんどくさすぎるので、30分ごとにプルダウンかなんかで作成できるようにしたいなあ…
usersコントローラのevents_tableアクションと、表が入っているビューを用意します。 表は横が30分刻みで、縦が1日1行2週間です。 もちろんevents_tableアクションには、対象をフォローしているユーザーしかアクセスできません。
def events_table params.permit(:endtime) @title = "睡眠表の印刷" @user = User.find(params[:id]) @end_date=Date.today if params[:endtime] && params[:endtime]!=""then @end_date=Date.parse(params[:endtime]) end @start_date=@end_date-14 @events = @user.events.where("starttime <= ? and endtime >= ?",(@end_date+1.day).to_time,@start_date.to_time) render 'events_table' end
view
<aside class="col-md-4"> <%= form_with(url:events_table_user_path,method: :get, local: true) do |f| %> <%= f.label :endtime, "最後の日付" %> <%= f.date_field :endtime%> <%= f.submit "表示", class: "btn btn-primary" %> <% end %> </aside> <div class="col-md-8"> <table border=1 id="events_table" style="table-layout:fixed;width: 100%;"> <tr> <th>記録</th> <% (24*2).times do |j|%> <td > <% if j%2==0 then%> <%=j/2%> <%end%> </td> <% end%> <td width="200">メモ</td> </tr> <% (@start_date..@end_date).each do |date|%> <tr> <td height="50"> <%=date.month%>/<%=date.mday%> </td> <% (24*2+1).times do |j|%> <td> </td> <% end%> </tr> <% end%> </table> 睡眠は★、食事は●、服薬は○、その他は先頭の一文字で示します。<br> あまりに生活記録の時間帯が重複していると表示がおかしくなる場合があります。 </div> <script> let table = document.getElementById('events_table'); <% @events.each do |event|%> start_duration=<%=(event.starttime.to_time-@start_date.to_time)%>; end_duration=<%=(event.endtime.to_time-@start_date.to_time)%>; event_name="<%=event.title%>"; event_type=<%=event.eventtype%>; counterx=0; if(event_type!=0){ for (let i=0;i<14;i++) { row=table.rows[i+1] console.log(counterx) let countery=0; for(let j=0;j<24*2;j++){ cell=row.cells[j+1]; celltime=counterx*60*60*24+countery*60*30; if(celltime+15*60>start_duration && celltime-15*60<=end_duration){ if(cell.innerText==" ")cell.innerText=""; if(event_type==1){ cell.innerText+="★\n"; }else if(event_type==2){ cell.innerText+="●\n"; }else if(event_type==3){ cell.innerText+="○\n"; }else{ cell.innerText+=event_name[0]+"\n"; } } countery+=1; } counterx+=1; } }else{ for (let i=0;i<14;i++) { row=table.rows[i+1] celltime=counterx*60*60*24; if(start_duration-24*60*60<=celltime&& celltime<=end_duration ){ console.log(counterx); row.cells[ 49 ].firstChild.data=event_name; } counterx+=1; } } <%end%> </script>
表の部分はjavascriptで書きました。もっといい方法がある気がするんですけど、目的が目的なのでなかなかぴったりくるものが見つからず… 見つけた方は教えてください。
とりあえずこのアルゴリズムだと(2週間のevent)242*14の計算量がかかりますが、(2週間のevent)はそんなに大きくないので大丈夫でしょう。ここで使ったwhichの条件、eventページにも使いたいですね。
テストを書いたら終わりです。
できました。(せっかくなので印刷する画面でみてみます。実用に耐えなさそうな気がします…まあ今後改良していきます)