今日の学習時間。
- Day:24
- Today:7h
- Total:149h
学習内容について。
タスク管理アプリケーションを作成してみた。
今日は課題であるタスク管理アプリケーションの作成を行なっていく。詳細は昨日メモしてあるので、それに沿って最低限のコードだけ載せる。あとは集中して取り組むだけ。
条件
- タスクを管理できるWebアプリケーションを作成
- 最後にGitHubへ
kadai-tasklist
というリモートリポジトリを作成してプッシュ - eclipseで
tasklist
という名前の動的webプロジェクトを作成 tasks
テーブルを利用- ID
- 作成日時
- 更新日時
- content(タスクの内容)
- 7つのアクションをすべて実装
- 4つのビュー
- index (タスク一覧)
- show(詳細ページ)
- new(作成ページ)
- edit(編集ページ)
- 機能追加は合格後に行う
サラッと作ったので、コードだけ載せておきます。
src
/ controllers
package controllers;
import java.io.IOException;
import java.util.List;
import javax.persistence.EntityManager;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import models.Task;
import utils.DBUtil;
/**
* Servlet implementation class IndexServlet
*/
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public IndexServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
EntityManager em = DBUtil.createEntityManager();
int page = 1;
try {
page = Integer.parseInt(request.getParameter("page"));
} catch (NumberFormatException e) {
}
List<Task> tasks = em.createNamedQuery("getAllTasks", Task.class)
.setFirstResult(10 * (page - 1))
.setMaxResults(10)
.getResultList();
long tasks_count = (long) em.createNamedQuery("getTasksCount", Long.class)
.getSingleResult();
em.close();
request.setAttribute("tasks", tasks);
request.setAttribute("tasks_count", tasks_count);
request.setAttribute("page", page);
RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/views/tasks/index.jsp");
rd.forward(request, response);
}
}
package controllers;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import models.Task;
/**
* Servlet implementation class NewServlet
*/
@WebServlet("/new")
public class NewServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public NewServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setAttribute("_token", request.getSession().getId());
request.setAttribute("task", new Task());
RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/views/tasks/new.jsp");
rd.forward(request, response);
}
}
package controllers;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.List;
import javax.persistence.EntityManager;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import models.Task;
import utils.DBUtil;
import validators.TaskValidator;
/**
* Servlet implementation class CreateServlet
*/
@WebServlet("/create")
public class CreateServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public CreateServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String _token = (String) request.getParameter("_token");
if (_token != null && _token.equals(request.getSession().getId())) {
EntityManager em = DBUtil.createEntityManager();
Task t = new Task();
String title = request.getParameter("title");
t.setTitle(title);
String content = request.getParameter("content");
t.setContent(content);
Timestamp currentTime = new Timestamp(System.currentTimeMillis());
t.setCreated_at(currentTime);
t.setUpdated_at(currentTime);
List<String> errors = TaskValidator.validate(t);
if (errors.size() > 0) {
em.close();
request.setAttribute("_token", request.getSession().getId());
request.setAttribute("message", t);
request.setAttribute("errors", errors);
RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/views/tasks/new.jsp");
rd.forward(request, response);
} else {
em.getTransaction().begin();
em.persist(t);
em.getTransaction().commit();
request.getSession().setAttribute("flush", "登録が完了しました。");
em.close();
response.sendRedirect(request.getContextPath() + "/index");
}
}
}
}
package controllers;
import java.io.IOException;
import javax.persistence.EntityManager;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import models.Task;
import utils.DBUtil;
/**
* Servlet implementation class ShowServlet
*/
@WebServlet("/show")
public class ShowServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public ShowServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
EntityManager em = DBUtil.createEntityManager();
Task t = em.find(Task.class, Integer.parseInt(request.getParameter("id")));
em.close();
request.setAttribute("task", t);
RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/views/tasks/show.jsp");
rd.forward(request, response);
}
}
package controllers;
import java.io.IOException;
import javax.persistence.EntityManager;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import models.Task;
import utils.DBUtil;
/**
* Servlet implementation class EditServlet
*/
@WebServlet("/edit")
public class EditServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public EditServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
EntityManager em = DBUtil.createEntityManager();
Task t = em.find(Task.class, Integer.parseInt(request.getParameter("id")));
em.close();
request.setAttribute("task", t);
request.setAttribute("_token", request.getSession().getId());
if (t != null) {
request.getSession().setAttribute("task_id", t.getId());
}
RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/views/tasks/edit.jsp");
rd.forward(request, response);
}
}
package controllers;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.List;
import javax.persistence.EntityManager;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import models.Task;
import utils.DBUtil;
import validators.TaskValidator;
/**
* Servlet implementation class UpdateServlet
*/
@WebServlet("/update")
public class UpdateServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public UpdateServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String _token = (String) request.getParameter("_token");
if (_token != null && _token.equals(request.getSession().getId())) {
EntityManager em = DBUtil.createEntityManager();
Task t = em.find(Task.class, (Integer) (request.getSession().getAttribute("task_id")));
String title = request.getParameter("title");
t.setTitle(title);
String content = request.getParameter("content");
t.setContent(content);
Timestamp currentTime = new Timestamp(System.currentTimeMillis());
t.setUpdated_at(currentTime);
List<String> errors = TaskValidator.validate(t);
if (errors.size() > 0) {
em.close();
request.setAttribute("_token", request.getSession().getId());
request.setAttribute("task", t);
request.setAttribute("errors", errors);
RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/views/tasks/edit.jsp");
rd.forward(request, response);
} else {
em.getTransaction().begin();
em.getTransaction().commit();
request.getSession().setAttribute("flush", "更新が完了しました。");
em.close();
request.getSession().removeAttribute("task_id");
response.sendRedirect(request.getContextPath() + "/index");
}
}
}
}
package controllers;
import java.io.IOException;
import javax.persistence.EntityManager;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import models.Task;
import utils.DBUtil;
/**
* Servlet implementation class DestroyServlet
*/
@WebServlet("/destroy")
public class DestroyServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public DestroyServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String _token = (String) request.getParameter("_token");
if (_token != null && _token.equals(request.getSession().getId())) {
EntityManager em = DBUtil.createEntityManager();
Task t = em.find(Task.class, (Integer) (request.getSession().getAttribute("task_id")));
em.getTransaction().begin();
em.remove(t);
em.getTransaction().commit();
request.getSession().setAttribute("flush", "削除が完了しました。");
em.close();
request.getSession().removeAttribute("task_id");
response.sendRedirect(request.getContextPath() + "/index");
}
}
}
src
/ filters
package filters;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
/**
* Servlet Filter implementation class EncodingFilter
*/
@WebFilter("/*")
public class EncodingFilter implements Filter {
/**
* Default constructor.
*/
public EncodingFilter() {
// TODO Auto-generated constructor stub
}
/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
src
/ models
package models;
import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
@Entity
@NamedQueries({
@NamedQuery(name = "getAllTasks", query = "SELECT t FROM Task AS t ORDER BY t.id DESC"),
@NamedQuery(name = "getTasksCount", query = "SELECT COUNT(t) FROM Task AS t")
})
@Table(name = "tasks")
public class Task {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "title", length = 255, nullable = false)
private String title;
@Column(name = "content", length = 255, nullable = false)
private String content;
@Column(name = "created_at", nullable = false)
private Timestamp created_at;
@Column(name = "updated_at", nullable = false)
private Timestamp updated_at;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Timestamp getCreated_at() {
return created_at;
}
public void setCreated_at(Timestamp created_at) {
this.created_at = created_at;
}
public Timestamp getUpdated_at() {
return updated_at;
}
public void setUpdated_at(Timestamp updated_at) {
this.updated_at = updated_at;
}
}
src
/ utils
package utils;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class DBUtil {
private static final String PERSISTENCE_UNIT_NAME = "tasklist";
private static EntityManagerFactory emf;
public static EntityManager createEntityManager() {
return _getEntityManagerFactory().createEntityManager();
}
private static EntityManagerFactory _getEntityManagerFactory() {
if (emf == null) {
emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
}
return emf;
}
}
src
/ validators
package validators;
import java.util.ArrayList;
import java.util.List;
import models.Task;
public class TaskValidator {
public static List<String> validate(Task t) {
List<String> errors = new ArrayList<String>();
String title_error = _validateTitle(t.getTitle());
if (!title_error.equals("")) {
errors.add(title_error);
}
String content_error = _validateContent(t.getContent());
if (!content_error.equals("")) {
errors.add(content_error);
}
return errors;
}
private static String _validateTitle(String title) {
if (title == null || title.equals("")) {
return "タイトルを入力してください。";
}
return "";
}
private static String _validateContent(String content) {
if (content == null || content.equals("")) {
return "タスクを入力してください。";
}
return "";
}
}
WebContent
/ css
@CHARSET "UTF-8";
/*
YUI 3.18.1 (build f7e7bcb)
Copyright 2014 Yahoo! Inc. All rights reserved.
Licensed under the BSD License.
http://yuilibrary.com/license/
*/
html{color:#000;background:#FFF}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal}ol,ul{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}q:before,q:after{content:''}abbr,acronym{border:0;font-variant:normal}sup{vertical-align:text-top}sub{vertical-align:text-bottom}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;*font-size:100%}legend{color:#000}#yui3-css-stamp.cssreset{display:none}
@CHARSET "UTF-8";
body {
color: #333333;
font-family: "Hiragino Kaku Gothic Pro", Meiryo, "MS PGothic", Helvetica,
Arial, sans-serif;
}
#header {
width: 100%;
height: 70px;
background-color: #333333;
}
#content {
width: 94%;
margin-top: 15px;
padding-left: 3%;
}
h1 {
width: 94%;
padding-top: 17px;
padding-left: 3%;
font-size: 24px;
color: #eeeeee;
}
h2 {
font-size: 36px;
margin-bottom: 15px;
}
li {
margin-top: 10px;
margin-bottom: 10px;
}
p {
margin-top: 15px;
margin-bottom: 15px;
}
a {
text-decoration: none;
color: #24738e;
}
table, tr, th, td {
border: 1px solid #cccccc;
}
table {
width: 100%;
table-layout: fixed;
}
th {
width: 26%;
padding: 10px 2%;
}
td {
width: 66%;
padding: 10px 2%;
}
button {
font-size: 14px;
padding: 5px 10px;
}
#footer {
text-align: center;
}
#flush_success {
width: 100%;
padding-top: 28px;
padding-left: 2%;
padding-bottom: 28px;
margin-bottom: 15px;
color: #155724;
background-color: #d4edda;
}
#flush_error {
width: 100%;
padding-top: 28px;
padding-left: 2%;
padding-bottom: 28px;
margin-bottom: 15px;
color: #721c24;
background-color: #f8d7da;
}
WebContent
/ WEB-INF
/ views
/ layout
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>タスク管理</title>
<link rel="stylesheet" href="<c:url value='/css/reset.css' />">
<link rel="stylesheet" href="<c:url value='/css/style.css' />">
</head>
<body>
<div id="wrapper">
<div id="header">
<h1>タスク管理アプリケーション</h1>
</div>
<div id="content">
${param.content}
</div>
<div id="footer">
by Keiten Kiki.
</div>
</div>
</body>
</html>
WebContent
/ WEB-INF
/ views
/ tasks
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:if test="${errors != null}">
<div id="flush_error">
入力内容にエラーがあります。<br />
<c:forEach var="error" items="${errors}">
・<c:out value="${error}" /><br />
</c:forEach>
</div>
</c:if>
<label for="title">タイトル</label><br />
<input type="text" name="title" value="${task.title}" />
<br /><br />
<label for="content">タスク</label><br />
<input type="text" name="content" value="${task.content}" />
<br /><br />
<input type="hidden" name="_token" value="${_token}" />
<button type="submit">投稿</button>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:import url="../layout/app.jsp">
<c:param name="content">
<c:if test="${flush != null}">
<div id="flush_success">
<c:out value="${flush}"></c:out>
</div>
</c:if>
<h2>タスク一覧</h2>
<ul>
<c:forEach var="task" items="${tasks}">
<li>
<a href="${pageContext.request.contextPath}/show?id=${task.id}">
<c:out value="${task.id}" />
</a>
:<c:out value="${task.title}"></c:out> > <c:out value="${task.content}" />
</li>
</c:forEach>
</ul>
<div id="pagination">
(全 ${tasks_count} 件)<br />
<c:forEach var="i" begin="1" end="${((tasks_count - 1) / 15) + 1}" step="1">
<c:choose>
<c:when test="${i == page}">
<c:out value="${i}" />
</c:when>
<c:otherwise>
<a href="${pageContext.request.contextPath}/index?page=${i}"><c:out value="${i}" /></a>
</c:otherwise>
</c:choose>
</c:forEach>
</div>
<p><a href="${pageContext.request.contextPath}/new">新規タスクの投稿</a></p>
</c:param>
</c:import>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:import url="../layout/app.jsp">
<c:param name="content">
<h2>タスク新規作成ページ</h2>
<form method="POST" action="${pageContext.request.contextPath}/create">
<c:import url="_form.jsp" />
</form>
<p><a href="${pageContext.request.contextPath}/index">一覧に戻る</a></p>
</c:param>
</c:import>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<c:import url="../layout/app.jsp">
<c:param name="content">
<c:choose>
<c:when test="${task != null}">
<h2>id : ${task.id} のタスク詳細ページ</h2>
<table>
<tbody>
<tr>
<th>タイトル</th>
<td><c:out value="${task.title}" /></td>
</tr>
<tr>
<th>タスク</th>
<td><c:out value="${task.content}" /></td>
</tr>
<tr>
<th>作成日時</th>
<td><fmt:formatDate value="${task.created_at}" pattern="yyyy-MM-dd HH:mm:ss" /></td>
</tr>
<tr>
<th>更新日時</th>
<td><fmt:formatDate value="${task.updated_at}" pattern="yyyy-MM-dd HH:mm:ss" /></td>
</tr>
</tbody>
</table>
<p><a href="${pageContext.request.contextPath}/index">一覧に戻る</a></p>
<p><a href="${pageContext.request.contextPath}/edit?id=${task.id}">このタスクを編集する</a></p>
</c:when>
<c:otherwise>
<h2>お探しのデータは見つかりませんでした。</h2>
</c:otherwise>
</c:choose>
</c:param>
</c:import>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:import url="../layout/app.jsp">
<c:param name="content">
<c:choose>
<c:when test="${task != null}">
<h2>id : ${task.id} のタスク編集ページ</h2>
<form method="POST" action="${pageContext.request.contextPath}/update">
<c:import url="_form.jsp" />
</form>
<p><a href="${pageContext.request.contextPath}/index">一覧に戻る</a></p>
<p><a href="#" onclick="confirmDestroy();">このタスクを削除する</a></p>
<form method="POST" action="${pageContext.request.contextPath}/destroy">
<input type="hidden" name="_token" value="${_token}" />
</form>
<script>
function confirmDestroy() {
if(confirm("本当に削除してよろしいですか?")) {
document.forms[1].submit();
}
}
</script>
</c:when>
<c:otherwise>
<h2>お探しのデータは見つかりませんでした。</h2>
</c:otherwise>
</c:choose>
</c:param>
</c:import>
GitHubにプッシュ。
MacBook-Pro:tasklist KeitenKiki$ git remote add origin https://github.com/kikikeiten/kadai-tasklist.git
MacBook-Pro:tasklist KeitenKiki$ git remote -v
origin https://github.com/kikikeiten/kadai-tasklist.git (fetch)
origin https://github.com/kikikeiten/kadai-tasklist.git (push)
MacBook-Pro:tasklist KeitenKiki$ git push -u origin master
Enumerating objects: 164, done.
Counting objects: 100% (164/164), done.
Delta compression using up to 8 threads
Compressing objects: 100% (138/138), done.
Writing objects: 100% (164/164), 20.15 KiB | 1.68 MiB/s, done.
Total 164 (delta 66), reused 0 (delta 0)
remote: Resolving deltas: 100% (66/66), done.
To https://github.com/kikikeiten/kadai-tasklist.git
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
お疲れ様でした。
HerokuでWebアプリを公開してみる。
- Heroku
- PaaS(Platform as a Service)と呼ばれるサービス
- サーバコンピュータを提供
- PaaS(Platform as a Service)と呼ばれるサービス
続きは明日。。
今日の反省と明日の目標。
今日はひたすらコードを打ち込んでました。途中までは非常に順調だったけど、初めての500エラーに直面して2時間も悩んで遂に解決。{}
の閉じる位置が少し違うだけでこんなに困るとは思わなかったよ。。
しかし、エラーを解決した時は気持ちが良いものですね。もちろん、エラーが出ないようなコードを書いていくのが一番だけど、それは無理だからこれからうまく付き合っていく必要のある相手でもあります。エラーが出るとどうしても集中力が切れちゃうから、そこを維持していくのも課題かもしれません。
Herokuでデプロイする一歩手前のところだけど、明日の朝は用事があるのでここまでにしときます。Herokuのコマンドでもエラー発生する箇所があったから、そこも明日の記事で。