Play Frameworkでエラーページとカスタムエラーハンドラを作る ~ ホントは登録機能作るつもりだった ~
本日の配信
Scala-Play ハンズオン作成part11 ~ CRUD(dbなし)のサンプル作ろうの巻3 ~
今日は登録ページを作る! つもりが、エラーハンドリング追加でハマっていました
ハマっていたというよりは、私がScala, Playのお作法に則れていないのかなと思います
私は
NotFound
のResultを返したら、いい感じにエラーハンドラのonNotFound
が呼ばれて欲しかったんです
どうしても呼べなかったのです...
コントローラから直接throwすることも考えましたが、それはなんか違う気がして... どうしたらいいんでしょうね??
本日の進捗と残タスク
進捗
- 404ページの表示
- カスタムエラーハンドラの追加
404ページ表示: Commit Log
カスタムエラーハンドラ追加: Commit Log
理想型とは違った形になりましたが、エラー関連の実装ができました
カスタムエラーハンドリングは最初はいらないかなと思ったので、おまけに追加してみました!
次こそは登録フォームの実装をしますよ、次こそは
残タスク
実質進んでいないので、昨日と同じですね
登録・更新を作るのだ
本日の反省
そもそも私が人に教えられるほどスキルがないので、ハマるとハマっちゃいますね... その間すごく無言だった気がします
一緒に自習室とするには私が煩すぎるし、実況として聴くにはハマりすぎるしで落とし所が見つかってない気もしております(๑´ڡ`๑)
まとめ
今日はゲームだけでのんびりしよっかなって思っても「配信しなくては」という気持ちから机に向かえているので、すごく重宝しています
この調子で頑張るぞい!
ちょっと普通にシステム開発をしたくなってきていたりします
ずっとハンズオン作ってるの辛いです...
PlayFrameworkで一覧・詳細表示 ~ DBはないよ~
本日の配信
Scala-Play ハンズオン作成part10 ~ CRUD(dbなし)のサンプル作ろうの巻2 ~
今日は一覧表示と詳細表示の資料作成を進めました。
最初の方でclassとcase classの違いが気になって調べ物をしたりjavaコードにして比較したりと脱線してますね。
もうひと頑張りでCRUDが作成できる気がします。
一部リファクタリングが必要なので、そこをどの程度突っ込むかですね。
本日の進捗と残タスク
進捗
- 一覧表示作成
- 詳細表示作成
- 一覧から詳細への遷移
一覧表示: Commit Log
詳細表示: Commit Log
残タスク
- エラー処理と404ページの表示
- 登録・変更処理の追加
まずは登録・変更からにするつもりです。
formが出てくると、またややこしくなりますねぇ。
formオブジェクトをどこに置いておくか、悩みますね。
本日の反省
気づいていなかったのですが、最近流していたBGMの中で使われてる音楽が著作物だったみたいです。
カフェなどの環境音を利用していたので、その環境音の中で流れてる音楽がアウトらしく...
youtube側の機能で、そのあたりの音声を削除実行したのでもう大丈夫ですけどね!
無意識に著作権侵害しているのも怖いですし、このレベルのものを発見できるyoutubeも凄いです
まとめ
レッスン1についてはもうひと頑張りで完成しそうです!
ただ完成と思った部分を実際に進めると何分かかるかの確認が必要そうです
何分くらいのコンテンツにできているのかなぁ...
Playで簡単な画面表示とvalとdefの動きを比較
本日の配信
Scala-Play ハンズオン作成part9 ~ CRUD(dbなし)のサンプル作ろうの巻 ~
今日はPlayで1枚のページを表示するところまでの資料を作成しました
実装だけに集中すればCRUD全部はすぐにできると思うのですが、人に説明するためにコードを読んだり、markdownを書いているとすぐに時間がすぎてしまいますね!
次で配信も10回目になるみたいです。
早いような、遅いような。思ったよりも続けているなぁという印象です。
本日の進捗と残タスク
進捗
- list表示の基本骨子作成
- Controllerの簡単な説明記載
残タスク
- モデルの作成
- 一覧表示
- Twirlのもう少し詳細な説明(悩み中)
Twirlは一旦メインコンテンツ部分だけで突き進んで、デザインを当てる時とかにlayoutを説明するのが良いかもしれないなと思っています。
その場合Twirlの説明はもうちょっと後になりそうですね。
本日の反省
- 作業に集中する前の前半がグダグダしてしまう
IDEAの起動が遅かったり、何かとグダグダしちゃう前半。
ある程度仕方ないかなと思ってますが、改善できるならしたいですね。
おまけ
あくまでScala側での動きだけになりますが、この動作が少しわかりづらくもありつつ、面白いです。
def a: Long
に対してval a = 1L
が置き換えできているんですねぇ。
置き換えという言葉が言語しようとして正しいかどうかは正直わからないのですが、利用している側としてはそのような感覚になります。
もうちょっと細かくみてみたいので、以下のscalaファイルをjavaに変換をかけてみました。
// scala class A (){ val a = 1L def b = 1L }
// java import scala.reflect.ScalaSignature; public class A { private final long a = 1L; public long a() { return this.a; } public long b() { return 1L; } }
valの方がprivate finalなフィールドを持っている以外は同じですね。
setterもなくfinalなのでgetterで値を取得できるだけの変数になっており、getterも変数名と一致しています。
これだと引数なしのでdefで定義したbと同じで、ただ1を返すだけのメソッドと機能的には同じです。
scalaがコンパイルするにあたってどう判断しているかまではわかりませんが、val a
とdef a
はコード上では同様にA.a()
と呼び出されるという使い方以外はされないので、置き換えができるのでしょうね。
だから何?と言われてしまうとそれまでなのですが、面白いですね。
ただこの辺り意図的に使い分けられているのか、無差別に書かれているのかまで判断できていません。
呼び出し時のオーバーヘッドやメモリの効率などに微妙に違いがあるのでしょうか?
まだまだ完全解決とまではいきそうになりません。
しかし一つお利口になった気持ちにはなれました。
まとめ
ハンズオンの方はやっぱり作るのが大変ですが、副産物として自分の勉強も行えているので良い傾向なのかなと思います。
引き続きコツコツがんばりたいです
Play Frameworkの実装環境セットアップ ~ 手順書作ってるとExcelマンだった記憶が蘇る ~
本日の配信
Scala-Play ハンズオン作成part8 ~ playの導入をしていくの巻 ~
今日は再び純粋Playのハンズオンに戻ってきました。
IDEAのインストールやプロジェクトの取り込み方法を作っていたのですが、過去に使っていた環境が影響していて真っ白な状態での設定と差分が出てしまっていそうです...
環境を準備して検証し直すのも大変なので、再現のラインで妥協しちゃいました。
悔しい ェン(p´;ω;`q)ェン
本日の進捗と残タスク
進捗
- IDEAへの取り込み
- Play開発環境のセットアップ完了
残タスク
- 実際のコーディングセッション
最低限の下準備が終わったので、次からは実際のコーディングに入っていこうと思います。
今回はDBは利用せずにモックデータとしてSeqに独自クラスを格納して画面に表示していこうと思います。
一覧、詳細を作成したら登録系をやりつつフォームに触れます。
最後はTwirlでlayout系ファイルとコンテンツを切り出すような実装をしていこうかなと思います。
i18nとかもあるのですが、その辺真面目にやりすぎて楽しくなくなるよりは現実問題使うところだけ解説できればなというスタンスでおります。
本日の反省
今回は特に反省点はありません。
これから花粉症の季節なので、くしゃみと鼻水が酷くて配信ができなくなる気がしています。
それはちょっと寂しいかもしれない。
まとめ
スクリーンショットを撮って手順を作っていると、SI時代を思い出します。
あぁ、馴染む、馴染むぞ。
まぁ私は美少女ぴちぴちエンジェルなのでお仕事とかよくわかんないんですけど! ✧. (๑•̀ㅂ•́)و✧
SlickとMySQLの日付型再び & もうちょっとシンプルに対応
本日の配信
Scala-Play ハンズオン作成part7 ~ 改めてslickのdatetimeと闘うの巻 ~
本日は一旦SlickとMySQLの日付型マッピングに戻りました。
先日調整したものがあまりにもよくわからなかったのとシンプルさに欠けていたのが主な理由です。
もう少しシンプルな方法で対応をしつつ、なんでエラーになるのか処理を追ってみました
本日の進捗と残タスク
進捗
- 日付型のマッピングを別方法で対応完了
- ある程度エラーの原因を特定
Mapping解説
val id: Rep[Long] = column[Long] ("id", O.AutoInc, O.PrimaryKey) val content: Rep[String] = column[String]("content", O.Length(120,varying=true)) val postedAt: Rep[String] = column[String]("posted_at") val createdAt: Rep[String] = column[String]("created_at") val updatedAt: Rep[String] = column[String]("updated_at")
まずマッピングを一度Stringに戻して、文字列で受け取るようにしています。
これでこちら側の管理下に入る前にエラーで落ちることを回避しているつもりです。
def * = (id, content, postedAt, createdAt, updatedAt) <> ( (x: (Long, String, String, String, String)) => { Tweet(x._1, x._2, LocalDateTime.parse(x._3, format), LocalDateTime.parse(x._4, format), LocalDateTime.parse(x._5, format)) }, (tweet: Tweet) => { Some(tweet.id, tweet.content, tweet.postedAt.toString, tweet.createdAt.toString, tweet.updatedAt.toString) })
次にモデルとのマッピング、モデルからSlick用のタプルへの変換を自分で処理するようにしています。
created_at, updated_atなどは基本的に全てのテーブルにあるので全部これを書くのはいささか面倒という気持ちは脱ぎいきれませんが、変なことをするくらいであればこちらの方がよっぽどシンプルで良いのかな、という気がしています。
本気で作り込めばもう少し楽にできるのかもしれませんが、今はこれで十分(っつぅか限界
エラー補足
// LocalDateTimeにマッピングしようとするときに以下の場所(slick.jdbc.MySQLProfile)で落ちてる。iso8601では少数の桁数を定義してない // override def getValue(r: ResultSet, idx: Int) : LocalDateTime = { // r.getString(idx) match { // case null => null // case iso8601String => LocalDateTime.parse(iso8601String) // } // }
このコメントアウトの部分まんまですが、ここで落ちてるっぽいです(予想)
ResultSetから文字列で取得するまでは良い気がするのですが、parseするときに少数以下が文字列で入ってきてエラーになってるんだと思います。
iso8601はどうも厳密には小数点以下の精度が決められていないみたいでした
本当に簡単に調べた範囲ではありますがmysql, postgresは6桁までの精度を持っていて、oracle, db2あたりは9桁の精度で格納できそうでした
java.time.LocalDateTimeは9桁までの精度は対応できており、10桁以上はエラーになるようです
これって、そもそもバグに近いようなエラーだと思うのですが、どうしようもないんですかね?
残タスク
- Lesson1の全て
今のところはlesson1を作ることように優先順位を変更しているので、優先度を考慮すると今日は進捗が0で残タスクは変わらずということになりました。
本日の反省
よかった点
- 声は比較的聞きやすくなった、気がする
- なんか画面がいつもより綺麗??
- vimである程度奥の処理も追えるようになってきた
悪かった点
まとめ
今回はいろいろと調べ物中心でしたが個人的には楽しく調べるものができました。
やはり私はフィーリングでプログラミングしているなぁという気持ちになりました。
ハンズオン構成の修正 - PlayFrameworkをシンプルに作成するレッスンを作成する -
本日の配信
Scala-Play ハンズオン作成part6 ~ シンプルにPlayを利用するLessonを前段に差し込むよの巻 ~
なんと今回はプルリクをいただいておりました!
冒頭で早速プルリクをマージしました。感動ですね。
その後は今まで作成していたLesson0をLesson2へ変更しつつ、新たにLesson1を挿入していました。
今作成しているものは、Play, Slick, Slick関連ツール, implicit, Future, Dockerと情報量が多すぎて目的が不明確になってしまっていたので良くないと判断しました
Lesson1ではPlayをnewしたタイミングで入っているものだけで構築しようと思います。
それでもForm, Twirl, routing, MVC, validatorなどやることいっぱいですからね。
十分お腹いっぱいになりそうです
本日の進捗と残タスク
進捗
- Lesson1の作成
- リポジトリ内のファイル構成変更
- プルリクのマージ
残タスク
- Lesson1のアジェンダ作成
- Lesson1のコンテンツ作成
本日の反省
よかった点
- 音声や映像がクリア
悪かった点
- BGMのミックスをミスした
- いきあたりばったりで進めすぎ
今日は淡々と作業が進んだので、反省点があまり多くないです
そもそも論として、行き当たりばったりで進めているのでターゲットや目的が定まらない状態になってしまっています
これはよくないですね。とはいえ、作業するのが楽しいので楽しみながら作るという点では良いのです。継続しやすいのです。
しかし反省はする
まとめ
文量が増えればいいというものではないですが、文量は増えている
その分進んでいるんだ、という気持ちで少しずつがんばっていきたいと思います
slick&MySQLの日付型と闘う
本日の配信
Scala-Play ハンズオン作成part5 ~ slick&MySQLの日付型と闘うよの巻 ~
Scala-Play ハンズオン作成part5-2 ~ slick&MySQLの日付型と闘うよの巻 ~
今日は休日なので長々と作業をしました〜
slick-codegenに関連する作業は一通り完了することができました
中途半端な状態ではありますが、モデル一覧表示までは動作するようになりました
もう少し今までの作業を整理・リファクタリングできたら、資料の方向性を再考した方が良さそうです
多分今の状態は初心者にいうほど優しくない...
本日の進捗と残タスク
というわけで、本日の進捗です!
進捗
MySQLとSlick3.3で日付を扱うときに型がうまく調整できずにかなり苦労しています
独自型を定義して対応する方法での解決はできているのですが、もう少しシンプルに解決したいです...
一度Stringで受けてしまってModelにマッピングするところで型を変換してあげる方がシンプルで良いのかもしれないですね
残タスク
そろそろ一度整理して、本格的にベクトルを決める感じですね
また一気に作成しているので、文章や構成が綺麗ではない箇所があるはずです
その辺りを綺麗にしてわかりやすい資料にしたいですね
補足もたりてない箇所があるはずなので、私自身の勉強が必要そうです
本日の反省
よかった点
- 自身の作業としては集中して作業ができた
悪かった点
- 配信の意味がない
- part2の後半。マイクをミュートにしたらその後の音声が全部死んでしまった
シンプルに個人学習の状態配信なので、配信の意味とは...? という状態ですね
でも、元々自習室開放みたいなイメージで始めているので、良いということにしておきます!
まとめ
作業自体はコツコツと進んでいますが、少し深掘りをしていかないと「復習」みたいな比重が大きくなってしまいそうです
slick周りのセットアップが本当に大変なのですね...
誰でもわかりやすく、でも不便すぎない感じにできるのか、頑張る必要がありそうです