-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.json
1 lines (1 loc) · 204 KB
/
index.json
1
[{"content":"幸福な王子/柘榴の家 童話集第一遍が「幸福な王子」、第二遍が「柘榴の家」で、今回は両方が一冊に纏まっているものを読んだ。幻想文学、というジャンルを(おそらくちゃんと意識しては)初めて読んで、あらゆるものに自我がある独特な世界観に圧倒されつつも楽しく読めたけど、よくよく考えたら「サルカニ合戦」とかも臼が喋ってるのに子供の頃は深く考えないで読んでたよなと思った。童話で花が喋ろうが打ち上げ花火が喋ろうが、読み聞かせてもらう子供にとっては問題ないのかもしれない。\nジャイロスコープ 短編集。あとがき的なインタビューで先生本人も仰ってるけど、読者の考える「伊坂さんらしさ」は若干薄い短編が多め(特に「ギア」とか)。「浜田少年ホントスカ」と「1人には無理がある」が特に好き。\n特に「浜田少年ホントスカ」の、\n「殺し屋なんていう便利な職業は、フィクションの中にしかいないですからね」\nこれを読んだ最初は、こういうメタ的に刺してくる台詞を登場人物に言わせるの好きだなー、とだけ思ってたけど、読み返してみるとこれってこっちの台詞に意識を持っていかせることで、少し前の浜田少年の「プロの殺し屋に頼んだ方がいい」という若干違和感のある台詞をかすませてるのがすごい。他にも好きな言い回しは山のようにあったけど、あげるとキリがないので割愛する。\n夜の国のクーパー 伊坂さん祭り。\nなんとなく、「私」にとってこの国はミニチュアの世界みたいな物なんじゃないかなぁと確たる証拠もなく漠然と考えていたので、まさか本当にそうだとは思わず読み進めていてびっくりした。\n冠人に対する印象が文字通り180度ひっくり返ったけれど、「この親にしてこの子あり」という観点で凄まじく納得出来たのがよかった。物語上、一番明確な目的を持って動いていた複眼隊長の目的が、実は冒頭で既に達成されてました、という読み終わった後にわかるあっけなさも好き。殺し屋シリーズのような転がっていく楽しさ、というよりは、じわじわと謎が深まっていく面白さ、という感じだった。\n二重人格 めちゃくちゃ難しくて自分の読解力を疑いそうになった。勢いで読み切った後に見た巻末解説に「ドエトスフキーの作品の中でも評価がわかれる」「冗長な書き方が~」的な事が書いてあってちょっと安心した。個人的には、タイトルとあらすじを見て、自分の理想の姿の他人格が内面に生まれて支配されてしまう話かなと思ってたんだけど全然違くて、自分が上手くいかない理由を突然現れた理想の自分が邪魔してくるからだと思い込んで破滅(自滅)するという話でちょっと意外だった。そもそも「二重人格」っていうタイトル自体が、本来はロシア語でのドッペルゲンガー的な単語の意訳らしいと知って納得した。他のドエトフスキー作品を何冊か読んでからまた読み返したい。\n「後回し」にしない技術 kindle unlimitedで読んで良かったので再読。ドエトフスキーの小説読んでみようと思ったのもこの本から。「一冊読もう、ではなく一行読もう」とか、「ウォーミングアップに時間をかけるな」とか、後回し癖のある人(私)にとっては切れ味の鋭い言葉が多い。この本とか、「勉強が面白くなる瞬間」はモチベーションダダ下がっている時に読みたい。\n","permalink":"https://SawaTszm.github.io/post/book-202405/","summary":"幸福な王子/柘榴の家 童話集第一遍が「幸福な王子」、第二遍が「柘榴の家」で、今回は両方が一冊に纏まっているものを読んだ。幻想文学、というジャンルを(おそらくちゃんと意識しては)初めて読んで、あらゆるものに自我がある独特な世界観に圧倒されつつも楽しく読めたけど、よくよく考えたら「サルカニ合戦」とかも臼が喋ってるのに子供の頃は深く考えないで読んでたよなと思った。童話で花が喋ろうが打ち上げ花火が喋ろうが、読み聞かせてもらう子供にとっては問題ないのかもしれない。\nジャイロスコープ 短編集。あとがき的なインタビューで先生本人も仰ってるけど、読者の考える「伊坂さんらしさ」は若干薄い短編が多め(特に「ギア」とか)。「浜田少年ホントスカ」と「1人には無理がある」が特に好き。\n特に「浜田少年ホントスカ」の、\n「殺し屋なんていう便利な職業は、フィクションの中にしかいないですからね」\nこれを読んだ最初は、こういうメタ的に刺してくる台詞を登場人物に言わせるの好きだなー、とだけ思ってたけど、読み返してみるとこれってこっちの台詞に意識を持っていかせることで、少し前の浜田少年の「プロの殺し屋に頼んだ方がいい」という若干違和感のある台詞をかすませてるのがすごい。他にも好きな言い回しは山のようにあったけど、あげるとキリがないので割愛する。\n夜の国のクーパー 伊坂さん祭り。\nなんとなく、「私」にとってこの国はミニチュアの世界みたいな物なんじゃないかなぁと確たる証拠もなく漠然と考えていたので、まさか本当にそうだとは思わず読み進めていてびっくりした。\n冠人に対する印象が文字通り180度ひっくり返ったけれど、「この親にしてこの子あり」という観点で凄まじく納得出来たのがよかった。物語上、一番明確な目的を持って動いていた複眼隊長の目的が、実は冒頭で既に達成されてました、という読み終わった後にわかるあっけなさも好き。殺し屋シリーズのような転がっていく楽しさ、というよりは、じわじわと謎が深まっていく面白さ、という感じだった。\n二重人格 めちゃくちゃ難しくて自分の読解力を疑いそうになった。勢いで読み切った後に見た巻末解説に「ドエトスフキーの作品の中でも評価がわかれる」「冗長な書き方が~」的な事が書いてあってちょっと安心した。個人的には、タイトルとあらすじを見て、自分の理想の姿の他人格が内面に生まれて支配されてしまう話かなと思ってたんだけど全然違くて、自分が上手くいかない理由を突然現れた理想の自分が邪魔してくるからだと思い込んで破滅(自滅)するという話でちょっと意外だった。そもそも「二重人格」っていうタイトル自体が、本来はロシア語でのドッペルゲンガー的な単語の意訳らしいと知って納得した。他のドエトフスキー作品を何冊か読んでからまた読み返したい。\n「後回し」にしない技術 kindle unlimitedで読んで良かったので再読。ドエトフスキーの小説読んでみようと思ったのもこの本から。「一冊読もう、ではなく一行読もう」とか、「ウォーミングアップに時間をかけるな」とか、後回し癖のある人(私)にとっては切れ味の鋭い言葉が多い。この本とか、「勉強が面白くなる瞬間」はモチベーションダダ下がっている時に読みたい。","title":"【日記】最近読んだ本の感想【2024/05/31】"},{"content":" 趣味で書いている小説をgitで管理していて、進捗把握のためにコミットメッセージにその日1日書いた総文字数を入れ込んでいます。\nこんな感じで。\n以前までは、SF作家である藤井太洋先生自身が公開してくださっている拡張機能: novel-writerのステータスバー表示で文字数を把握し、手動でコミットメッセージを書いていました。\nただ、この方法にはいくつかの(個人的には解決したい)問題があり、\n日付が回ると文字数がリセットされるので、うっかりしてると差分の文字数がわからなくなる 特定のファイルや変更は含みたくない場合がある(翌日への自分のメモなど) コミットメッセージへの手打ちを辞めたい 上記二つに関しては、私が拡張機能で出来ることを把握しきれていないだけ or 今後改善される可能性はありますが、どうせならコミット時に自動でコミットメッセージ入力できたら楽だよなぁという動機があったので、ちょっと調べてスクリプトを組んでみました。\nやったこと 下記のスクリプトを.git/hooks/commit-msgとして設定します。\n#!/bin/bash # ステージングエリアに追加されたファイルの差分を取得し、文字数をカウントする関数 # .git/hooksに移動させて、`chmod +x .git/hooks/commit-msg`を実行することでコミット時にhookされる get_character_count() { # ステージングエリアに追加されたファイルの差分を取得 diff_output=$(git diff --cached) # 追加された行の文字数を合計する added_characters=$(echo \u0026#34;$diff_output\u0026#34; | grep \u0026#39;^+\u0026#39; | sed \u0026#39;s/^+//g\u0026#39; | wc -m) # 削除された行の文字数を合計する deleted_characters=$(echo \u0026#34;$diff_output\u0026#34; | grep \u0026#39;^-\u0026#39; | sed \u0026#39;s/^-//g\u0026#39; | wc -m) # 追加された文字数と削除された文字数の合計を計算する total_characters=$((added_characters - deleted_characters)) # 結果を出力 echo \u0026#34;$total_characters\u0026#34; } # コミットメッセージに追加 character_count=$(get_character_count) echo \u0026#34;📝 $character_count 文字\u0026#34; \u0026gt;\u0026gt; \u0026#34;$1\u0026#34; スクリプト内でやっている事はかなりシンプルで、git diffの結果である追加行(+で始まるもの)と削除行(-で始まるもの)の文字数をそれぞれカウントして差し引いて、総文字数を計算しているだけです。\nあとはこれに実行権限を渡してあげます。\nchmod +x .git/hooks/commit-msg 実際にお試しコミットしてみた結果がこちら。 便利!\n1日の終わりに1コミットするのみ、という前提が必須にはなっちゃいますが、今のところはこれで十分かなと思っています。コードと違ってそんなにこまめにコミット切りたい場面もないし。\nこれからもgit管理を続けていきたいので、何かやりたいことを思いついて実現できたら公開しようと思います。\n","permalink":"https://SawaTszm.github.io/post/auto-counting-word/","summary":"趣味で書いている小説をgitで管理していて、進捗把握のためにコミットメッセージにその日1日書いた総文字数を入れ込んでいます。\nこんな感じで。\n以前までは、SF作家である藤井太洋先生自身が公開してくださっている拡張機能: novel-writerのステータスバー表示で文字数を把握し、手動でコミットメッセージを書いていました。\nただ、この方法にはいくつかの(個人的には解決したい)問題があり、\n日付が回ると文字数がリセットされるので、うっかりしてると差分の文字数がわからなくなる 特定のファイルや変更は含みたくない場合がある(翌日への自分のメモなど) コミットメッセージへの手打ちを辞めたい 上記二つに関しては、私が拡張機能で出来ることを把握しきれていないだけ or 今後改善される可能性はありますが、どうせならコミット時に自動でコミットメッセージ入力できたら楽だよなぁという動機があったので、ちょっと調べてスクリプトを組んでみました。\nやったこと 下記のスクリプトを.git/hooks/commit-msgとして設定します。\n#!/bin/bash # ステージングエリアに追加されたファイルの差分を取得し、文字数をカウントする関数 # .git/hooksに移動させて、`chmod +x .git/hooks/commit-msg`を実行することでコミット時にhookされる get_character_count() { # ステージングエリアに追加されたファイルの差分を取得 diff_output=$(git diff --cached) # 追加された行の文字数を合計する added_characters=$(echo \u0026#34;$diff_output\u0026#34; | grep \u0026#39;^+\u0026#39; | sed \u0026#39;s/^+//g\u0026#39; | wc -m) # 削除された行の文字数を合計する deleted_characters=$(echo \u0026#34;$diff_output\u0026#34; | grep \u0026#39;^-\u0026#39; | sed \u0026#39;s/^-//g\u0026#39; | wc -m) # 追加された文字数と削除された文字数の合計を計算する total_characters=$((added_characters - deleted_characters)) # 結果を出力 echo \u0026#34;$total_characters\u0026#34; } # コミットメッセージに追加 character_count=$(get_character_count) echo \u0026#34;📝 $character_count 文字\u0026#34; \u0026gt;\u0026gt; \u0026#34;$1\u0026#34; スクリプト内でやっている事はかなりシンプルで、git diffの結果である追加行(+で始まるもの)と削除行(-で始まるもの)の文字数をそれぞれカウントして差し引いて、総文字数を計算しているだけです。","title":"【git】カウントしたコミットファイルの総文字数を自動でコミットメッセージに追加する"},{"content":"ベースブランチってどこ向け?\nタイトルの通り、main(default)ではないブランチから派生したブランチのPRを出すのに謎の抵抗感があったのですが、githubくんがかなりよしなにしてくれることに気がついたのでその挙動を備忘録として書いておきます。\n(知っている人にとってはめちゃくちゃ当たり前体操な内容だと思います)\nTL;DR main(default)ブランチから切ったブランチAから更に切ったブランチA2のPRを出すときは、難しいこと考えずにブランチA向けにPR出すのが良き。\nどういうこと? たとえば、チームメンバーがmainから派生したbranchAで作業していたとします。\nbranchAに乗っている機能が前提の作業をするために、branchAからbranchA2を切りました。\nbranchA2の作業が終わりPRを出したいのですが、branchAはまだ細かい部分のPR中でmainにはマージされていません。\nさて、このbranchA2のPRの向き先はmainかbranchAか、という話です。\n今こうして自分で書いていても「いやbranchA向けだろ……」と思うのですが(main向けにPRを出すと、branchAのコミットもPRに乗ってしまうためかなり見づらいことになるので)、\n「branchA向けに出したとして、branchAがmainにマージされたらbranchA向けのPRはどういう扱いになるんだ……? mainでrebase or mergeしてmain向けに直さないといけないのか?」と漠然と面倒臭がっていました。今までは。\nこの「PRのbaseとなっているブランチがマージされていった後にデフォルトのブランチ向けのPRに直す」作業、githubが勝手にやってくれます。\n実例 (ほとんどmainにしかpushしていないprivateリポジトリで実験)\ntest-branch-Aというブランチををmainから切ってPRを出したとします。\nその後、test-branch-Aから切ったtest-branch-A2のPRをtest-branch-A向けに出します。\n(PR作成時にbaseが選べるし、作成した後もEDITボタンから変更できます)\nこの状態でtest-branch-AのPRがマージされると、\nBase automatically changed from test-branch-A to mainというログが残って、test-branch-A2のPRがmain向けに自動修正されます。\nめちゃくちゃ便利だ……。もっと早く気が付きたかった。\nPR出した後は、ベースとなるブランチ自体に先んじてマージしちゃうか、そっちの作業を待ってからmainにマージするか、どちらにせよベースとなるブランチで作業している方とのコミュニケーションは必要ですが、とりあえず派生元にPR出しておけばあんまり困ることは(今のところの経験上)ないです。\n派生PR、もう怖くない!な備忘録でした。\n","permalink":"https://SawaTszm.github.io/post/pr-on-a-branch-not-main/","summary":"ベースブランチってどこ向け?\nタイトルの通り、main(default)ではないブランチから派生したブランチのPRを出すのに謎の抵抗感があったのですが、githubくんがかなりよしなにしてくれることに気がついたのでその挙動を備忘録として書いておきます。\n(知っている人にとってはめちゃくちゃ当たり前体操な内容だと思います)\nTL;DR main(default)ブランチから切ったブランチAから更に切ったブランチA2のPRを出すときは、難しいこと考えずにブランチA向けにPR出すのが良き。\nどういうこと? たとえば、チームメンバーがmainから派生したbranchAで作業していたとします。\nbranchAに乗っている機能が前提の作業をするために、branchAからbranchA2を切りました。\nbranchA2の作業が終わりPRを出したいのですが、branchAはまだ細かい部分のPR中でmainにはマージされていません。\nさて、このbranchA2のPRの向き先はmainかbranchAか、という話です。\n今こうして自分で書いていても「いやbranchA向けだろ……」と思うのですが(main向けにPRを出すと、branchAのコミットもPRに乗ってしまうためかなり見づらいことになるので)、\n「branchA向けに出したとして、branchAがmainにマージされたらbranchA向けのPRはどういう扱いになるんだ……? mainでrebase or mergeしてmain向けに直さないといけないのか?」と漠然と面倒臭がっていました。今までは。\nこの「PRのbaseとなっているブランチがマージされていった後にデフォルトのブランチ向けのPRに直す」作業、githubが勝手にやってくれます。\n実例 (ほとんどmainにしかpushしていないprivateリポジトリで実験)\ntest-branch-Aというブランチををmainから切ってPRを出したとします。\nその後、test-branch-Aから切ったtest-branch-A2のPRをtest-branch-A向けに出します。\n(PR作成時にbaseが選べるし、作成した後もEDITボタンから変更できます)\nこの状態でtest-branch-AのPRがマージされると、\nBase automatically changed from test-branch-A to mainというログが残って、test-branch-A2のPRがmain向けに自動修正されます。\nめちゃくちゃ便利だ……。もっと早く気が付きたかった。\nPR出した後は、ベースとなるブランチ自体に先んじてマージしちゃうか、そっちの作業を待ってからmainにマージするか、どちらにせよベースとなるブランチで作業している方とのコミュニケーションは必要ですが、とりあえず派生元にPR出しておけばあんまり困ることは(今のところの経験上)ないです。\n派生PR、もう怖くない!な備忘録でした。","title":"【github】mainではないブランチから派生したブランチでPRを出すとき"},{"content":" (2023/06/17)\nWe updated our RSA SSH host key - Github\n私用のPCで久々にpushしようとして警告出て、ちゃんと公式情報見た上で対応できたけど、3/24以降仕事以外のコードをpushしてなかったことが地味にショックでした。\n(2023/06/24)\n広くなったベランダで育て始めたペパーミント、苗買ってきた時よりなんか葉っぱ過疎ってないか……?と思って見てみたら馬鹿でかい青虫がついててリアルタイムでもりもり葉っぱ食べられてました。\n(2023/06/26)\n「AI分析でわかった トップ5%社員の習慣」を読んで、上位5%社員のXX%が〜っていうのに関しては、サンプリング数少ないから95%の人たちと違って一概には言えないんじゃないの?(この本作るために良いところだけピックアップするときにだいぶバイアスかかってそう)とは思ったけど、これ実践してみようかなと思うところはいくつかあったので読んでよかったです。\n読んですぐに(内容は本とは全然関係ない)スーパーミニマムな社内LTをしたんですが、「資料作りに時間をかけない」と割り切って最初からNotionにまとめることで割と短い時間で形に出来たのが個人的にいい学びでした。\n(2023/06/27)\nJavaScriptの入れ子の関数とクロージャ、シンプルに知らなかったです。使い過ぎはネストが辛くなりそうなので良くないと思う(というかユースケース自体あんまり思いつかない)けど、外側の関数のスコープを持ってくれる性質を利用して、コード理解の一助のためにロジックの一部を別関数に切り出す時なんかには有効そうだなと思いました。\n","permalink":"https://SawaTszm.github.io/post/diary-2023-07/","summary":"(2023/06/17)\nWe updated our RSA SSH host key - Github\n私用のPCで久々にpushしようとして警告出て、ちゃんと公式情報見た上で対応できたけど、3/24以降仕事以外のコードをpushしてなかったことが地味にショックでした。\n(2023/06/24)\n広くなったベランダで育て始めたペパーミント、苗買ってきた時よりなんか葉っぱ過疎ってないか……?と思って見てみたら馬鹿でかい青虫がついててリアルタイムでもりもり葉っぱ食べられてました。\n(2023/06/26)\n「AI分析でわかった トップ5%社員の習慣」を読んで、上位5%社員のXX%が〜っていうのに関しては、サンプリング数少ないから95%の人たちと違って一概には言えないんじゃないの?(この本作るために良いところだけピックアップするときにだいぶバイアスかかってそう)とは思ったけど、これ実践してみようかなと思うところはいくつかあったので読んでよかったです。\n読んですぐに(内容は本とは全然関係ない)スーパーミニマムな社内LTをしたんですが、「資料作りに時間をかけない」と割り切って最初からNotionにまとめることで割と短い時間で形に出来たのが個人的にいい学びでした。\n(2023/06/27)\nJavaScriptの入れ子の関数とクロージャ、シンプルに知らなかったです。使い過ぎはネストが辛くなりそうなので良くないと思う(というかユースケース自体あんまり思いつかない)けど、外側の関数のスコープを持ってくれる性質を利用して、コード理解の一助のためにロジックの一部を別関数に切り出す時なんかには有効そうだなと思いました。","title":"日記(~2023/07)"},{"content":"TypeScriptを使っていると、「ちゃんとprivateとかreadonlyとか使って制約かけないとな〜」と認識し直すタイミングが定期的に来るんですが、\nそんな折にJavaScript側で実現できるプライベートクラス機能なるものがあることを知りました。\nプライベートクラス機能 - JavaScript | MDN\nクラスのフィールドの先頭にハッシュ(#)をつけることで、プライベートなインスタンスフィールドを生成することができます。\nあくまでコンパイル時にエラーの判定を行うTypeScriptと異なり、JavaScript自身の機能なのでランタイム時に判定&エラーを返してくれます。\n継承を使う場合は、privateと同じく子クラスからは参照不可になりますが、\n子クラス側で同じ名前のプライベートインスタンスフィールドを定義することはできます。\n存在を知ってパッと概要を追って、良さそうと思ったけど世の反応(?)はどんな感じなんでしょうか。\n(ちなみに、インスタンス生成時に少し遅くなるらしい、と言う旨の去年の記事はお見かけしました: JavaScriptでプライベートを使うと遅くなる話)\n","permalink":"https://SawaTszm.github.io/post/private-class-field/","summary":"TypeScriptを使っていると、「ちゃんとprivateとかreadonlyとか使って制約かけないとな〜」と認識し直すタイミングが定期的に来るんですが、\nそんな折にJavaScript側で実現できるプライベートクラス機能なるものがあることを知りました。\nプライベートクラス機能 - JavaScript | MDN\nクラスのフィールドの先頭にハッシュ(#)をつけることで、プライベートなインスタンスフィールドを生成することができます。\nあくまでコンパイル時にエラーの判定を行うTypeScriptと異なり、JavaScript自身の機能なのでランタイム時に判定&エラーを返してくれます。\n継承を使う場合は、privateと同じく子クラスからは参照不可になりますが、\n子クラス側で同じ名前のプライベートインスタンスフィールドを定義することはできます。\n存在を知ってパッと概要を追って、良さそうと思ったけど世の反応(?)はどんな感じなんでしょうか。\n(ちなみに、インスタンス生成時に少し遅くなるらしい、と言う旨の去年の記事はお見かけしました: JavaScriptでプライベートを使うと遅くなる話)","title":"【覚え書き】JavaScriptのプライベートクラス機能"},{"content":"(純然たる日記の寄せ集めです)\n(2023/04/01)\nながら聞き用にbocoのPEACE SS-1買いました。\n仕事中に音楽とかラジオとか聴きたい派なんですが、ずっとイヤホンをしていると耳が痛いし、中耳炎になって危ないってよく聞くし……と思って数年前にShokz(旧Aftershokz)の骨伝導イヤホンを買ったのが骨伝導との出会いでした。\n買った当時は気にならなかったんですが、しばらく経ってちょっといい椅子を導入してヘッドレストにクッションをつけたら首周りの部分が干渉するようになってしまって、ちょっと不便だな〜と思っていたところにPEACE SS-1くんと出会いました。実に快適です。ありがとうboco。\n(耳を挟むように押し込むと音量上げたりできるらしいですが、なんか直感的に出来なくてコツが必要&挟み込み部分の寿命縮めそうなので本体操作は諦めてます)\n(2023/06/16)\n最近調べ物によくChatGPTを使っていて、便利だなぁと思う反面このままいくと原神のスメール編で学者たちに起きていたこと(聞けばなんでも出してくれるアーカーシャ端末があるから、誰も一次情報に触れようとしなくなる)が自分の中で起こりそうだなぁと漠然と考えたりしてました。\n利便性の恩恵を受けつつ、自分で調べ物をする感覚は忘れないように上手く間をとっていきたいです。\n(2023/06/17)\n応用情報がCBT方式になるのを密かに待っているんですが(基本情報はそれで去年受けた)、長文読解とか記述方式の回答とかの相性の問題で中々導入されないんじゃないか説が結構濃厚な感じがするので、観念して秋季に受けようかなと考え中です。\n予定があれば早起きできることを証明したいと思います。\n","permalink":"https://SawaTszm.github.io/post/diary-2023-06/","summary":"(純然たる日記の寄せ集めです)\n(2023/04/01)\nながら聞き用にbocoのPEACE SS-1買いました。\n仕事中に音楽とかラジオとか聴きたい派なんですが、ずっとイヤホンをしていると耳が痛いし、中耳炎になって危ないってよく聞くし……と思って数年前にShokz(旧Aftershokz)の骨伝導イヤホンを買ったのが骨伝導との出会いでした。\n買った当時は気にならなかったんですが、しばらく経ってちょっといい椅子を導入してヘッドレストにクッションをつけたら首周りの部分が干渉するようになってしまって、ちょっと不便だな〜と思っていたところにPEACE SS-1くんと出会いました。実に快適です。ありがとうboco。\n(耳を挟むように押し込むと音量上げたりできるらしいですが、なんか直感的に出来なくてコツが必要&挟み込み部分の寿命縮めそうなので本体操作は諦めてます)\n(2023/06/16)\n最近調べ物によくChatGPTを使っていて、便利だなぁと思う反面このままいくと原神のスメール編で学者たちに起きていたこと(聞けばなんでも出してくれるアーカーシャ端末があるから、誰も一次情報に触れようとしなくなる)が自分の中で起こりそうだなぁと漠然と考えたりしてました。\n利便性の恩恵を受けつつ、自分で調べ物をする感覚は忘れないように上手く間をとっていきたいです。\n(2023/06/17)\n応用情報がCBT方式になるのを密かに待っているんですが(基本情報はそれで去年受けた)、長文読解とか記述方式の回答とかの相性の問題で中々導入されないんじゃないか説が結構濃厚な感じがするので、観念して秋季に受けようかなと考え中です。\n予定があれば早起きできることを証明したいと思います。","title":"日記(~2023/06)"},{"content":"SSO、使う側としてはよく見かけますが実装する側としてはあんまりキャッチアップしてこなかったなと思ったので、軽く調べたのをまとめておきます。\nSSOとは シングルサインオン(Single Sign-On、SSO)は、ユーザが1回の認証で複数のアプリケーションにアクセスできるようにする仕組み全般のことを指します。\n大きく分けるとSAML(Security Assertion Markup Lnaguage)、OIDC(OpenID Connect)の2つの一般的なプロトコルがあります。(※諸説ある)\nSAML SAMLアサーション(ユーザ情報とアクセスできる内容を含む暗号化署名されたXMLドキュメント)を使用してサービス間でID情報を共有します。\nビジネス系(Slack, Office365, Salesforce)などでよく見られる(らしい)です。\nOpenID Connect JWT(JSON Web Token)を使用してサービス間でID情報を共有します。\nよくお世話になる「GoogleアカウントでYoutubeにログインしている」系はOpenID Connectで実現されています。\n代表的な実現方式 (【図解つき】シングルサインオン(SSO)とは?機能や仕組み、導入メリット、デメリットをわかりやすく解説! | mobiconnect(モビコネクト)を多大に参考にしています、ありがとうございます)\n代行認証方式 利用者の代わりにエージェントが認証情報を保持し、ログイン画面を検知したら代行して各システムのID、パスワードを入力する方式です。\n(個人的にはこれをSSOと呼んでも良いのか、という気持ちは多少あるけど、パスワード自動生成などで認証情報を意識しないので実質SSO、と言うことなのかもしれない)\nシステム側でSSOに対応していなくても、ID/パスワードでログインする一般的なシステムであれば使用することができ、活用範囲が広いです。\nその代わり、利用者側のPC(もしくはWebブラウザ)に常駐するエージェントを必ず入れる必要があります。\nリバースプロキシ方式 Web上で実現するSSOの仕組みとして、アクセスを全てリバースプロキシと呼ばれる中継サーバを介して行うようにネットワークを設計する方式です。\nリバースプロキシに対して認証を行うと、認証済みのCookieが発行され、各サイトにアクセスできるようになります。 対象としたいシステムに何か導入する必要がないため、既存システムへの影響がほぼない状態で事前検証ができます。が、リバースプロキシがボトルネックになる可能性があります。\n実装する場合はざっくり以下のような構成になります:\nNginx等を使用して、アプリケーションへのリバースプロキシをセットアップ SSOプロバイダの設定(色々あるので最適なものを選ぶ) アプリケーション側の認証ビュー(API)の実装 エージェント方式 リバースプロキシ方式同様、Web上で実現するSSOの仕組みで、Webサーバやアプリケーションサーバにエージェントソフトウェアを組み込む方式です。\n組み込んだモジュールがSSOサーバと連携することでSSOを実現します。\nリバースプロキシと異なり、ボトルネックが発生しづらい、既存のネットワーク環境に変更を加えなくて良い点がメリットです。\nSAML認証方式 SAML認証方式は、IdP(Identity Provider)とSP(Service Provider)の2つの要素で構成され、SP側(Webサーバやアプリケーション側)をSAMLに対応させることで、IdPが提供する認証情報を利用してSSOを実現できます。\n(名前がすごくややこしいけど、別に他の方式がSAMLプロトコルを使わないと言うわけではなくて、この方式の説明の意図は「上二つの方式と異なりWeb上で完結せず、アプリケーション側でSAMLに対応するSSO方式」ってことだと思います)\nまとめ 認証まわりって難しいですね。\n(見ている途中でソーシャル認証やOAuth2あたりの情報も出てきましたがちょっとパンクしてきたのでここで止めておきます)\n参考 シングルサインオンとは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典 【図解つき】シングルサインオン(SSO)とは?機能や仕組み、導入メリット、デメリットをわかりやすく解説! | mobiconnect(モビコネクト) What Is Single Sign-on (SSO)? How It Works - YouTube 後で見たい Django SSO - YouTube ","permalink":"https://SawaTszm.github.io/post/sumary-sso/","summary":"SSO、使う側としてはよく見かけますが実装する側としてはあんまりキャッチアップしてこなかったなと思ったので、軽く調べたのをまとめておきます。\nSSOとは シングルサインオン(Single Sign-On、SSO)は、ユーザが1回の認証で複数のアプリケーションにアクセスできるようにする仕組み全般のことを指します。\n大きく分けるとSAML(Security Assertion Markup Lnaguage)、OIDC(OpenID Connect)の2つの一般的なプロトコルがあります。(※諸説ある)\nSAML SAMLアサーション(ユーザ情報とアクセスできる内容を含む暗号化署名されたXMLドキュメント)を使用してサービス間でID情報を共有します。\nビジネス系(Slack, Office365, Salesforce)などでよく見られる(らしい)です。\nOpenID Connect JWT(JSON Web Token)を使用してサービス間でID情報を共有します。\nよくお世話になる「GoogleアカウントでYoutubeにログインしている」系はOpenID Connectで実現されています。\n代表的な実現方式 (【図解つき】シングルサインオン(SSO)とは?機能や仕組み、導入メリット、デメリットをわかりやすく解説! | mobiconnect(モビコネクト)を多大に参考にしています、ありがとうございます)\n代行認証方式 利用者の代わりにエージェントが認証情報を保持し、ログイン画面を検知したら代行して各システムのID、パスワードを入力する方式です。\n(個人的にはこれをSSOと呼んでも良いのか、という気持ちは多少あるけど、パスワード自動生成などで認証情報を意識しないので実質SSO、と言うことなのかもしれない)\nシステム側でSSOに対応していなくても、ID/パスワードでログインする一般的なシステムであれば使用することができ、活用範囲が広いです。\nその代わり、利用者側のPC(もしくはWebブラウザ)に常駐するエージェントを必ず入れる必要があります。\nリバースプロキシ方式 Web上で実現するSSOの仕組みとして、アクセスを全てリバースプロキシと呼ばれる中継サーバを介して行うようにネットワークを設計する方式です。\nリバースプロキシに対して認証を行うと、認証済みのCookieが発行され、各サイトにアクセスできるようになります。 対象としたいシステムに何か導入する必要がないため、既存システムへの影響がほぼない状態で事前検証ができます。が、リバースプロキシがボトルネックになる可能性があります。\n実装する場合はざっくり以下のような構成になります:\nNginx等を使用して、アプリケーションへのリバースプロキシをセットアップ SSOプロバイダの設定(色々あるので最適なものを選ぶ) アプリケーション側の認証ビュー(API)の実装 エージェント方式 リバースプロキシ方式同様、Web上で実現するSSOの仕組みで、Webサーバやアプリケーションサーバにエージェントソフトウェアを組み込む方式です。\n組み込んだモジュールがSSOサーバと連携することでSSOを実現します。\nリバースプロキシと異なり、ボトルネックが発生しづらい、既存のネットワーク環境に変更を加えなくて良い点がメリットです。\nSAML認証方式 SAML認証方式は、IdP(Identity Provider)とSP(Service Provider)の2つの要素で構成され、SP側(Webサーバやアプリケーション側)をSAMLに対応させることで、IdPが提供する認証情報を利用してSSOを実現できます。\n(名前がすごくややこしいけど、別に他の方式がSAMLプロトコルを使わないと言うわけではなくて、この方式の説明の意図は「上二つの方式と異なりWeb上で完結せず、アプリケーション側でSAMLに対応するSSO方式」ってことだと思います)\nまとめ 認証まわりって難しいですね。\n(見ている途中でソーシャル認証やOAuth2あたりの情報も出てきましたがちょっとパンクしてきたのでここで止めておきます)\n参考 シングルサインオンとは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典 【図解つき】シングルサインオン(SSO)とは?機能や仕組み、導入メリット、デメリットをわかりやすく解説! | mobiconnect(モビコネクト) What Is Single Sign-on (SSO)? How It Works - YouTube 後で見たい Django SSO - YouTube ","title":"SSOについて調べたことまとめ"},{"content":"最近個人でFlutterを触っていて楽しいので色々調べていて、その時知ったことや勉強会で聞かせてもらった話などのまとめ。\n(「こんな便利なものあるんだ〜」と思っても一回ブラウザのタブを開いちゃうと忘れがちなので、自分用のリンク集として)\nMaterial Design3 https://m3.material.io/\nMaterial 3 is the latest version of Google’s open-source design system. Design and build beautiful, usable products with Material 3.\n(拙訳) Material 3 は、Google のオープンソース デザイン システムの最新バージョンです。 Material 3 を使用して、美しく使いやすい製品を設計および構築します。\nGoogleのデザイナーと開発者によって構築・サポートされている、オープンソースなデザインシステム。\nAndroid, Flutter, そしてWeb向けのUXガイダンス・UIコンポーネントの実装が含まれている。 PrimaryColorを選択するだけでいい感じに各色設定してくれたりするので便利。\n(絶対それ以外の便利な使い方もある)\n// ThemeDataで指定する ThemeData( useMaterial3: true, colorSchemeSeed: Colors.XXX, // 好きな色 ) これだけでデフォルトの「テストです!!!」と言わんばかりの真っ青なヘッダが変わるのでちょっと「おぉ……」ってなる。\nDartPad https://dartpad.dev/\nDartの構文を気軽に試せる。便利。\nちなみに、新しいバージョンを試したいときは下のstable channelを押して切り替える。\nServerpod https://serverpod.dev/\nreverpodならぬServerPod。\nFlutterコミュニティ向けに、Dartで書かれたOSSのアプリサーバ。\nisar https://isar.dev/\nhiveのv2系としてのプロジェクトらしい?\nFlutterで使うデータベース。詳しくはこれから調べる。\n","permalink":"https://SawaTszm.github.io/post/diary-2023-03-11-about-flutter/","summary":"最近個人でFlutterを触っていて楽しいので色々調べていて、その時知ったことや勉強会で聞かせてもらった話などのまとめ。\n(「こんな便利なものあるんだ〜」と思っても一回ブラウザのタブを開いちゃうと忘れがちなので、自分用のリンク集として)\nMaterial Design3 https://m3.material.io/\nMaterial 3 is the latest version of Google’s open-source design system. Design and build beautiful, usable products with Material 3.\n(拙訳) Material 3 は、Google のオープンソース デザイン システムの最新バージョンです。 Material 3 を使用して、美しく使いやすい製品を設計および構築します。\nGoogleのデザイナーと開発者によって構築・サポートされている、オープンソースなデザインシステム。\nAndroid, Flutter, そしてWeb向けのUXガイダンス・UIコンポーネントの実装が含まれている。 PrimaryColorを選択するだけでいい感じに各色設定してくれたりするので便利。\n(絶対それ以外の便利な使い方もある)\n// ThemeDataで指定する ThemeData( useMaterial3: true, colorSchemeSeed: Colors.XXX, // 好きな色 ) これだけでデフォルトの「テストです!!!」と言わんばかりの真っ青なヘッダが変わるのでちょっと「おぉ……」ってなる。\nDartPad https://dartpad.dev/\nDartの構文を気軽に試せる。便利。\nちなみに、新しいバージョンを試したいときは下のstable channelを押して切り替える。\nServerpod https://serverpod.dev/\nreverpodならぬServerPod。\nFlutterコミュニティ向けに、Dartで書かれたOSSのアプリサーバ。\nisar https://isar.dev/\nhiveのv2系としてのプロジェクトらしい?\nFlutterで使うデータベース。詳しくはこれから調べる。","title":"Flutter周りで知ったことまとめ"},{"content":"pythonでHTTP通信するときに大体使うrequestsで、timeoutエラーの種類で問題の切り分けがしたくて調べたのでちょっとまとめ。\nTL;DR 公式ドキュメントのExceptionsを見るとわかりやすい。\n中でもタイムアウト関連のエラーは以下の二つ:\nconnect timeout requests.exceptions.ConnectTimeout例外が投げられる。\n相手のサーバと接続を確立する時に時間がかかりすぎたtimeout。\n公式ドキュメント\nread timeout requests.exceptions.ReadTimeout例外が投げられる。\n相手のサーバからレスポンスが返ってくるまでに時間がかかりすぎたtimeout。\n公式ドキュメント\n両方まとめてcatchしたい時は requests.exceptions.Timeout例外が設定されていて、ConnectTimeout, ReadTimeoutどちらも含まれます。\nもうちょっと詳しく そもそもRequestsの例外の中には、RequestException(曖昧な例外)やConnectionErrorが設定されていて、明らかに設定がおかしい場合や早期に接続エラーが起きた場合には、レスポンスを待つ前にこの例外が投げられます。\nそれらが起きずにtimeoutエラーが起きた場合は、接続の確立で相手からレスポンスが返ってこない(ConnectTimeout)か、接続確率はできてるけど接続先がデータの準備などで時間がかかりすぎて設定したtimeout時間内にレスポンスが返ってこない(Readtimeout)かの二択。\nなので、ConnectTimeoutが起きた時には安全に再試行できると公式ドキュメントにも書かれてます(少なくともリクエスト時の設定に問題がある訳じゃないから)。\nTimeout例外が出た時にする事は下記の感じになると思います:\nConnectTimeoutが出た場合は、リクエストを投げてる相手のサーバがダウンしてないか、ネットワーク設定に問題がないかを確認する。 ReadTimeoutが出た場合は、接続の確立には成功していて、向こうのレスポンスに時間がかかっているので、リクエストするサーバ側にも責任がある場合はチューニングする。そうでない場合は一度timeout時間を伸ばして成功するか様子を見る。 デフォルトのtimeout時間は設定されていないので注意する 明示的に設定しない限り、timeoutのデフォルトはNoneです。つまりtimeoutしません。\n基本的にはtimeoutを設定して、上記のtimeoutエラーで原因がわかるようにした方が良さそうです。\nimport requests try: # connect timeout, read timeoutどちらも同じ値で良い場合 res = requests.get(\u0026#39;有効なURL\u0026#39;, timeout=30) # connect timeout=30, read timeout=60とかで分けたい場合 res = requests.get(\u0026#39;有効なURL\u0026#39;, timeout=(30, 60)) except requests.exceptions.ConnectTimeout: print(\u0026#34;接続確立のエラー\u0026#34;) except requests.exceptions.ReadTimeout: print(\u0026#34;レスポンスが遅すぎたエラー\u0026#34;) ","permalink":"https://SawaTszm.github.io/post/python-requests-timeout/","summary":"pythonでHTTP通信するときに大体使うrequestsで、timeoutエラーの種類で問題の切り分けがしたくて調べたのでちょっとまとめ。\nTL;DR 公式ドキュメントのExceptionsを見るとわかりやすい。\n中でもタイムアウト関連のエラーは以下の二つ:\nconnect timeout requests.exceptions.ConnectTimeout例外が投げられる。\n相手のサーバと接続を確立する時に時間がかかりすぎたtimeout。\n公式ドキュメント\nread timeout requests.exceptions.ReadTimeout例外が投げられる。\n相手のサーバからレスポンスが返ってくるまでに時間がかかりすぎたtimeout。\n公式ドキュメント\n両方まとめてcatchしたい時は requests.exceptions.Timeout例外が設定されていて、ConnectTimeout, ReadTimeoutどちらも含まれます。\nもうちょっと詳しく そもそもRequestsの例外の中には、RequestException(曖昧な例外)やConnectionErrorが設定されていて、明らかに設定がおかしい場合や早期に接続エラーが起きた場合には、レスポンスを待つ前にこの例外が投げられます。\nそれらが起きずにtimeoutエラーが起きた場合は、接続の確立で相手からレスポンスが返ってこない(ConnectTimeout)か、接続確率はできてるけど接続先がデータの準備などで時間がかかりすぎて設定したtimeout時間内にレスポンスが返ってこない(Readtimeout)かの二択。\nなので、ConnectTimeoutが起きた時には安全に再試行できると公式ドキュメントにも書かれてます(少なくともリクエスト時の設定に問題がある訳じゃないから)。\nTimeout例外が出た時にする事は下記の感じになると思います:\nConnectTimeoutが出た場合は、リクエストを投げてる相手のサーバがダウンしてないか、ネットワーク設定に問題がないかを確認する。 ReadTimeoutが出た場合は、接続の確立には成功していて、向こうのレスポンスに時間がかかっているので、リクエストするサーバ側にも責任がある場合はチューニングする。そうでない場合は一度timeout時間を伸ばして成功するか様子を見る。 デフォルトのtimeout時間は設定されていないので注意する 明示的に設定しない限り、timeoutのデフォルトはNoneです。つまりtimeoutしません。\n基本的にはtimeoutを設定して、上記のtimeoutエラーで原因がわかるようにした方が良さそうです。\nimport requests try: # connect timeout, read timeoutどちらも同じ値で良い場合 res = requests.get(\u0026#39;有効なURL\u0026#39;, timeout=30) # connect timeout=30, read timeout=60とかで分けたい場合 res = requests.get(\u0026#39;有効なURL\u0026#39;, timeout=(30, 60)) except requests.exceptions.ConnectTimeout: print(\u0026#34;接続確立のエラー\u0026#34;) except requests.exceptions.ReadTimeout: print(\u0026#34;レスポンスが遅すぎたエラー\u0026#34;) ","title":"Python: requestsのタイムアウトエラーについて"},{"content":"個人開発でアプリ出したいなぁと思っていて(今はFlutterくんと仲良くなるためにチュートリアルやってるだけですが)、毎日少しずつでもコーディングするモチベーションが欲しい……!と思ってwakatimeを導入しました。\nwakatimeは、VSCodeなどのエディタと連携して、実際にコーディングしている時間を計測してくれるサービスです。\nちょうど最近登録したLAPRAS(GithubやTwitterなどからクローリングした情報をまとめてポートフォリオにしてくれるサービス)のbeta版機能として連携できるようになっていて知りました。\n個人で使っているPCのVSCodeにだけ導入しておけば、完全に個人でコーディングしている時間を集計できるのが良さげです。\nインストール\u0026amp;セットアップ サイトからgithubでサインアップ settingsにあるSecret API Keyをコピーしておく VSCodeの拡張機能でwakatimeをインストール インストールが終わるとAPIKeyの入力を求められるのでペースト これだけです。ダッシュボードは割とリアルタイムに反映されるので、少しコードを触って見に行くと集計されてます。\nどのリポジトリを触ったか、どの言語を触ったか、更にはデバッグしていた時間なども記録されてました。\nprofileに反映されるのは少し時間がかかりますが、少しすると表示され始めます:\n(githubのProfileにバッジも置いてみた)\n結論: 良さそう 最初は「ブログでもzennの記事書くときでも結構だらだらmdファイル触るし、触った言語比率とかそういうのpublicになるとちょっと恥ずかしいな〜」みたいな謎のプライド(?)で導入を悩んでいたんですが、公表するデータは制御できるし、最初から気軽な気持ちで導入しておけばよかったなと思いました。\nサイト内でコーディング時間のゴールも設定できる\u0026amp;profileの草形式で自分の頑張りが見られるので、モチベーションアップに繋がりそうです。\n(個人で触るコードのみの環境なのでサクッと導入しましたが、仕事上の守秘義務のあるコードを触る環境なんかに入れる時はセキュリティ的にちゃんと色々調べないといけないと思います。)\n","permalink":"https://SawaTszm.github.io/post/install-wakatime/","summary":"個人開発でアプリ出したいなぁと思っていて(今はFlutterくんと仲良くなるためにチュートリアルやってるだけですが)、毎日少しずつでもコーディングするモチベーションが欲しい……!と思ってwakatimeを導入しました。\nwakatimeは、VSCodeなどのエディタと連携して、実際にコーディングしている時間を計測してくれるサービスです。\nちょうど最近登録したLAPRAS(GithubやTwitterなどからクローリングした情報をまとめてポートフォリオにしてくれるサービス)のbeta版機能として連携できるようになっていて知りました。\n個人で使っているPCのVSCodeにだけ導入しておけば、完全に個人でコーディングしている時間を集計できるのが良さげです。\nインストール\u0026amp;セットアップ サイトからgithubでサインアップ settingsにあるSecret API Keyをコピーしておく VSCodeの拡張機能でwakatimeをインストール インストールが終わるとAPIKeyの入力を求められるのでペースト これだけです。ダッシュボードは割とリアルタイムに反映されるので、少しコードを触って見に行くと集計されてます。\nどのリポジトリを触ったか、どの言語を触ったか、更にはデバッグしていた時間なども記録されてました。\nprofileに反映されるのは少し時間がかかりますが、少しすると表示され始めます:\n(githubのProfileにバッジも置いてみた)\n結論: 良さそう 最初は「ブログでもzennの記事書くときでも結構だらだらmdファイル触るし、触った言語比率とかそういうのpublicになるとちょっと恥ずかしいな〜」みたいな謎のプライド(?)で導入を悩んでいたんですが、公表するデータは制御できるし、最初から気軽な気持ちで導入しておけばよかったなと思いました。\nサイト内でコーディング時間のゴールも設定できる\u0026amp;profileの草形式で自分の頑張りが見られるので、モチベーションアップに繋がりそうです。\n(個人で触るコードのみの環境なのでサクッと導入しましたが、仕事上の守秘義務のあるコードを触る環境なんかに入れる時はセキュリティ的にちゃんと色々調べないといけないと思います。)","title":"Wakatime導入してみた"},{"content":"最近読んだGoF本を記事としてまとめたくて、このサイト内でmermaidを記述したかったので組み込みました。その時の備忘録です。\n※「エラーを出さずに動くようにする」をメインに進めていったので、「こっちの方がいい」「これやらない方がいい」等もあるかもです。適宜読み替えて実施してください。\n手順 mermaidのUNPKGから、mermaild.min.jsとmermaild.min.js.mapをダウンロードする static/jsあたりに取得した2つのファイルを置く 適宜リネームしてください。私はVersion情報を入れてmermaild.min.9.2.jsにしました layouts/shortcodes/mermaid.htmlを作成する。 \u0026lt;script src=\u0026#34;{{\u0026#34;js/mermaid.min.9.2.js\u0026#34; | relURL}}\u0026#34; defer\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;div class=\u0026#34;mermaid\u0026#34; align=\u0026#34;{{ if .Get \u0026#34;align\u0026#34; }}{{ .Get \u0026#34;align\u0026#34; }}{{ else }}center{{ end }}\u0026#34;\u0026gt; {{ safeHTML .Inner }} \u0026lt;/div\u0026gt; (ローカルで確認するときは)ビルド&devサーバ立ち上げ 記事内に{{\u0026lt;mermaid\u0026gt;}} mermaidの記述 {{\u0026lt; /mermaid \u0026gt;}}と記述することで、図として表示されるようになります。 結果 これは試しに入れてみた公式ドキュメントの例:\n(ダークモードだとちょっと見づらいかも)\nsequenceDiagram participant Alice participant Bob Alice-\u003e\u003eJohn: Hello John, how are you? loop Healthcheck John-\u003e\u003eJohn: Fight against hypochondria end Note right of John: Rational thoughts prevail! John--\u003e\u003eAlice: Great! John-\u003e\u003eBob: How about you? Bob--\u003e\u003eJohn: Jolly good! 参考 下記を参考にさせていただきました! ありがとうございました。\nHugoにmermaidを組み込んでみた ","permalink":"https://SawaTszm.github.io/post/use-mermaid-in-hugo-blog/","summary":"最近読んだGoF本を記事としてまとめたくて、このサイト内でmermaidを記述したかったので組み込みました。その時の備忘録です。\n※「エラーを出さずに動くようにする」をメインに進めていったので、「こっちの方がいい」「これやらない方がいい」等もあるかもです。適宜読み替えて実施してください。\n手順 mermaidのUNPKGから、mermaild.min.jsとmermaild.min.js.mapをダウンロードする static/jsあたりに取得した2つのファイルを置く 適宜リネームしてください。私はVersion情報を入れてmermaild.min.9.2.jsにしました layouts/shortcodes/mermaid.htmlを作成する。 \u0026lt;script src=\u0026#34;{{\u0026#34;js/mermaid.min.9.2.js\u0026#34; | relURL}}\u0026#34; defer\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;div class=\u0026#34;mermaid\u0026#34; align=\u0026#34;{{ if .Get \u0026#34;align\u0026#34; }}{{ .Get \u0026#34;align\u0026#34; }}{{ else }}center{{ end }}\u0026#34;\u0026gt; {{ safeHTML .Inner }} \u0026lt;/div\u0026gt; (ローカルで確認するときは)ビルド&devサーバ立ち上げ 記事内に{{\u0026lt;mermaid\u0026gt;}} mermaidの記述 {{\u0026lt; /mermaid \u0026gt;}}と記述することで、図として表示されるようになります。 結果 これは試しに入れてみた公式ドキュメントの例:\n(ダークモードだとちょっと見づらいかも)\nsequenceDiagram participant Alice participant Bob Alice-\u003e\u003eJohn: Hello John, how are you? loop Healthcheck John-\u003e\u003eJohn: Fight against hypochondria end Note right of John: Rational thoughts prevail! John--\u003e\u003eAlice: Great! John-\u003e\u003eBob: How about you?","title":"Hugoを使用しているサイトでmermaidを記述できるようにする"},{"content":"前置き 今更何を言っているんだ感が凄まじいんですが、最近「ここ見たらわかりやすいですよ」とファイルのURL(できればgithub上の)を投げたい事があって、VScodeでファイル探す→githubのURLに直して渡すの流れが億劫だった(絶対VSCode上で出来るだろうにその時テンパってて見つけられなかった)のを真面目に探したら数分で発見したので備忘録として書いておきます。\n結論 拡張機能:GitLensのコマンドで出来ます。\nGitLens: Open File on Remote # ブラウザで開く GitLens: Copy Remote File Url # URLコピーする(便利) コマンドを実行する前に範囲選択しておくと、その行が選択された状態のURLになります。便利だ……。\n反省 「不便だな」と思ったことを手数で誤魔化してそのままにしないこと。\n","permalink":"https://SawaTszm.github.io/post/get-code-url-viewing-in-vscode/","summary":"前置き 今更何を言っているんだ感が凄まじいんですが、最近「ここ見たらわかりやすいですよ」とファイルのURL(できればgithub上の)を投げたい事があって、VScodeでファイル探す→githubのURLに直して渡すの流れが億劫だった(絶対VSCode上で出来るだろうにその時テンパってて見つけられなかった)のを真面目に探したら数分で発見したので備忘録として書いておきます。\n結論 拡張機能:GitLensのコマンドで出来ます。\nGitLens: Open File on Remote # ブラウザで開く GitLens: Copy Remote File Url # URLコピーする(便利) コマンドを実行する前に範囲選択しておくと、その行が選択された状態のURLになります。便利だ……。\n反省 「不便だな」と思ったことを手数で誤魔化してそのままにしないこと。","title":"VSCodeで開いているファイルをgithubで表示する"},{"content":"体調悪くてお休みいただいて、夜になってやっと復活してきたので、前記事(lodash is dead, long live radash)を見かけて気になってたRadashについて調べてました。\nRadash - github\nだけど調べてたら この「Lodashは死んだ」の記事と公式のドキュメント、githubページ以外全然関連の記事が出てこなくて(Radashって検索欄に入れてるのにRedashの記事ばっかり出てきて、マイナス検索してもRadashに触れてる記事はなかった)、記事は結構見られてたけどな……?と思って記事に戻ってみたら、書いてるのが作者本人でした。\n(最後の方に書いてあったし、早い段階でGithubページ見に行ってリポジトリ名チェックしてたらもっと早く気づけたかもしれません)\nタイトルだけ読んで現行のlodashに取ってかわる最新版なんだと思ってしまっていたので、この事実&それ自体に気づくまでが結構長かったのが個人的なショックでした。そういう意味ではいい学びになった感じがします。\nあと、コメント欄で「自分で書いとるんか〜い」みたいな突っ込みもされてましたが、それらに対して「それでもこのライブラリを作った彼の労力は賞賛すべき」「このような肯定的な批判を受け取る場を自ら作り出すこと自体に批判的になってはいけない。それはOSSの衰退につながる」みたいなコメントが多かったことも、OSS文化に触れてまだ浅い身からすると新しい気づきでした。\n次からは、何かしら記事を見るときは「どういう立場で書かれているものか」は軽くチェックすることを心がけようと思います。\n","permalink":"https://SawaTszm.github.io/post/diary-2022-09-15/","summary":"","title":"日記 2022-09-15"},{"content":" タイトル通りTOEIC受けてきました。\n新卒時代にIPテストを受けて驚異の300点台前半を叩き出してから一回も受けてなかったんですが、最近英語圏のVtuberにハマって英語に触れる機会が増えてきたのでいけるのでは……?と思って勢いで申し込みました。\n一応1ヶ月間は真面目に勉強したので、過去最高点は取れるんじゃないかなと思います(低すぎるハードル)。\n以下備忘録を兼ねた感想です。\n腕時計必須(それはそう) スマートウォッチ系がダメだって言うのを前日の夜に知って、腕時計なしで挑むことになったのが辛かったです。\n1問20秒ほどだっていうのは知ってたので何とか体内時計で頑張りました。最後の問題解いたあたりで試験が終わったので、結構正確だったんだと思います(そこじゃない)。\n今後も年1くらいで受けたいな〜と思ってるのでお気に入りの腕時計探しておきます。\n慣れてないと集中力続けさせるのが結構キツい リスニングのPart4の途中と、リーディングのPart7の途中で「もう残り全部塗りつぶして帰りたいな……」ってなってました。\n勉強してはいたんですが、一問一答形式のものをずっとやっていただけだったので、本番の長さに全く体が適応できてなかったです。\n模試とか絶対やった方がいい。\n勉強してる時ほど音声はクリアじゃない ノイキャン付きのイヤホンつけて聞く音源とやたらデカい室内のスピーカーの音は全然違うので、最初の音量合わせの時に慣れるのにもうちょっとフォーカス当てた方がいいなと思いました。\n成長はちょっと感じた IP受けた時(3~4年前……?)は正直「問題に何聞かれてるかわからない」レベルだったのが、少なくともそこで困ることはなかったのでちょっとは成長してるんだな〜って感じました。\n1ヶ月くらいで結果出ると思うので楽しみです。\n追記 結果が出ました。初めて400点代が取れました&今までの最高得点から100点近く上がりました!\n点数的にはまだまだですが、この調子でこれからも頑張っていきたいです。\n","permalink":"https://SawaTszm.github.io/post/diary-2022-09-13/","summary":"","title":"TOEICを受けてきました"},{"content":"今更だけど remについて。\n一回調べてなるほど〜!ってなった記憶はあるのにロジック考えずに見た目で数字決めてコミットしたの中々にテンパってたなって反省をした備忘録です。(一息)\nremとは 基準のフォントサイズを1として考える単位。\n例えば:1rem=16px(html要素のフォントサイズが16px)の場合、\n12px: 0.75rem 14px: 0.875rem 18px: 1.125rem \u0026hellip; と言う感じ。\n「〇〇pxって何remだっけ……」ってなって他のコードと実際の表示を見にいくことが多かったんですが、\n欲しいpx数/ルートのフォントサイズ(px)すれば出てくる……出てくるのに……何で今まで調べなきゃ出てこないって思ってたんだろう……。\n反省。次からは間違えないと思います。\n","permalink":"https://SawaTszm.github.io/post/diary-2022-06-25/","summary":"","title":"日記(2022/06/25)"},{"content":"タイトルの通り、\n最近仕事をしていて気がついたこと/教えてもらえたことで、自分はこれを気をつけた方がいいなと思ったことを忘れないために言語化したメモです。\n(増えるかもしれません)\n「既存のもの」を「覆してはならない前提」と捉えない 悪かった例(この場合はDjango) 私「このmodelにカラム追加したいけど、似たようなカラムがあるしな。データ被るのも嫌だから、propertyメソッドで動的に返すようにしよう」\n~30分後~\n「あ、propertyだとunion()時ののcolumn数合わせに使えないんだった。どうしよう……」(ここで無限ググり編に突入)\n~30分後~\n「クエリもうひとつ発行してitertools.chain()で繋げる手があるかぁ」(そうじゃない)\nこの時の結論:\n元のmodelのデータ定義自体が改善しても良い範囲だったので、unionできる形にmodelを寄せることを提案してもらって解決しました。\nメタ的な原因 既にプロジェクトに存在しているコードを、無意識に「絶対的に正しいもの」「変えちゃいけないもの」として捉えていました。\n(「このmodelはこういう定義なんだから、これを変形してどうにかしないと」と言うところから思考がスタートしていた)\n社会人初の案件がガチガチに要件が固まった後のネットワーク更改案件だったので、「既存のconfigは絶対に正しい、これを崩さないように新しい経路繋げないと」的な考えが根底に残ってたのかもしれないです。\n(今までも似たような感覚に陥ったことが何回かあって、言語化できてちょっとスッキリしました)\n改善策 「既存のもの」を「覆してはならない前提」と捉えない。 実装のために考え始める時、「そもそも」の疑問を大切にする。 「そもそも、どうしてこのmodelってこういう構造になったんだろう?」 言っても「考える時に気をつけよう」は忘れるので、しばらくモニターに付箋を貼る。 緊張時に毎回心拍数120近くまで上がるのはいき過ぎなので対策を考えるべき これ、最近調べて初めて知りました。\n今まで緊張してる時(例えばプレゼン前とか、極端な例で言うと広めのメンションでslack送る前とか)Apple Watchに「非常に高い心拍数です」って言われるのをネタにして生きてきてたんですが、最近動悸が激しすぎて頭が真っ白になる経験をして、これはまずいなと思って調べたらやっぱり心拍数上がりすぎらしいです。\n幸いその時は人前で喋るとかじゃなくて、家の中で一人ぜーはー言ってただけで落ち着く時間もあって事なきを得ましたが、このままじゃ良くないので色々対策してみようと思いました。\n","permalink":"https://SawaTszm.github.io/post/things-to-watch-out-for/","summary":"","title":"気をつけるべきだなと思ったこと"},{"content":"上手くいかないCSSをdev toolでぐりぐり動かしていたらdisplay: contents;なる値があることを知って、結局そのパターンは上手くいったんですがなんで上手くいったかわからないのでちょっとだけ調べました。\n(本格的に調べるのは後日)\ndisplay: contents;とは colissで紹介されていました。\n(先日参加した勉強会で紹介されていたサイトなのでちょっとテンションが上が理ました)\nすごくざっくり言うと、\nタグ内のコンテンツを通常通り描画しつつ、周囲のタグは完全に省略する display: contents; が指定されたタグ自体が無視されたような挙動になる CSS Gridのレイアウトで、複数あるカードのそれぞれの高さや幅を揃えるのに便利 (今回上手くいった修正はこのパターンだった) まだ全然追いきてれないですが、タグを無視したような挙動をする以上落とし穴(何かの拍子にめちゃくちゃ表示崩れる)とかもありそうなので、見れる時にもう少しちゃんと挙動を見たい……。\nちなみにCan I Useで見てみると、大体2018年くらいからパーシャルサポートが始まり、現在(2022/06)主要なブラウザはほとんどがフルサポートです。\nIE君はNot Supportedですが先日卒業式をしたので……\n参考 [CSS]「display: contents;」がすごい便利!ラッパーを使った実装が大きく変わるこれからのテクニック Can I use display: contents ","permalink":"https://SawaTszm.github.io/post/css-display-contents/","summary":"","title":"[TIL] display: contents;"},{"content":"タイトルの通り 3月頃に思い立って申し込みをして、1ヶ月前後の勉強で受かりました。嬉しいことに午前午後どちらも9割近く取った上での合格でした。\n全体的には、学生時代に学んだことを思い出すのに役立ったなぁと言う印象でした。\n学生の頃に「ITパスポート取るか。言っても専攻だし(情報工学科だった)いけるでしょ!」と全く勉強をせずに行って落ちた経験があり、国家試験系からは長年目を背け続けていたので、受けるにあたってちょっと驚いたことがいくつかあったので書いておきます。\n早起きを証明できる試験ではなくなっていた よく基本情報についてTwitterなどで「朝早く起きて会場に行ける社会性を証明できる試験」なんて揶揄されているのを目にしていましたが、CBT方式になって時間は選び放題、なんなら午前と午後を別日に受けてもいいと言う緩さになっていました。\n正直、今回基本情報を実際に受ける気になったのも、このCBT方式で受けられると言うのを知ったから、と言うところが大きかったです。\n直近の過去問が参照できない 基本情報と言えば引くほど過去問が見れるイメージがあったんですが、CBT方式になってからの過去問は公開されていないみたいです。\n今はまだCBT方式になってから日が浅い&シラバスの大幅な改訂も入っていないので、公開されている過去問を一通り解いても十分勉強になります。ただ、これからどんどん過去問と実際の問題との乖離が進んでいくんじゃないかなーと思います。\n(そもそもCBT方式にしてから合格者の割合がグッと増えてるらしいので、そう言う意味ではちょうど良いところに落ち着くのかも?)\n応用情報はまだ紙試験 この勢いで応用情報も受けようかな〜と思ったんですが、応用情報の方はまだ筆記らしくて悩んでます。\n朝起きれないし、一日に午前午後で集中力続く気がしないので……(社会適応力皆無)。\n","permalink":"https://SawaTszm.github.io/post/diary-2021-05-16/","summary":"","title":"基本情報に受かりました"},{"content":"環境 PC: macbook Air (M1) OS: Big Sur 11.6.1 起きた問題 ある日、docker desktop for macのアイコンからPreferencesを押してもDockerの画面が立ち上がらなくなりました(アイコンが2,3回跳ねて落ちる)。\n同様にDownload updateも立ち上がらないのでおや?と思い、一度PCを再起動したらFatal Error Failed to ping backend APIというエラーウィンドウが出てdocker自体が立ち上がらなくなりました。\nReset Docker to factory defaults, Diagnose \u0026amp; Feedback, Exitの選択肢はありますが押せない(カーソルぐるぐる)状態になっていて、リセットもさせてくれません。\nどうやら似た状況になっている方も結構いるようで、既知のバグ?のようです。(docker for macのissue)。こちらでも未だに議論されていて、完璧な解決策はまだ出ていないように見えます。\n色々参考にさせてもらいつつとりあえず復旧はさせたので、手順を残しておこうと思います。\n復帰方法 docker関連のプロセスをkillする コマンドで消すか、アクティビティモニタでdockerを調べて出てきたものを終了させます。\n# コマンドの場合 $killall Docker アンインストール アプリケーションフォルダからゴミ箱にどん。今思えばもうちょっとスマートなやりようがあった気がします。\n新しいのをインストールする 公式サイトから最新版をダウンロード&インストール。\nフルアクセスを許可 上記でインストールしたものが上手く立ち上がればここはスキップしてもいいと思います(起動時にアクセス権限の変更をdocker側から提案してくれる筈なので)。\nシステム環境設定\u0026gt;セキュリティとプライバシー\u0026gt;フルディスクアクセスからdockerにフルアクセスを許可します。\n(追記)\nしばらく触っていなかった別のmacbookを見てみたらdockerにそんな権限は渡していなかった(でも上手く動いている)ので、ここに関してはちょっと不確かかも知れません。\ndocker再起動 うまく動きました。\n","permalink":"https://SawaTszm.github.io/post/docker-for-mac-does-not-work/","summary":"","title":"docker for Macが更新できない"},{"content":"https://firstcontributions.github.io/\nMake your first open source contribution in 5 minutes.\n君も5分でOSSコントリビューターだ!(意訳)\n「OSS活動への貢献してみたいけど、まずどうすれば良いのかよくわからないな」と思って調べていた時に発見した上記のありがたいプロジェクトで、OSSコントリビュータデビューさせてもらった時の備忘録です。\nOSSにPR出してみたいけどぶっつけ本番は緊張する、貢献したいOSSとかまだあんまり決まってない(けどやりたいとは思ってる)人がもしいれば、このプロジェクトの胸を借りることをお勧めします。\n流れのまとめ First ContributionsのリポジトリでPRを出す流れを体験させてもらう サイトのプロジェクトリストを参考に作業するリポジトリを探す ↑のREADMEやContribute.mdなどでルールを確認(大事) 1.の要領でPRを作成、修正、マージ PRの手順 基本的にはリポジトリのREADMEに沿って進めるだけです。5分もかかりませんでした。\n(様々な言語で翻訳されていて、コミュニティの大きさを感じます)\n簡単な手順は以下の通り。\nリポジトリをフォーク フォークしたリポジトリをクローンしてくる ブランチを作成 コードを変更してコミット Push PRを送る(githubで自分のリポジトリに行くとCompare \u0026amp; pull requestボタンが表示される) これで完了です!\n記念すべき人生初OSSコミットがこちら\n練習が終わったら本番 PRを出すまでの流れを実際に体験できたので、いよいよ他のOSSにPR出していくぞ!という流れなのですが、貢献したいコミュニティが最初から決まっている場合を除くとどこのリポジトリにどういう作業をさせてもらおうか悩む、というか目星をつけられなくて困ると思います。少なくとも私は困りました。\nですがその辺りもFirst Contributionsはカバーしてくれていて、ネクストステップとして取り組みやすいプロジェクトのリストを用意してくれています。(一番最初に貼ったURLと同じです)\nhttps://firstcontributions.github.io/\nここで自分で使っている言語や諸々で絞り込んで、気になったリポジトリのissue等を見ていくと、すぐに取り組めるタスクがあったりします。\n(もしくは実際に使ってみて、気になる箇所があればissueやそれに対するPRを立てたりもできます)\n私の場合は、興味があったリポジトリに誰でも取り組んで良い「ファイルごとのテストカバレッジを100%にする」issueが立っていたのでそれに着手しました。\n大体のリポジトリはREADMEやContribute.mdなどに貢献の方法やルールが明記されているのでまずはそれを見て、しっかりそれらを守りつつ作業することを心がけましょう(自戒)。\n記念すべき人生二度目OSSコミットがこちら\n余談 OSSコントリビューションというと花形のPRに目が行きがちですが、issueでのエラー報告も立派な貢献になるみたいです。言われてみれば確かに、実装中エラーに当たった時OSSのissueにはいつもお世話になってます。 カタカナ表記の場合、リポジトリ派閥とレポジトリ派閥があることに気がつきました。IT用語辞典などでも併記されているので、完全に好みの問題みたいです。 軽い気持ちでやったFirst Contributionsさんのお試しPRでしたが、大きな声では言えないですがこれひとつでfindyさんの偏差値が結構上がりました(!)。OSSへの貢献はエンジニアのハードルの一つなのかも知れないですね。 ","permalink":"https://SawaTszm.github.io/post/first-oss-contributions/","summary":"https://firstcontributions.github.io/\nMake your first open source contribution in 5 minutes.\n君も5分でOSSコントリビューターだ!(意訳)\n「OSS活動への貢献してみたいけど、まずどうすれば良いのかよくわからないな」と思って調べていた時に発見した上記のありがたいプロジェクトで、OSSコントリビュータデビューさせてもらった時の備忘録です。\nOSSにPR出してみたいけどぶっつけ本番は緊張する、貢献したいOSSとかまだあんまり決まってない(けどやりたいとは思ってる)人がもしいれば、このプロジェクトの胸を借りることをお勧めします。\n流れのまとめ First ContributionsのリポジトリでPRを出す流れを体験させてもらう サイトのプロジェクトリストを参考に作業するリポジトリを探す ↑のREADMEやContribute.mdなどでルールを確認(大事) 1.の要領でPRを作成、修正、マージ PRの手順 基本的にはリポジトリのREADMEに沿って進めるだけです。5分もかかりませんでした。\n(様々な言語で翻訳されていて、コミュニティの大きさを感じます)\n簡単な手順は以下の通り。\nリポジトリをフォーク フォークしたリポジトリをクローンしてくる ブランチを作成 コードを変更してコミット Push PRを送る(githubで自分のリポジトリに行くとCompare \u0026amp; pull requestボタンが表示される) これで完了です!\n記念すべき人生初OSSコミットがこちら\n練習が終わったら本番 PRを出すまでの流れを実際に体験できたので、いよいよ他のOSSにPR出していくぞ!という流れなのですが、貢献したいコミュニティが最初から決まっている場合を除くとどこのリポジトリにどういう作業をさせてもらおうか悩む、というか目星をつけられなくて困ると思います。少なくとも私は困りました。\nですがその辺りもFirst Contributionsはカバーしてくれていて、ネクストステップとして取り組みやすいプロジェクトのリストを用意してくれています。(一番最初に貼ったURLと同じです)\nhttps://firstcontributions.github.io/\nここで自分で使っている言語や諸々で絞り込んで、気になったリポジトリのissue等を見ていくと、すぐに取り組めるタスクがあったりします。\n(もしくは実際に使ってみて、気になる箇所があればissueやそれに対するPRを立てたりもできます)\n私の場合は、興味があったリポジトリに誰でも取り組んで良い「ファイルごとのテストカバレッジを100%にする」issueが立っていたのでそれに着手しました。\n大体のリポジトリはREADMEやContribute.mdなどに貢献の方法やルールが明記されているのでまずはそれを見て、しっかりそれらを守りつつ作業することを心がけましょう(自戒)。\n記念すべき人生二度目OSSコミットがこちら\n余談 OSSコントリビューションというと花形のPRに目が行きがちですが、issueでのエラー報告も立派な貢献になるみたいです。言われてみれば確かに、実装中エラーに当たった時OSSのissueにはいつもお世話になってます。 カタカナ表記の場合、リポジトリ派閥とレポジトリ派閥があることに気がつきました。IT用語辞典などでも併記されているので、完全に好みの問題みたいです。 軽い気持ちでやったFirst Contributionsさんのお試しPRでしたが、大きな声では言えないですがこれひとつでfindyさんの偏差値が結構上がりました(!)。OSSへの貢献はエンジニアのハードルの一つなのかも知れないですね。 ","title":"初めてのOSS Contribute【First Contributions編】"},{"content":"最近やったこと DIY(初級) 人生初DIYで元々使ってた机をL字に改造しました。\n加工済みのいい感じのサイズの板買ってきてネジで止めただけの簡易机ながら結構快適。仕事も趣味も机に向かってやる系でオンオフの切り替え(というか机片付けてPCしまってiPad出して……の一連の作業)が面倒くさくて困ってたから、趣味の環境をL字の部分にそのまま広げて置くことで凄く楽になりました。\nブログ(ここ)の改装 見た目を若干弄りました。\nHTML, CSSに苦手意識を持っててあんまり積極的に触ってこなかったけど(仕事で必要な時にリファレンス見ればいいやの精神)、色々教えてもらってソース見たり弄ったりするのが楽しくなってきました。\nそのうちHUGOのテーマ作りたいですね。\n気になったもの crowdin crowdin - Agile localization for tech companies\n最近買ったDjango本で紹介されてたDjango Girlsのチュートリアル内で、翻訳を進めていくために使われてました。\nDjango Girlsのチュートリアル Django Girls(上とダブるけど)\nさっと見たけどめちゃくちゃわかりやすかったです。特にインターネットの仕組みあたり。\n人に教える機会があったらここおすすめしたいです。\nその他 新すばせかが楽しいです。指は死んでます。\n","permalink":"https://SawaTszm.github.io/post/diary-2021-08-05/","summary":"","title":"2021 08 05 Diary"},{"content":"目的 すごく今更\u0026amp;簡潔にだけど、python3.6以降で利用できる文字列フォーマットについてまとめていきます。\n(ずっとstr.format()を使っていたので戒めも兼ねて)。\nフォーマット済み文字列リテラルとは フォーマット済み文字列リテラル(f-string)では、文字列の先頭にfを付けることで、pythonの式を文字列内に{式}の形で埋め込むことができます。\n従来の書き方よりも簡潔、かつわかりやすく記述することができる書き方です。\n公式ドキュメント\n使い方 変数に入った数字を3文字のカンマ区切りにする hoge = 99999999 # 従来のstr.format() print(\u0026#34;{:,}\u0026#34;.format(hoge)) # フォーマット済み文字列リテラル print(f\u0026#34;{hoge:,d}\u0026#34;) :の後ろに整数をつけて縦を揃える tokuten = {\u0026#34;kokugo\u0026#34;: 9, \u0026#34;sugaku\u0026#34;: 81, \u0026#34;eigo\u0026#34;: 100} for sub, point in tokuten.items(): print(f\u0026#39;{sub:10} ==\u0026gt; {point:5d}\u0026#39;) # kokugo ==\u0026gt; 9 # sugaku ==\u0026gt; 81 # eigo ==\u0026gt; 100 まとめ 従来のstr.format()と比べると、f-stringは最終結果が人の目で見てもわかりやすいですね。\n","permalink":"https://SawaTszm.github.io/post/python-%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88%E6%B8%88%E3%81%BF%E6%96%87%E5%AD%97%E5%88%97%E3%83%AA%E3%83%86%E3%83%A9%E3%83%AB/","summary":"目的 すごく今更\u0026amp;簡潔にだけど、python3.6以降で利用できる文字列フォーマットについてまとめていきます。\n(ずっとstr.format()を使っていたので戒めも兼ねて)。\nフォーマット済み文字列リテラルとは フォーマット済み文字列リテラル(f-string)では、文字列の先頭にfを付けることで、pythonの式を文字列内に{式}の形で埋め込むことができます。\n従来の書き方よりも簡潔、かつわかりやすく記述することができる書き方です。\n公式ドキュメント\n使い方 変数に入った数字を3文字のカンマ区切りにする hoge = 99999999 # 従来のstr.format() print(\u0026#34;{:,}\u0026#34;.format(hoge)) # フォーマット済み文字列リテラル print(f\u0026#34;{hoge:,d}\u0026#34;) :の後ろに整数をつけて縦を揃える tokuten = {\u0026#34;kokugo\u0026#34;: 9, \u0026#34;sugaku\u0026#34;: 81, \u0026#34;eigo\u0026#34;: 100} for sub, point in tokuten.items(): print(f\u0026#39;{sub:10} ==\u0026gt; {point:5d}\u0026#39;) # kokugo ==\u0026gt; 9 # sugaku ==\u0026gt; 81 # eigo ==\u0026gt; 100 まとめ 従来のstr.format()と比べると、f-stringは最終結果が人の目で見てもわかりやすいですね。","title":"【Python】フォーマット済み文字列リテラル"},{"content":"lodashとは The Lodash library exported as a UMD module.\n(中略) \u0026hellip;Lodash makes JavaScript easier by taking the hassle out of working with arrays, numbers, objects, strings, etc.\n配列、数値、オブジェクト、文字列など、値を扱う際に便利な関数を多く提供しているJavaspriptのライブラリです。\n_.getや_.eachなどがそれ。\n公式ドキュメントがすごくわかりやすくていい感じです。\nlodash - github\n公式ドキュメント\n使い方 インポート import _ from \u0026#39;lodash\u0026#39;; 関数 _.get() _.get(object, path, [defaultValue]) objectのpathの値を取得する。値を解決できなかった場合、defaultValueを返す。\n_.has() _.has(object, path) objectのpathの値が存在するかを調べる。値自体は返さない。\n_.set() _.set(object, path, value) objectのpathにvalueの値をセットする。\npathが定義されていない場合は新しく作られる。\nインデックスのプロパティがない場合は配列が作成され、それ以外のプロパティがない場合はオブジェクトが作成される。(?)\n_.each() -\u0026gt; forEach() _.forEach(collection, [iteratee=_.identity]) collectionの要素を反復し、各要素に対してiterateeを実行。\niterateeは3つの引数(value, index|key, collection)で呼び出される。\n※iteratee関数は明示的にfalseを返すことで反復を終わらせることができる\n_.flatten() _.flatten(array) arrayを一段分フラットにする。非破壊的メソッド。\n(例:[1, [2, [3, [4]], 5]]を[1, 2, [3, [4]], 5]に)\n全部フラットにする_.flattenDeep(array)や任意の深さをフラットにする_.flattenDepth(array, [depth=1])もある。\n_.isNil() _.isNil(value) valueの値がnullか、もしくは未定義かをチェックする。\nsortBy() _.sortBy(collection, [iteratees=[_.identity]]) // 例:_.sortBy(users, [\u0026#34;id\u0026#34;, \u0026#34;name\u0026#34;]) id-\u0026gt;nameの順でソート 要素の配列を作成する。非破壊的メソッド。\n","permalink":"https://SawaTszm.github.io/post/javascript-lodash/","summary":"lodashとは The Lodash library exported as a UMD module.\n(中略) \u0026hellip;Lodash makes JavaScript easier by taking the hassle out of working with arrays, numbers, objects, strings, etc.\n配列、数値、オブジェクト、文字列など、値を扱う際に便利な関数を多く提供しているJavaspriptのライブラリです。\n_.getや_.eachなどがそれ。\n公式ドキュメントがすごくわかりやすくていい感じです。\nlodash - github\n公式ドキュメント\n使い方 インポート import _ from \u0026#39;lodash\u0026#39;; 関数 _.get() _.get(object, path, [defaultValue]) objectのpathの値を取得する。値を解決できなかった場合、defaultValueを返す。\n_.has() _.has(object, path) objectのpathの値が存在するかを調べる。値自体は返さない。\n_.set() _.set(object, path, value) objectのpathにvalueの値をセットする。\npathが定義されていない場合は新しく作られる。\nインデックスのプロパティがない場合は配列が作成され、それ以外のプロパティがない場合はオブジェクトが作成される。(?)\n_.each() -\u0026gt; forEach() _.forEach(collection, [iteratee=_.identity]) collectionの要素を反復し、各要素に対してiterateeを実行。\niterateeは3つの引数(value, index|key, collection)で呼び出される。\n※iteratee関数は明示的にfalseを返すことで反復を終わらせることができる\n_.flatten() _.flatten(array) arrayを一段分フラットにする。非破壊的メソッド。","title":"Lodashの概要と関数まとめ"},{"content":"目的 バッチ処理もAWS Lambdaで書きたいので、SAM テンプレートに記述できるのかどうかを調べたい。\n結論 できます。\nし、かなりわかりやすいです。\nCloudWatch イベント アプリケーションの AWS SAM テンプレート\n記述例 AWSTemplateFormatVersion: \u0026#34;2010-09-09\u0026#34; Transform: AWS::Serverless-2016-10-31 Globals: Function: Timeout: 30 MemorySize: 256 Handler: app.lambda_handler Runtime: python3.7 Resources: ### Batch ### HogeBatchFunction: Type: AWS::Serverless::Function Properties: CodeUri: api/batch/hoge_batch Events: HogeBatch: # TypeをScheduleに Type: Schedule Properties: # 実行タイミングを決める Schedule: cron(0 0 ? * SUN *) 最後のSchedule式は、rateとcronのどちらでも使えます。\nRate または Cron を使用したスケジュール式\n参考 ざっと見て参考にさせてもらいたいなと思った記事(と公式ドキュメント):\nWhat Is the AWS Serverless Application Model (AWS SAM)?\nチュートリアル: CodeDeploy および AWS サーバーレスアプリケーションモデル を使用して更新された Lambda 関数をデプロイする\nAWS SAM を使う前に CloudFormation テンプレートを書こう - Qiita\n","permalink":"https://SawaTszm.github.io/post/aws-sam-template/","summary":"","title":"【AWS SAM】テンプレートでCloudWatchイベントを記述する"},{"content":"目的 社内お勉強会で DDD 本を輪読することになったんですが、\n改めて「〇〇ってわかりますか?」と言われると戸惑ってしまうことが多いので自分用にまとめました。\n抽象クラス(abstract class) 他のクラスで継承してもらうことを前提としたクラス。\n複数のクラスの共通処理の中に、一部異なる処理を使用したい場合などに定義する。\n抽象クラス自体はインスタンス化できない abstract functionで抽象メソッドを定義できる インターフェース クラスが実装するメソッドを定義することができるもの。\nメソッドの実体は持てない(定義のみ) 使用できる修飾子はpublicのみ 定数を持てる。実装先のクラスでのオーバーライドはできない\n不特定のクラスで、共通のメソッドを定義したい場合などに定義する。 ポリモーフィズム 「中に入るものによって、同じ関数でも違う処理を行える」というオブジェクト指向プログラミングの特徴のこと。\n「モノが「そのモノ」らしく振る舞うこと」 =「呼び出した関数が、呼び出し元のオブジェクトに適した振る舞いをすること」\n# 動物は必ず「鳴く」 interface Animal { sound(); } # 犬は「動物らしい振る舞い」をする(鳴く) class dog implements Animal { sound() { /**/ } } # 動物は「鳴く」ので、引数の動物ごとの異なる鳴き声を処理する # 引数で与えられる動物によって、異なる処理(鳴き声)ができる public function animalsound(animal) { animal.sound() } 継承 親クラスの振る舞いを引き継いで、子クラスを実装すること。 子クラス側で親クラスを拡張することができる。\n委譲 実際の振る舞いを別のオブジェクトに委ねることで、別のオブジェクトの振る舞いを再利用する手法。(?)\nカプセル化 関連のあるデータとその使い方を一まとめにしたもの。 内部のデータを直接いじることはさせずに、使い方だけを見せる。\nGoF デザインパターン 23 種類あるヤツ(雑)\n勉強します\n3 分でわかるデザインパターン入門\nSOLID 原則 SOLID 原則とは Robert C. Martin によって提唱された 5 つのガイドライン。\nこれらのガイドライン(原則)に則ることで、開発者にとって読みやすく、メンテナンスが可能なプログラムを作成しやすくなる。\nRobert C. Martin:\n「ボブおじさん」の通称で知られる(?)ソフトフェア技術者・インストラクター。\nアジャイル宣言の著者の一人。\n「プログラマが知るべき 97 のこと」でもいくつかエッセイを書いている。\n5 つの原則 S:SRP、単一責任の原則\n→ クラスその他諸々が負う責任は一つにしようね O:OCP、解放閉鎖の原則\n→ 修正時に既存のロジックを弄らないといけない実装は駄目だよ L:LSP、リスコフの置換原則\n→ サブクラスとスーパークラスを入れ替えても動くように設計してね I:ISP、インタフェース分離の原則\n→ 使用しないメソッドをクラスに強要するインターフェースを作らないでね D:DIP、依存性逆転の原則 単一責任の原則(SRP) クラスは1つのことだけ責任を負うべき。\nもし複数の責任を負っている場合、それらは連動してしまう。\n※この原則はクラスだけでなく、ソフトフェアコンポーネントやマイクロサービスにも当てはまる。\n違反する例 # プロパティ管理とDB管理の二つの責任を持ってしまっているクラス class Animal { constructor(name: string) { } getAnimalName() { } saveAnimal(a: Animal) { } SRP に一致する改善案 class Animal { constructor(name: string) { } getAnimalName() { } } class AnimalDB { getAnimal(a: Animal) { } saveAnimal(a: Animal) { } } 解放閉鎖の原則(OCP) ソフトウェアのエンティティ(クラス、モジュール、関数)は、拡張に対して開き、修正に対して閉じていなければならない。(?)\n→ ロジックのパターンが増える度に既存の処理を修正 or 追記しなくちゃいけないような書き方は避ける。\n違反する例 class Animal { constructor(name: string) { } getAnimalName() { } } # animalリストを順に処理し、泣き声を出す const animals: Array\u0026lt;Animal\u0026gt; = [ new Animal(“lion”), new Animal(“mouse”) ]; # animalsが更新されるごとに修正を入れないといけない # animalsの修正に対して「閉じていない」関数 function AnimalSound(a: Array\u0026lt;Animal\u0026gt;) { for(int i = 0; i \u0026lt;= a.length; i++) { if(a[i].name == “lion”) log(“gaogao”) if(a[i].name == “mouse”) log(“chu”) } } AnimalSound(animals); OCP に一致する例 # Animalに仮想メソッドmakeSound()を宣言 # 各々の動物に各々のmakeSound()が実装されるので、 # 新しい動物が増える度にAnimalSound()を変更する必要はない class Animal { makeSound(); # ... } class Lion extends Animal { nameSound() { return “gaogao” } } class mouse extends Animal { nameSound() { return “chu” } } # お好きなアニマルをanimalsに突っ込む fanction AnimalSound(a: Array\u0026lt;Animal\u0026gt;) { for(int i = 0; i \u0026lt;= a.length; i++) { log(a[i].makeSound()); } } AnimalSound(animals); リスコフの置換原則(LSP) サブクラスは、そのスーパークラスで代用可能でなければならない。\n違反している例 # 全部のAnimalの型を見て、それに関連するLegCountを呼び出す必要がある # コードでクラスの型をチェックしていたら、LSPに違反している場合が多い # OCPにも違反している function AnimalLegCount(a: Array\u0026lt;animal\u0026gt;) { for(int i = 0; i \u0026lt;= a.length; i++) { if(typeof a[i] == Lion) log(LionLegCount(a[i])); if(typeof a[i] == Mouse) log(MouseLegCount(a[i])); if(typeof a[i] == Snake) log(SnakeLegCount(a[i])); } } AnimalLegCount(animals); LSP に一致した例 # OCPに一致させるために仮想メソッドを定義 class Animal { LegCount(); # ... } # Animal型が通過しても気にせず、ただLegCountメソッドを呼び出すだけ function AnimalLegCount(a: Array\u0026lt;Animal\u0026gt;){ for(let i = 0; i \u0026lt;= a.length; i++) { a[i].LegCount() } } AnimalLegCount(animals); (この例だと OCP の解決法とほぼ一緒なのでは……)\nインターフェース分離の原則(ISP) 顧客に特化した細粒度のインターフェースを作る。\n顧客は、自分たちが使わないインターフェースに依存することを強いられるべきではない。\n違反する例 interface ISape { drawCircle(); drawSquare(); drawRectagle(); } # 円しか書かないのにdrawSquare()、drawRectagle()を実装しないといけない class Circle implements IShape { drawCircle(){ /**/ } drawSquare(){ /**/ } drawRectangle(){ /**/ } } ISP に一致する例 interface IShape { draw(); } interface Icicle() { drawCicle(); } interface ISquare { drawSquare(); } class Circle implements ICircle { drawCicle() { /**/ } } # もしくは、IShapeを継承してお好きなdrawを組み立てる 依存性逆転の原則(DIP) 依存性は、具体化ではなく抽象化でなければならない。\n具体的な依存性の問題点:\n依存元を修正するとき、依存先も修正する必要がある\n単体テストの範囲が大きくなりがち(場合によっては書けない)\nテストの範囲が大きくなる。失敗時の原因特定が難しくなる。\n違反している例(具体的な依存性)\nClass Speaker() { sound() { /**/} } # この書き方をすることで、RadioTunerはSpeakerに強く依存している # (Speakerの事を直接「知ってしまっている」) # Speakerを修正する場合、RadioTunerも修正が必要になる class RadioTuner() { $speaker = new Speaker(); $speaker-\u0026gt;sound(); } DIP に一致する例 interface AudioOutput() { sound(); } # Speakerはinterfaceに依存 Class Speaker implements AudioOutput { sound() { /**/} } # RadioTunerもinterfaceに依存 # RadioTuner自体は、自分が実際に渡されているクラスを知らない # (ポリモーフィズムという) class RadioTuner { public function output(AudoiOutput $outputCircuit) { # sound()があることはinterfaceで保証されている $outputCircuit-\u0026gt;sound(); } } サービスコンテナ サービスコンテナ 5.8 Laravel\nLaravel のサービスコンテナは、クラス間の依存を管理する強力な管理ツールです。依存注入というおかしな言葉は主に「コンストラクターか、ある場合にはセッターメソッドを利用し、あるクラスをそれらに依存しているクラスへ外部から注入する」という意味で使われます。\nクラスのインスタンスを作ってくれるツール。 同じ文字列から、条件によって異なるクラスのインスタンスを生成することができる。\n使用することで、DI と呼ばれるデザインパターンを実現できてクラスの依存性が薄まるので、 単体テストがしやすくなるなどの恩恵が得られる。\nファザード ファサード(facade、「入り口」)はアプリケーションの サービスコンテナ に登録したクラスへ、「静的」なインターフェイスを提供します。Laravel のほとんどの機能に対して、ファサードが用意されています。Laravel の「ファサード」は、サービスコンテナ下で動作しているクラスに対し、\u0026ldquo;static proxy\u0026quot;として動作しています。これにより伝統的な静的メソッドよりもテストの行いやすさと柔軟性を保ちながらも、簡潔で記述的であるという利点があります。\nLaravel くんが用意してくれている便利なメソッド集(曲解)。\nDB ファザードであれば、DB の操作に便利なメソッドがたくさんある(DB::hogehoge)\n参考 開発者が知っておくべき SOLID の原則 | POSTD\nGetting a SOLID start. - Clean Coder\n","permalink":"https://SawaTszm.github.io/post/ddd-%E5%89%8D%E6%8F%90%E7%9F%A5%E8%AD%98%E3%81%BE%E3%81%A8%E3%82%81/","summary":"目的 社内お勉強会で DDD 本を輪読することになったんですが、\n改めて「〇〇ってわかりますか?」と言われると戸惑ってしまうことが多いので自分用にまとめました。\n抽象クラス(abstract class) 他のクラスで継承してもらうことを前提としたクラス。\n複数のクラスの共通処理の中に、一部異なる処理を使用したい場合などに定義する。\n抽象クラス自体はインスタンス化できない abstract functionで抽象メソッドを定義できる インターフェース クラスが実装するメソッドを定義することができるもの。\nメソッドの実体は持てない(定義のみ) 使用できる修飾子はpublicのみ 定数を持てる。実装先のクラスでのオーバーライドはできない\n不特定のクラスで、共通のメソッドを定義したい場合などに定義する。 ポリモーフィズム 「中に入るものによって、同じ関数でも違う処理を行える」というオブジェクト指向プログラミングの特徴のこと。\n「モノが「そのモノ」らしく振る舞うこと」 =「呼び出した関数が、呼び出し元のオブジェクトに適した振る舞いをすること」\n# 動物は必ず「鳴く」 interface Animal { sound(); } # 犬は「動物らしい振る舞い」をする(鳴く) class dog implements Animal { sound() { /**/ } } # 動物は「鳴く」ので、引数の動物ごとの異なる鳴き声を処理する # 引数で与えられる動物によって、異なる処理(鳴き声)ができる public function animalsound(animal) { animal.sound() } 継承 親クラスの振る舞いを引き継いで、子クラスを実装すること。 子クラス側で親クラスを拡張することができる。\n委譲 実際の振る舞いを別のオブジェクトに委ねることで、別のオブジェクトの振る舞いを再利用する手法。(?)\nカプセル化 関連のあるデータとその使い方を一まとめにしたもの。 内部のデータを直接いじることはさせずに、使い方だけを見せる。\nGoF デザインパターン 23 種類あるヤツ(雑)\n勉強します\n3 分でわかるデザインパターン入門\nSOLID 原則 SOLID 原則とは Robert C.","title":"【DDD】前提知識まとめ"},{"content":"目的 docker-composeで立てたnginxをhttps対応にしたい。\nあくまでも開発環境用なのでオレオレ証明書です。\n手順 自己署名証明書をサクッと作成する ❯ openssl req -x509 -nodes -new -keyout server.key -out server.crt -days 365 docker-composeの更新 443ポートを使用するように変更。\nまた、作成した証明書も読み込めるようにvolumesも更新。\nversion: \u0026#34;3.5\u0026#34; services: web: build: ./docker/nginx restart: always ports: - 443:443 # 変更 depends_on: - app volumes: - ./:/var/www/html - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf - ./docker/nginx/server.crt:/etc/nginx/server.crt # 追加 - ./docker/nginx/server.key:/etc/nginx/server.key # 追加 links: - app networks: - default default.confの更新 ポートを443に変更し、証明書の情報を追加します。\nserver { listen 443; ssl on; ssl_certificate /etc/nginx/server.crt; ssl_certificate_key /etc/nginx/server.key; index index.php index.html; server_name php-docker.local; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /var/www/html/laravel/public; location / { try_files $uri $uri/ @laravel; } 立ち上げ ❯ docker-compose down \u0026amp;\u0026amp; docker-compose up -d ❯ docker-compose ps Name Command State Ports -------------------------------------------------------------------------------------------------------------------- web_1 nginx -g daemon off; Up 0.0.0.0:443-\u0026gt;443/tcp オレオレ証明書なので接続時に警告が出ますが、ひとまずこれでhttpsでの接続が可能になりました。\n【補足】laravel-admin対応 環境変数の更新 .envのAPP_URLを更新します。\nAPP_URL=https://~~~\nちなみに実際の作業時、ここをちゃんとhttpsにはしてたんですが、お試しデプロイ時にlocalhostにしたままにしてしまって遷移先が全部つながらずフフ……となるなどしました。\n設定ファイルの更新 larave-adminの遷移先URLもhttpsにするため、confit/admin.phpも修正。\n\u0026#39;https\u0026#39; =\u0026gt; env(\u0026#39;ADMIN_HTTPS\u0026#39;, TRUE), 参考にさせていただいたもの オレだよオレオレ認証局で証明書つくる - Qiita\nNginx on DockerでHTTPS接続できるローカルサーバーを用意する - Tomcky’s blog\nこれも大事:\nオレオレ証明書を使いたがる人を例を用いて説得する - Qiita\n","permalink":"https://SawaTszm.github.io/post/docker-nginx-ssl-on-server/","summary":"","title":"【Docker】【nginx】docker-compose上のnginxをhttps対応する(開発環境編)"},{"content":"割と大量のデータを別の場所に転送したい。といった要件があり、諸々模索している最中で、先輩から教えてもらったEmbulkを触ってみたのでまとめました。\nEmbulkとは GitHub - embulk/embulk: Embulk: Pluggable Bulk Data Loader.\nさまざまなストレージ、データベース、NoSQL、クラウドサービス間のデータ転送を支援する並列バルクデータローダーです。\n関数を追加するプラグインをサポートしており、インプット先/アウトプット先に沿ったプラグインを適宜使用する/作成することで、前述の様々なストレージやDBなどでデータ転送を行うことができます。\nインストール Brewでインストール可能です。\n$ brew install embulk # embulk: Java 1.8 is required to install this formula. と言われたらエラー文通り下記でJava入れてもう一回 $ brew cask install homebrew/cask-versions/adoptopenjdk8 必要だなと思ったプラグインをプラグイン一覧から確認してインストール。\n# CSVインポート $ embulk gem install embulk-input-jdbc # mysqlインポート $ embulk gem install embulk-input-mysql # mysqlアウトプット $ embulk gem install embulk-output-mysql # などなど チュートリアル 公式ドキュメントに乗っている、めちゃくちゃ簡単な動作確認チュートリアルです。\nCSVを読み込んで画面に表示するだけの簡単なものになっています。\n# サンプルCSVファイル、構成ファイルを作成 $ embulk example ./try1 # 推測プラグインを呼び出して適切な構成ファイル(提案)を出力。 $ embulk guess ./try1/seed.yml -o config.yml # インプット側から引っ張ってこれるデータを確認 $ embulk preview config.yml # 実行!(csvから読み込んで画面に表示するだけ) $ embulk run config.yml Embulkではバルクデータロードを定義するために、yamlファイルを使います。\nサンプルはこんな感じ:\nin: # インプットプラグインオプション type: file path_prefix: ./mydata/csv/ decoders: - {type: gzip} parser: charset: UTF-8 newline: CRLF type: csv delimiter: \u0026#39;,\u0026#39; quote: \u0026#39;\u0026#34;\u0026#39; escape: \u0026#39;\u0026#34;\u0026#39; null_string: \u0026#39;NULL\u0026#39; skip_header_lines: 1 columns: - {name: id, type: long} - {name: account, type: long} - {name: time, type: timestamp, format: \u0026#39;%Y-%m-%d %H:%M:%S\u0026#39;} - {name: purchase, type: timestamp, format: \u0026#39;%Y%m%d\u0026#39;} - {name: comment, type: string} filters: - type: speedometer speed_limit: 250000 out: # アウトプットプラグインオプション type: stdout Liquidテンプレートエンジン を使用してこの構成ファイルに環境変数を埋め込むこともできるけど、実験的な機能なので変更される可能性があるとのこと。\nまた、同じように別の構成ファイルを含めることもできるらしいです。\nこれらのためにテンプレートエンジンを使用するには、設定ファイルの末尾をyml.liquidにする必要があります。\n(今回はこの二つは割愛)\nembulk-input-dynamodbをローカルから試してみる プラグインを作ってくださっている方がいらっしゃったので使わせていただきました!\nGitHub - lulichn/embulk-input-dynamodb\n構成ファイル なぜかauth_method : envとauth_method : profileは上手く行かなかったので(後述)、ローカルでの動作確認時は直書きのauth_method : basicでやってます。\nIAMロールが設定されているものの上で動かすのであれば、credentials情報などは不要らしいです。\nin: type: dynamodb auth_method: basic # IAMロールが設定されていればこの辺りは不要 access_key_id: *** # 同上 secret_access_key: *** # 同上 table: dynamodb-table-name region: ap-northeast-1 scan: total_segment: 20 # 要確認 scan_limit: 10000 record_limit: 10 columns: - {name: user_id, type: long} - {name: name, type: string} out: type: stdout # 画面に出力する embulk previewでインプット内容を確認します。\n(今回は画面上にアウトプットするだけなので、embulk runでも大丈夫だと思います)\n$ embulk preview config.yml # 上記でplugin is not found 的なエラーが出た時は下記を実行(\u0026lt;\u0026gt;内は適宜書き換えて下さい) $ embulk preview -I /Users/\u0026lt;user\u0026gt;/.embulk/lib/gems/gems/embulk-input-dynamodb-\u0026lt;varsion\u0026gt;/lib config.yml 無事指定したテーブルの項目が表示されたら成功です!\nハマったところ 実行時にInputPlugin 'dynamodb' is not foundになる 最初は以下の方法でpreviewしようとしていましたが、エラーが出てしまいました。\n$embulk preview config.yml エラー:\nError: InputPlugin \u0026#39;dynamodb\u0026#39; is not found. org.jruby.proxy.org.embulk.config.ConfigException$Proxy1: Unknown input plugin \u0026#39;dynamodb\u0026#39;. embulk/input/dynamodb.rb is not installed. Run \u0026#39;embulk gem search -rd embulk-input\u0026#39; command to find plugins. インストールはしているはずだけど、もしかして見にいっている場所が違う?と思ったら割とビンゴでした。\nこの実行時のログではGem's home and path are set by default: \u0026quot;/var/root/.embulk/lib/gems\u0026quot;と出ていて、プラグインをインストールした先(私の場合は/Users/\u0026lt;user\u0026gt;/.embulk/lib/gems/)とは異なる場所を参照していたため、そんなものはない!と認識されてしまっていたようです。\nそのため、最初の一回は使用しているプラグインのパスを明示的に渡してあげる必要があります。\n$embulk preview -I /Users/\u0026lt;user\u0026gt;/.embulk/lib/gems/gems/embulk-input-dynamodb-\u0026lt;varsion\u0026gt;/lib config.yml 一度実行が通ってくれた後は、Gem's home and path are set by defaultが上記で設定したパスの方を見にいってくれるようになり、$ embulk preview config.ymlでも実行できるようになりました。\nAWS認証情報渡す部分 embulk-input-dynamodbではAWS認証情報を受け取る方法を選ぶことができるのですが、やってみようと思ったenv, profileでエラーが発生し、トラブルシューティングがしきれなかったので一旦上記のbasicで試しました。\n(結構初歩的な部分でつまづいている気もするました……)\n最初profileでAWS認証情報を取得しようとした構成ファイル:\nin: type: dynamodb auth_method: profile profile_file: ~/.aws/credentials profile_name: default table: dynamodb-table-name region: ap-northeast-1 # 以下同じ エラー:\nError: java.lang.IllegalArgumentException: ~/.aws/credentials **追記:**こちらご指摘いただいて解決しました!ありがとうございます!\nyamlファイルでは~/.aws/credentialsの~の部分を解決してくれないので(これはシェル側の機能)、明示的に渡してあげる必要があります。\n絶対パスで記述し直すか、環境変数を使用して~の部分を渡してあげる形にすると通るようになります。\n次envで認証情報を取得しようとした構成ファイル:\nin: type: dynamodb auth_method: env table: dynamodb-table-name region: ap-northeast-1 # 以下同じ エラー:\nError: Unable to load AWS credentials from environment variables (AWS_ACCESS_KEY_ID (or AWS_ACCESS_KEY) and AWS_SECRET_KEY (or AWS_SECRET_ACCESS_KEY)) ($envで確かめてみたけどちゃんと環境変数には定義できていた)\nまとめ めちゃくちゃ触りだけをやりましたが、Embulk素敵ですね。\nあとはこれをAWS上で定期実行するためにどうするかを調べて行こうかなと思います。\n","permalink":"https://SawaTszm.github.io/post/embulk-install-and-dynamodb-import/","summary":"","title":"【Embulk】インストール&dynamoDBのインポートを試してみる"},{"content":"目的 ここ最近、しばらくlaravel-adminという管理画面を作成するためのライブラリを使っていたので、調べたことやつまづいたところも含めて少しずつ書き起こそうと思います。\nまずはインストール編です。簡単に管理画面を確認できるところまで見ていきましょう。\nlaravel-adminとは laravelで簡単にDBの管理画面を作成することができるライブラリです。\nドキュメントやデモサイトなど使用するために必要な資料が充実しており、難しいカスタムを行う必要がなければものすごく簡単に管理画面が構築できます。\nLaravel-admin(ドキュメント)\nGitHubページ\n基本的な使用方法は上記でカバーし、カスタマイズして使用したい際には直接ソースコードを読んで適宜書き換えていく形になります。\n主観ですが、コード内のコメントも(おそらく書き換える前提の部分は)丁寧に書かれているので、しっかり読み解けば問題ないかと思います。\nプロジェクトの作成 既に開発しているlaravelプロジェクトに追加する場合は、この章は飛ばしてもらって大丈夫です。\n何もないところからlaravel-adminを試したい方は、まずlaravelプロジェクトを作成するところから始めましょう。\n公式によると、現在のバージョンでは以下の環境が推奨されるようです。\nPHP 7+ laravel 5.5+ This package requires PHP 7+ and Laravel 5.5, for old versions please refer to 1.4\nlaravel-admin install\n$composer create-project --prefer-dist \u0026#34;laravel/laravel=5.5.*\u0026#34; \u0026lt;project-name\u0026gt; DBも必要になってくるので、.envにDBの情報も書き足しておきましょう。\nよければこちらの記事も参考にしてみてください。\n【Laravel+MySQL+nginx】docker-composeで最小構成の環境構築 - SawaLog\nインストール laravelの準備ができたら早速laravel-adminをインストールします。\n$composer require encore/laravel-admin インストールが終わったら下記コマンドを実行します。\n$php artisan vendor:publish --provider=\u0026#34;Encore\\Admin\\AdminServiceProvider\u0026#34; $php artisan admin:install これらを実行すると、app/Adminディレクトリが作られます。これからの実装はこのディレクトリ配下で行うことになります。\nファイルの初期配置は以下。\napp/Admin ├── Controllers │ ├── ExampleController.php │ └── HomeController.php ├── bootstrap.php └── routes.php フロント周りのファイルは/public/packages/adminに置かれています。\n構成ファイルはconfig/admin.phpです。後々触ることになります。\nここまでで既にダッシュボードは作成されているので、php artisan serveなどをして、http://localhost:8000/admin にアクセスしてみましょう。\nID・PASSどちらにもadminと入力し、無事ダッシュボードが表示されれば成功です。\n早速DBテーブルの管理画面を作成していきましょう。\nモデル・コントローラ作成 laravelでDBテーブルを認識するためにモデルを作成します。\n$php artisan make:model Recipe モデルが作成されたのを確認したら、それを利用してAdmin用のコントローラを作成します。\n$php artisan admin:make RecipeController --model=App\\\\Recipe 成功すると、作成したコントローラのルーティング情報がターミナルに出力されます。\nこれをapp/Admin/routes.phpに記述しましょう。\n$router-\u0026gt;resource(\u0026#39;admin/recipes\u0026#39;, RecipeController::class); 上記ルーティング情報のURLを叩くと、それらしい画面が表示されていると思います。\nあとは作成したAdmin用のコントローラを、ドキュメントを参考にしながら更新していく流れになります。\n現在仕様として提供されているのは以下のページです。\n一覧画面(grid関数) 詳細画面(show関数) 新規作成・編集画面(form関数) それぞれドキュメントに基本の使用方法からカスタマイズ方法まで乗っていますので、一通り目を通すことをお勧めします。\nまとめ とても簡単に導入できるので、気になっている方は一度試して見ると面白いかも知れません。\nその他、主にカスタマイズ部分でつまづくことが多かったので、少しずつ記事にして行こうかと思います。\n参考 Laravel-admin(ドキュメント)\nlaravel-admin(GitHub)\n","permalink":"https://SawaTszm.github.io/post/laravel-admin-install/","summary":"目的 ここ最近、しばらくlaravel-adminという管理画面を作成するためのライブラリを使っていたので、調べたことやつまづいたところも含めて少しずつ書き起こそうと思います。\nまずはインストール編です。簡単に管理画面を確認できるところまで見ていきましょう。\nlaravel-adminとは laravelで簡単にDBの管理画面を作成することができるライブラリです。\nドキュメントやデモサイトなど使用するために必要な資料が充実しており、難しいカスタムを行う必要がなければものすごく簡単に管理画面が構築できます。\nLaravel-admin(ドキュメント)\nGitHubページ\n基本的な使用方法は上記でカバーし、カスタマイズして使用したい際には直接ソースコードを読んで適宜書き換えていく形になります。\n主観ですが、コード内のコメントも(おそらく書き換える前提の部分は)丁寧に書かれているので、しっかり読み解けば問題ないかと思います。\nプロジェクトの作成 既に開発しているlaravelプロジェクトに追加する場合は、この章は飛ばしてもらって大丈夫です。\n何もないところからlaravel-adminを試したい方は、まずlaravelプロジェクトを作成するところから始めましょう。\n公式によると、現在のバージョンでは以下の環境が推奨されるようです。\nPHP 7+ laravel 5.5+ This package requires PHP 7+ and Laravel 5.5, for old versions please refer to 1.4\nlaravel-admin install\n$composer create-project --prefer-dist \u0026#34;laravel/laravel=5.5.*\u0026#34; \u0026lt;project-name\u0026gt; DBも必要になってくるので、.envにDBの情報も書き足しておきましょう。\nよければこちらの記事も参考にしてみてください。\n【Laravel+MySQL+nginx】docker-composeで最小構成の環境構築 - SawaLog\nインストール laravelの準備ができたら早速laravel-adminをインストールします。\n$composer require encore/laravel-admin インストールが終わったら下記コマンドを実行します。\n$php artisan vendor:publish --provider=\u0026#34;Encore\\Admin\\AdminServiceProvider\u0026#34; $php artisan admin:install これらを実行すると、app/Adminディレクトリが作られます。これからの実装はこのディレクトリ配下で行うことになります。\nファイルの初期配置は以下。\napp/Admin ├── Controllers │ ├── ExampleController.php │ └── HomeController.php ├── bootstrap.","title":"【laravel-admin】インストール&画面作成まで 編"},{"content":"起こった問題 タイトルの通り、Laravelで使用するDBのhostをRead/Weiteで切り替えたい、と思って設定をしていました。\n設定後下記を確認して、\n\u0026gt;\u0026gt;\u0026gt; config(\u0026#39;database.connections.pgsql\u0026#39;) =\u0026gt; [ \u0026#34;read\u0026#34; =\u0026gt; [ \u0026#34;host\u0026#34; =\u0026gt; [ \u0026#34;postgres2\u0026#34;, ], ], \u0026#34;write\u0026#34; =\u0026gt; [ \u0026#34;host\u0026#34; =\u0026gt; \u0026#34;postgres\u0026#34;, ], ... 反映されてるな、と思って念の為connectionも見てみました。\n\u0026gt;\u0026gt;\u0026gt; DB::connection(\u0026#39;pgsql::read\u0026#39;)-\u0026gt;getConfig(); =\u0026gt; [ ..., \u0026#34;host\u0026#34; =\u0026gt; \u0026#34;postgres\u0026#34;, ] ……あれ?\nReadコネクションなのでpostgres2であって欲しいのに、postgresが出てきてしまいました。\n反映されてないのかな?と思い色々調べたので、備忘録として置いて起きます。\n調べたこと getConfigで参照されるconfigは、\nIlluminate\\Database\\Connectors\\ConnectionFactory::make内で、\n/** * Establish a PDO connection based on the configuration. * * @param array $config * @param string|null $name * @return \\Illuminate\\Database\\Connection */ public function make(array $config, $name = null) { $config = $this-\u0026gt;parseConfig($config, $name); if (isset($config[\u0026#39;read\u0026#39;])) { return $this-\u0026gt;createReadWriteConnection($config); } return $this-\u0026gt;createSingleConnection($config); } createReadWriteConnectionが呼び出され、\n/** * Create a read / write database connection instance. * * @param array $config * @return \\Illuminate\\Database\\Connection */ protected function createReadWriteConnection(array $config) { $connection = $this-\u0026gt;createSingleConnection($this-\u0026gt;getWriteConfig($config)); return $connection-\u0026gt;setReadPdo($this-\u0026gt;createReadPdo($config)); } その中でwrite用のconfigがセットされてるので、どう呼び出してもwriterのconfigが見える、というオチでした。\nまとめ ReadとWriteでconnectionインスタンスが切り替わってるわけではなさそうで、「Readコネクションの向き先が正しく設定できているかどうか」はDB::connection('pgsql::read')-\u0026gt;getConfig();ではわからない、ということがわかりました。\nそのため、config('database.connections.pgsql')で確認できるhostが分かれていればヨシ!\n","permalink":"https://SawaTszm.github.io/post/laravel%E3%81%A7%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8Bdb%E3%82%92%E3%82%92readwrite%E6%A7%8B%E6%88%90%E3%81%AB%E3%81%99%E3%82%8B%E6%99%82%E3%81%AB%E3%81%A1%E3%82%87%E3%81%A3%E3%81%A8%E3%83%8F%E3%83%9E%E3%81%A3%E3%81%9F%E8%A9%B1/","summary":"起こった問題 タイトルの通り、Laravelで使用するDBのhostをRead/Weiteで切り替えたい、と思って設定をしていました。\n設定後下記を確認して、\n\u0026gt;\u0026gt;\u0026gt; config(\u0026#39;database.connections.pgsql\u0026#39;) =\u0026gt; [ \u0026#34;read\u0026#34; =\u0026gt; [ \u0026#34;host\u0026#34; =\u0026gt; [ \u0026#34;postgres2\u0026#34;, ], ], \u0026#34;write\u0026#34; =\u0026gt; [ \u0026#34;host\u0026#34; =\u0026gt; \u0026#34;postgres\u0026#34;, ], ... 反映されてるな、と思って念の為connectionも見てみました。\n\u0026gt;\u0026gt;\u0026gt; DB::connection(\u0026#39;pgsql::read\u0026#39;)-\u0026gt;getConfig(); =\u0026gt; [ ..., \u0026#34;host\u0026#34; =\u0026gt; \u0026#34;postgres\u0026#34;, ] ……あれ?\nReadコネクションなのでpostgres2であって欲しいのに、postgresが出てきてしまいました。\n反映されてないのかな?と思い色々調べたので、備忘録として置いて起きます。\n調べたこと getConfigで参照されるconfigは、\nIlluminate\\Database\\Connectors\\ConnectionFactory::make内で、\n/** * Establish a PDO connection based on the configuration. * * @param array $config * @param string|null $name * @return \\Illuminate\\Database\\Connection */ public function make(array $config, $name = null) { $config = $this-\u0026gt;parseConfig($config, $name); if (isset($config[\u0026#39;read\u0026#39;])) { return $this-\u0026gt;createReadWriteConnection($config); } return $this-\u0026gt;createSingleConnection($config); } createReadWriteConnectionが呼び出され、","title":"【Laravel】Laravelで使用するDBををReadWrite構成にする時の確認でちょっとハマった話"},{"content":"やりたいこと Laravel くんで Controller をすっきりさせたいので、バリデーションをフォームリクエストで行いたい。\nプラスで、簡単な条件分岐のバリデーションも付け足したい。\n結論 withValodatorメソッドを通してsometimesを使うのが良さげです。\n詳しく 通常のフォームリクエストでのバリデーション // FormRequest namespace App\\Http\\Request; use \\\\illuminate\\Foundation\\Http\\FormRequest; class ItemUpdateRequest extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } public function rules() { return [ \u0026#39;id\u0026#39; =\u0026gt; \u0026#39;required|integer\u0026#39;, \u0026#39;item_type\u0026#39; =\u0026gt; \u0026#39;required|string|in:tv,web,radio\u0026#39; \u0026#39;name\u0026#39; =\u0026gt; \u0026#39;required|string|max:255\u0026#39;, \u0026#39;url\u0026#39; =\u0026gt; \u0026#39;nullable|url|max:2083, \u0026#39;note\u0026#39; =\u0026gt; \u0026#39;nullable|string|max:2047\u0026#39;, ]; } } // Controller(必要な記述以外は省略) use App\\Http\\Request\\ItemUpdateRequest; class ItemController extends Controller { public function update(ItemUpdateRequest $request) { // } } これだけで通常のバリデーションは出来ますね。\nただ、例えばitem_type == 'web'の時だけurlカラムは必須にしたいとか、そういった簡単な条件付けは rules の中ではできません。\n条件付きのバリデーションの追加 じゃあどうするよ。前述の通り、withValidatorメソッドとsometimesを使います。\nメソッドについては、以下にそれらしいことが書いてあります。\nLaravel Validation\nsometimes は条件ごとに適応するルールを記載できるものなので、それを使用してフォームリクエストに下記メソッドを追加するだけ。\n/** * Configure the validator instance. * * @param \\Illuminate\\Validation\\Validator $validator * @return void */ public function withValidator($validator) { $validator-\u0026gt;sometimes(\u0026#39;url\u0026#39;, \u0026#39;required\u0026#39;, function ($input) { return $input[\u0026#39;item_type\u0026#39;] == \u0026#39;web\u0026#39;; }); } このフォームリクエストを継承して作る子クラスにもこのメソッド内の条件は引き継がれます。\nこの記述だと条件一つに対して一文が長くなってしまうので、条件分岐が多い/複雑な場合には向かないかもですが、ちょっとした分岐が必要な際には活用できると思います。\n","permalink":"https://SawaTszm.github.io/post/laravel-%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%A7%E3%81%AE%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AB%E6%9D%A1%E4%BB%B6%E4%BB%98%E3%81%8D%E3%81%AE%E5%88%B6%E7%B4%84%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B/","summary":"","title":"【Laravel】フォームリクエストでのバリデーションに条件付きの制約を追加する"},{"content":"やりたいこと データベース:ペジネーション 5.8 Laravel\nこのページの「独自ペジネータ作成」の欄にあるように、\nIlluminate\\Pagination\\LengthAwarePaginatorインスタンスを作成して、自前の Collection を Collection のままページネーションしたい。\n結論 ペジネーションは引数に Collection を許容しているので実装が可能。\nLengthAwarePaginatorインスタンスの第一引数に渡す Collection を、slice()メソッドを使って Collection の型を崩さずに区切る。\nこれだけ見ると「自明では?」と思うけど、初心者(私)はどハマりしたので過程も含めて書いておきます。\nハマった流れ まず「Eloquent ORM から取ってきた結果をページネーションしたいわね」と思い Laravel くんドキュメント(前述)を参照しました。\nNote: 自前でペジネーターインスタンスを生成する場合、ペジネーターに渡す結果の配列を自分で”slice”する必要があります。その方法を思いつかなければ、 [array_slice] PHP 関数を調べてください。\nなるほど!!!!!\nと思い array_slice()を使用して記述したのが以下のような書き方。\n// app/Services/ItemsService.php // 前略。$columnsには取得したいカラム名を格納 $items = ItemMaster::query() -\u0026gt;select($columns) -\u0026gt;with(\u0026#39;relatedUsers\u0026#39;) -\u0026gt;get(); // 表示する件数のみ取得するために、ページ番号($page)と最大表示件数($limit)から$offsetを計算 $offset = ($page * $limit) - $limit; // ドキュメントに言われたように表示する部分のみ切り取った配列を用意 $slice = array_slice($items-\u0026gt;toArray(), $offset, $limit); return new LengthAwarePaginator($slice, count($items), $limit, $page); これでも$columnsの値を参照する分には特に問題ありません。\nただ、return を受け取った先の Resource なんかでリレーションの情報が欲しくて$this-\u0026gt;relatedUsers...なんていうふうに書くとその時点でエラーになってしまいます。\n原因は$slice = array_slice($items-\u0026gt;toArray(), $offset, $limit);の部分で、collection 型だった$items を配列に戻してしまっているので、この時点でリレーションの情報は消えてしまっていると。\n(Collection から配列に変換する際、採用されるのは collection 内の attributes 部分だけ)\n解決した流れ 公式ドキュメントでarray_sliceを推しているということは、LengthAwarePaginatorには collection を渡せないのか……?\nと思いLengthAwarePaginatorの定義を見てみました。\n// LengthAwarePaginator.php class LengthAwarePaginator extends AbstractPaginator implements Arrayable, ArrayAccess, Countable, IteratorAggregate, JsonSerializable, Jsonable, LengthAwarePaginatorContract { // 略 /** * Create a new paginator instance. * * @param mixed $items * @param int $total * @param int $perPage * @param int|null $currentPage * @param array $options (path, query, fragment, pageName) * @return void */ public function __construct($items, $total, $perPage, $currentPage = null, array $options = []) { $this-\u0026gt;options = $options; foreach ($options as $key =\u0026gt; $value) { $this-\u0026gt;{$key} = $value; } $this-\u0026gt;total = $total; $this-\u0026gt;perPage = $perPage; $this-\u0026gt;lastPage = max((int) ceil($total / $perPage), 1); $this-\u0026gt;path = $this-\u0026gt;path !== \u0026#39;/\u0026#39; ? rtrim($this-\u0026gt;path, \u0026#39;/\u0026#39;) : $this-\u0026gt;path; $this-\u0026gt;currentPage = $this-\u0026gt;setCurrentPage($currentPage, $this-\u0026gt;pageName); $this-\u0026gt;items = $items instanceof Collection ? $items : Collection::make($items); } __constructを確認すると、任意の配列を受け取る第一引数は$itemsと定義されています。\nこの引数の初期化処理を見てみると、\n$this-\u0026gt;items = $items instanceof Collection ? $items : Collection::make($items);\n「collection で来たらそのまま格納して、そうじゃなかったら collection 型にして返す」。\nバリバリに collection 型を出す想定なので、引数に collection を渡しても大丈夫そうです。\nであれば後は、問題の箇所だったarray_sliceの collection バージョンがあれば万事解決ということ。\nコレクション 5.8 Laravel\nslice() Slice メソッドは指定したインデックスからコレクションを切り分けます。\nググれば一発ですね。\n解決後のコード // app/Services/ItemsService.php // 前略。$columnsには取得したいカラム名を格納 $items = ItemMaster::query() -\u0026gt;select($columns) -\u0026gt;with(\u0026#39;relatedUsers\u0026#39;) -\u0026gt;get(); // 表示する件数のみ取得するために、ページ番号($page)と最大表示件数($limit)から$offsetを計算 $offset = ($page * $limit) - $limit; // *collection型を崩さずに切り取る* $slice = $items-\u0026gt;slice($offset, $limit); // $sliceの中身はcollectionなので、この戻り値を受け取った先でもcollectionに対する操作が出来る return new LengthAwarePaginator($slice, count($items), $limit, $page); これで無事に Resource 側でもリレーションを参照できるようになりました。\nまとめ Collection に対する理解が浅かった&各動作の戻り値を意識しなかったために起きた悲劇でした。初心者のハマるポイントは誰にも予想ができない。\n(名称からして LengthAwarePaginator が slice 周りもサポートしてくれるものだと思ってたけど違うんですね)\nもし他に良い実装方法があれば教えて頂けると嬉しいです:)\nでは。\n","permalink":"https://SawaTszm.github.io/post/laravel-%E7%8B%AC%E8%87%AA%E3%83%9A%E3%82%B8%E3%83%8D%E3%83%BC%E3%82%BF%E3%81%A7%E8%87%AA%E5%89%8D%E3%81%AEcollection%E3%82%92%E4%BD%BF%E3%81%86/","summary":"","title":"【Laravel】独自ペジネータで自前のCollectionを使う"},{"content":"目的 laravel-admin使いたいだけの用途にLaradockは重すぎる……\nので、お勉強も兼ねて、docker-composeでLaravel\u0026amp;MySQLのみの環境を立てました。\nその上でlaravel-adminの管理画面まで開けるようにしてみます。\n構成 project_root_dir ├── docker-compose.yml ├── docker │ ├── nginx │ │ ├── Dockerfile │ │ └── default.conf │ ├── php │ │ └── Dockerfile │ └── db │ │ ├── my.cnf │ └── Dockerfile └── laravel └── ... 手順 docker-compose.ymlを作成 # docker-compose.yml version: \u0026#34;3.5\u0026#34; services: app: build: context: . dockerfile: ./docker/php/Dockerfile args: PROJECT_NAME: app_admin volumes: - ./:/var/www/html depends_on: - database links: - database ports: - \u0026#34;4000:80\u0026#34; - \u0026#34;4001:8080\u0026#34; tty: true database: image: mysql:5.7 restart: always env_file: .env_db ports: - \u0026#34;23306:3306\u0026#34; volumes: - \u0026#34;./docker/database/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d\u0026#34; - \u0026#34;./docker/database/my.cnf:/etc/mysql/conf.d/my.cnf\u0026#34; web: build: ./docker/nginx ports: - 80:80 depends_on: - app volumes: - ./:/var/www/html - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf links: - app appコンテナ設定 composerはもうここに含めます。\n# ./docker/php/Dockerfile FROM php:7-fpm COPY php.ini /usr/local/etc/php/ RUN apt-get update \u0026amp;\u0026amp; apt-get install -y \\ libfreetype6-dev libjpeg62-turbo-dev libpng-dev libmcrypt-dev libonig-dev \\ git vim unzip \\ \u0026amp;\u0026amp; docker-php-ext-install pdo_mysql mysqli gd iconv \\ \u0026amp;\u0026amp; apt-get clean # install composer RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer webコンテナ設定 # ./docker/nginx/Dockerfile FROM nginx:latest RUN apt-get update \u0026amp;\u0026amp; apt-get install -y \\ vim \\ unzip \\ zip \\ git 後々laravelディレクトリを作るので、設定ファイルのルートは/var/www/html/laravel/~にしておきます。\n# ./docker/nginx/default.conf server { listen 80; index index.php index.html; server_name php-docker.local; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /var/www/html/laravel/public; # ココ location / { try_files $uri $uri/ @laravel; } # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /var/www/html; } location ~ \\.php$ { try_files $uri $uri/ @laravel; fastcgi_split_path_info ^(.+\\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location @laravel { fastcgi_split_path_info ^(.+\\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME /var/www/html/laravel/public/index.php; // ココ fastcgi_param PATH_INFO $fastcgi_path_info; } } dbコンテナの設定 # docker/database/my.cnf [mysql] default-character-set=utf8mb4 [mysqld] sql-mode=\u0026#34;ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION\u0026#34; character-set-server=utf8mb4 collation-server=utf8mb4_general_ci [mysqld_safe] timezone = UTC default-time-zone = UTC 後はHOST情報などを.enb_db(docker-compose.ymlで指定したファイル)に記述する。\nMYSQL_DATABASE=[my_database_name] MYSQL_USERNAME=root MYSQL_PASSWORD= MYSQL_HOSTNAME=127.0.0.1 MYSQL_ROOT_PASSWORD= API_MYSQL_PORT=23306 起動&Laravelのインストール # 起動 $ docker-compose up -d # laravelプロジェクトの作成 $ docker-compose exec app /bin/bash app$ composer create-project --prefer-dist laravel/laravel laravel http://localhost/ でwelcomページが見られるようになる。\nLaravel環境変数ファイルの修正 laravel/.envを、DB情報を作成したdockerコンテナに合わせて修正。\nDB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=[my_database_name] DB_USERNAME=root DB_PASSWORD= laravel-adminをインストール composerを使用してインストールし、有効化する。 公式ドキュメントがかなりまとまっていて素敵です。\n$ docker-compose exec app /bin/bash app $ cd laravel app/laravel $ composer require encore/laravel-admin app/laravel $ php artisan vendor:publish --provider=\u0026#34;Encore\\Admin\\AdminServiceProvider\u0026#34; app/laravel $ php artisan admin:install http://localhost/admin/に接続して、ログイン画面が出ればおk!\nadmin/adminで入れます。\n補足:既にある開発環境のDBコンテナに接続する なんらかの理由で、管理画面開発に使用したいDBコンテナが既存のdocker-compose.ymlにある場合。\n(開発側はPythonでもりもり作業してるからLaravelのディレクトリ混ぜたくないとかそう言った場合)\n前提として、以下であれば比較的簡単に繋げられます。\nDBコンテナ側でなんらかのDockerNetworkを設定している 開発環境の方でもdocker-compose up -dを実行している (直接でも良いし、もしくは開発環境のリポジトリをサブモジュール として引っ張ってきて叩くなどする) 例えばtest-appという名前のnetworkを設定している↓のであれば、\n# 既存docker-compose.yml version: \u0026#34;3.5\u0026#34; services: database: hostname: database image: mysql:5.7 ~~~ networks: - default networks: default: name: test-app 管理画面側のdocker-compose.ymlでそれを使用するように書き換える↓\n# docker-compose.yml version: \u0026#34;3.5\u0026#34; services: app: build: context: . dockerfile: ./docker/php/Dockerfile args: PROJECT_NAME: recipe_app_admin restart: always volumes: - ./:/var/www/html ports: - \u0026#34;4000:80\u0026#34; - \u0026#34;4001:8080\u0026#34; tty: true networks: - default # dbコンテナの設定は不要になる web: build: ./docker/nginx restart: always ports: - 80:80 depends_on: - app volumes: - ./:/var/www/html - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf links: - app networks: - default networks: default: name: test-app external: true # 外部ファイルで設定していることを指定 後はよしなに環境変数ファイルを更新し、開発環境→管理画面開発環境の順にdocker-compose up -dを叩くだけです。\n","permalink":"https://SawaTszm.github.io/post/laravel+mysql+nginx-docker-compose%E3%81%A7%E6%9C%80%E5%B0%8F%E6%A7%8B%E6%88%90%E3%81%AE%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89/","summary":"目的 laravel-admin使いたいだけの用途にLaradockは重すぎる……\nので、お勉強も兼ねて、docker-composeでLaravel\u0026amp;MySQLのみの環境を立てました。\nその上でlaravel-adminの管理画面まで開けるようにしてみます。\n構成 project_root_dir ├── docker-compose.yml ├── docker │ ├── nginx │ │ ├── Dockerfile │ │ └── default.conf │ ├── php │ │ └── Dockerfile │ └── db │ │ ├── my.cnf │ └── Dockerfile └── laravel └── ... 手順 docker-compose.ymlを作成 # docker-compose.yml version: \u0026#34;3.5\u0026#34; services: app: build: context: . dockerfile: ./docker/php/Dockerfile args: PROJECT_NAME: app_admin volumes: - ./:/var/www/html depends_on: - database links: - database ports: - \u0026#34;4000:80\u0026#34; - \u0026#34;4001:8080\u0026#34; tty: true database: image: mysql:5.","title":"【Laravel+MySQL+nginx】docker-composeで最小構成の環境構築"},{"content":"エラー 外部キー制約を追加しようとした時、下記エラーで怒られました。\nERROR 1215 (HY000): Cannot add foreign key constraint “外部キー制約を追加できません”\nもっと詳細なエラーログが……ほしい……! と思ったので調べました。\nSHOW ENGINE INNODB STATUS で外部キー制約時のエラーを確認 恐らくとてつもなく初歩的な話だと思うのですが、SHOW ENGINE 構文なるものがあると。\nSHOW ENGINE INNODB STATUS SHOW ENGINE INNODB STATUSは、InnoDBストレージエンジンの状態に関するInnoDB標準モニターからの広範囲にわたる情報を表示します。\nMySQL :: MySQL 5.6 リファレンスマニュアル :: 13.7.5.16 SHOW ENGINE 構文\n便利だ!!!!!\n実践 早速入って見てみます。\n$ docker exec -it [docker-name] bash # mysql -u [username] -p \u0026gt; SHOW ENGINE INNODB STATUS ------------------------ LATEST FOREIGN KEY ERROR ------------------------ Cannot find an index in the referenced table where the referenced columns appear as the first columns, or column types in the table and the referenced table do not match for constraint. Note that the internal storage type of ENUM and SET changed in tables created with \u0026gt;= InnoDB-4.1.12, and such columns in old tables cannot be referenced by such columns in new tables. Please refer to http://dev.mysql.com/doc/refman/5.7/en/innodb-foreign-key-constraints.html for correct foreign key definition. “参照された列が最初の列として表示される参照された表にインデックスが見つからないか、テーブルの列タイプと参照された表が制約に一致しません”\nこの一文に沿って見てみたら、参照される側のテーブルの項目と参照するテーブルの項目が合っていませんでした。\nちなみにこのエラーの前は(調べる前に気がつきましたが)「参照される側のテーブルの項目は PRIMARY KEY でなくてはならない」と言うのを忘れて外部キーを設定しようとしてました。\n正月ボケだね〜フフと言いたいところですが、これは単純な初心者ボケ(ガチ)です。\n型を参照される側のテーブルの項目に合わせたら無事設定できました。\n参考にさせて頂いたもの お世話になりました。\nMySQL :: MySQL 5.6 リファレンスマニュアル :: 13.7.5.16 SHOW ENGINE 構文\nMySQL の外部キー追加時にエラー…ERROR 1215 (HY000): Cannot add foreign key constraint\nなぜあなたは SHOW ENGINE INNODB STATUS を読まないのか - そーだいなるらくがき帳\n","permalink":"https://SawaTszm.github.io/post/mysql-%E5%A4%96%E9%83%A8%E3%82%AD%E3%83%BC%E8%BF%BD%E5%8A%A0%E6%99%82%E3%81%AB%E3%82%A8%E3%83%A9%E3%83%BC/","summary":"","title":"【MySQL】外部キー追加時にエラー"},{"content":"cerberusとは CERBERUS, n. The watch-dog of Hades, whose duty it was to guard the entrance; everybody, sooner or later, had to go there, and nobody wanted to carry off the entrance. - Ambrose Bierce, The Devil’s Dictionary\nケルベロスはシンプルで軽量なデータ検証機能を提供するパッケージです。\n公式曰く、拡張も容易なため、カスタム検証も可能です。\n(以下、9割公式のドキュメントの翻訳です)\n概要 検証用のスキーマを定義し、それを Validator クラスのインスタンスに渡します。\nschma = {\u0026#39;name\u0026#39;: {\u0026#39;type\u0026#39;: \u0026#39;string\u0026#39;}} v = Validator(schema) 次に、validate()を呼び出すことで、簡単にスキーマと辞書を検証できます。\n検証が成功すると True が返されます。\ndocument = {\u0026#39;name\u0026#39;: \u0026#39;john doe\u0026#39;} v.validate(document) # True インストール 安定バージョンはpipから取得できます。\npip install cerberus\n使い方 基本的な使い方 # 概要の通り。スキーマを定義し、Validatorクラスに渡して検証する。 \u0026gt;\u0026gt;\u0026gt; from cerberus import Validator \u0026gt;\u0026gt;\u0026gt; schema = {\u0026#39;name\u0026#39;: {\u0026#39;type\u0026#39;: \u0026#39;string\u0026#39;}} \u0026gt;\u0026gt;\u0026gt; v = Validator(schema) \u0026gt;\u0026gt;\u0026gt; document = {\u0026#39;name\u0026#39;: \u0026#39;john doe\u0026#39;} \u0026gt;\u0026gt;\u0026gt; v.validate(document) True # スキーマと辞書を同時に渡すこともできる。 \u0026gt;\u0026gt;\u0026gt; v = Validator() \u0026gt;\u0026gt;\u0026gt; v.validate(document, schema) True # Validatorクラスとそのインスタンスは呼び出し可能なので、以下の簡略構文が使える。 \u0026gt;\u0026gt;\u0026gt; v(document) True ケルベロスは、検証に問題があった時点(最初のバリデーションエラーが起きた時点)では停止しません(!)。\n文書全体が常に処理されてからFalseを返します。その後、エラープロパティにアクセスすることで、起きた問題のリストを取得できます。\nつまり検証したデータ内で起きたバリデーションエラーは全て取得できます。\nバリデーションエラーはValidator.errorsに格納されます。\n\u0026gt;\u0026gt;\u0026gt; schema = {\u0026#39;name\u0026#39;: {\u0026#39;type\u0026#39;: \u0026#39;string\u0026#39;}, \u0026#39;age\u0026#39;: {\u0026#39;type\u0026#39;: \u0026#39;integer\u0026#39;, \u0026#39;min\u0026#39;: 10}} \u0026gt;\u0026gt;\u0026gt; document = {\u0026#39;name\u0026#39;: 400, \u0026#39;age\u0026#39;: 5} \u0026gt;\u0026gt;\u0026gt; v.validate(document, schema) False \u0026gt;\u0026gt;\u0026gt; v.errors {\u0026#39;age\u0026#39;: [\u0026#39;min value is 10\u0026#39;], \u0026#39;name\u0026#39;: [\u0026#39;must be of string type\u0026#39;]} 未知のものを許可 デフォルトでは、スキーマで定義された以外のキーは許可されません。\nただし、Validator でallow_unknown = Trueを設定することにより、スキーマに記述されていないキーを許可したり、検証をかけたりすることができます。\n# デフォルトでは、スキーマで定義されたキーのみが許可される。 \u0026gt;\u0026gt;\u0026gt; schema = {\u0026#39;name\u0026#39;: {\u0026#39;type\u0026#39;: \u0026#39;string\u0026#39;, \u0026#39;maxlength\u0026#39;: 10}} \u0026gt;\u0026gt;\u0026gt; v.validate({\u0026#39;name\u0026#39;: \u0026#39;john\u0026#39;, \u0026#39;sex\u0026#39;: \u0026#39;M\u0026#39;}, schema) False \u0026gt;\u0026gt;\u0026gt; v.errors {\u0026#39;sex\u0026#39;: [\u0026#39;unknown field\u0026#39;]} # allow_unknownをTrueに設定することで、不明なキーを許可できる。(検証はしない) \u0026gt;\u0026gt;\u0026gt; v.schema = {} \u0026gt;\u0026gt;\u0026gt; v.allow_unknown = True \u0026gt;\u0026gt;\u0026gt; v.validate({\u0026#39;name\u0026#39;: \u0026#39;john\u0026#39;, \u0026#39;sex\u0026#39;: \u0026#39;M\u0026#39;}) True # もしくは、検証スキーマに設定できる。この場合は未知のキーが検証される。 \u0026gt;\u0026gt;\u0026gt; v.schema = {} \u0026gt;\u0026gt;\u0026gt; v.allow_unknown = {\u0026#39;type\u0026#39;: \u0026#39;string\u0026#39;} \u0026gt;\u0026gt;\u0026gt; v.validate({\u0026#39;an_unknown_field\u0026#39;: 1}) False \u0026gt;\u0026gt;\u0026gt; v.errors {\u0026#39;an_unknown_field\u0026#39;: [\u0026#39;must be of string type\u0026#39;]} # 初期化時に設定することも可能。 \u0026gt;\u0026gt;\u0026gt; v = Validator({}, allow_unknown=True) \u0026gt;\u0026gt;\u0026gt; v.validate({\u0026#39;name\u0026#39;: \u0026#39;john\u0026#39;, \u0026#39;sex\u0026#39;: \u0026#39;M\u0026#39;}) True # スキーマのルールとして設定することもできる。ネストした先の辞書等にも使用可能。 \u0026gt;\u0026gt;\u0026gt; v = Validator() \u0026gt;\u0026gt;\u0026gt; v.allow_unknown False \u0026gt;\u0026gt;\u0026gt; schema = { ... \u0026#39;name\u0026#39;: {\u0026#39;type\u0026#39;: \u0026#39;string\u0026#39;}, ... \u0026#39;a_dict\u0026#39;: { ... \u0026#39;type\u0026#39;: \u0026#39;dict\u0026#39;, ... \u0026#39;allow_unknown\u0026#39;: True, #a_dict辞書の未知のキーを許可 ... \u0026#39;schema\u0026#39;: { ... \u0026#39;address\u0026#39;: {\u0026#39;type\u0026#39;: \u0026#39;string\u0026#39;} ... } ... } ... } \u0026gt;\u0026gt;\u0026gt; v.validate({\u0026#39;name\u0026#39;: \u0026#39;john\u0026#39;, ... \u0026#39;a_dict\u0026#39;: {\u0026#39;an_unknown_field\u0026#39;: \u0026#39;is allowed\u0026#39;}}, ... schema) True \u0026gt;\u0026gt;\u0026gt; v.validate({\u0026#39;name\u0026#39;: \u0026#39;john\u0026#39;, ... \u0026#39;an_unknown_field\u0026#39;: \u0026#39;is not allowed\u0026#39;, # 親の辞書はv.allow_unknown == False ... \u0026#39;a_dict\u0026#39;:{\u0026#39;an_unknown_field\u0026#39;: \u0026#39;is allowed\u0026#39;}}, ... schema) False \u0026gt;\u0026gt;\u0026gt; v.errors {\u0026#39;an_unknown_field\u0026#39;: [\u0026#39;unknown field\u0026#39;]} 全てを要求する デフォルトでは、スキーマで定義されたキーは不要です。\nただし、Validator でrequire_all = Trueを設定することにより、スキーマに記述した全てのキーを要求できます。\n\u0026gt;\u0026gt;\u0026gt; v = Validator() \u0026gt;\u0026gt;\u0026gt; v.require_all False \u0026gt;\u0026gt;\u0026gt; schema = { ... \u0026#39;name\u0026#39;: {\u0026#39;type\u0026#39;: \u0026#39;string\u0026#39;}, ... \u0026#39;a_dict\u0026#39;: { ... \u0026#39;type\u0026#39;: \u0026#39;dict\u0026#39;, ... \u0026#39;require_all\u0026#39;: True, ... \u0026#39;schema\u0026#39;: { ... \u0026#39;address\u0026#39;: {\u0026#39;type\u0026#39;: \u0026#39;string\u0026#39;} ... } ... } ... } \u0026gt;\u0026gt;\u0026gt; v.validate({\u0026#39;name\u0026#39;: \u0026#39;foo\u0026#39;, \u0026#39;a_dict\u0026#39;: {}}, schema) False \u0026gt;\u0026gt;\u0026gt; v.errors {\u0026#39;a_dict\u0026#39;: [{\u0026#39;address\u0026#39;: [\u0026#39;required field\u0026#39;]}]} \u0026gt;\u0026gt;\u0026gt; v.validate({\u0026#39;a_dict\u0026#39;: {\u0026#39;address\u0026#39;: \u0026#39;foobar\u0026#39;}}, schema) True 処理済みドキュメントの取得 # 検証されたドキュメントはドキュメントプロパティに格納される \u0026gt;\u0026gt;\u0026gt; v.schema = {\u0026#39;amount\u0026#39;: {\u0026#39;type\u0026#39;: \u0026#39;integer\u0026#39;, \u0026#39;coerce\u0026#39;: int}} \u0026gt;\u0026gt;\u0026gt; v.validate({\u0026#39;amount\u0026#39;: \u0026#39;1\u0026#39;}) True \u0026gt;\u0026gt;\u0026gt; v.document {\u0026#39;amount\u0026#39;: 1} # validated() # 検証済みの値のみを返す \u0026gt;\u0026gt;\u0026gt; schema = {\u0026#39;name\u0026#39;: {\u0026#39;type\u0026#39;: \u0026#39;string\u0026#39;, \u0026#39;maxlength\u0026#39;: 10}} \u0026gt;\u0026gt;\u0026gt; v = Validator(schema) \u0026gt;\u0026gt;\u0026gt; v.validated({\u0026#39;name\u0026#39;: \u0026#39;hoge\u0026#39;}) {\u0026#39;name\u0026#39;: \u0026#39;hoge\u0026#39;} \u0026gt;\u0026gt;\u0026gt; v.validated({\u0026#39;name\u0026#39;: 200}) # None # normalized() # 検証せずにDocumentの正規化されたコピーを返す \u0026gt;\u0026gt;\u0026gt; n = v.normalized({\u0026#39;name\u0026#39;: 200}) \u0026gt;\u0026gt;\u0026gt; type(n[\u0026#39;name\u0026#39;]) # \u0026lt;class \u0026#39;int\u0026#39;\u0026gt; \u0026gt;\u0026gt;\u0026gt; n = v.normalized({\u0026#39;name\u0026#39;: \u0026#39;hoge\u0026#39;}) \u0026gt;\u0026gt;\u0026gt; type(n[\u0026#39;name\u0026#39;]) # \u0026lt;class \u0026#39;str\u0026#39;\u0026gt; \u0026gt;\u0026gt;\u0026gt; n {\u0026#39;name\u0026#39;: \u0026#39;hoge\u0026#39;} 検証スキーマ 前述の通りですが、デフォルトの設定では、スキーマに書かれている全てのキーはオプションとして扱われます。\n極端な話、デフォルトではどんなスキーマ相手でもdocument = {}で検証が通ります。\n設定を変えるか、Validator.require_allを True にして全てのスキーマキーを要求することが望ましいです。\n2つのレジスタ # schema_registry \u0026gt;\u0026gt;\u0026gt; from cerberus import schema_registry \u0026gt;\u0026gt;\u0026gt; schema_registry.add(\u0026#39;non-system user\u0026#39;, ... {\u0026#39;uid\u0026#39;: {\u0026#39;min\u0026#39;: 1000, \u0026#39;max\u0026#39;: 0xffff}}) \u0026gt;\u0026gt;\u0026gt; schema = {\u0026#39;sender\u0026#39;: {\u0026#39;schema\u0026#39;: \u0026#39;non-system user\u0026#39;, ... \u0026#39;allow_unknown\u0026#39;: True}, ... \u0026#39;receiver\u0026#39;: {\u0026#39;schema\u0026#39;: \u0026#39;non-system user\u0026#39;, ... \u0026#39;allow_unknown\u0026#39;: True}} # rules_set_registry \u0026gt;\u0026gt;\u0026gt; from cerberus import rules_set_registry \u0026gt;\u0026gt;\u0026gt; rules_set_registry.extend(((\u0026#39;boolean\u0026#39;, {\u0026#39;type\u0026#39;: \u0026#39;boolean\u0026#39;}), ... (\u0026#39;booleans\u0026#39;, {\u0026#39;valuesrules\u0026#39;: \u0026#39;boolean\u0026#39;}))) \u0026gt;\u0026gt;\u0026gt; schema = {\u0026#39;foo\u0026#39;: \u0026#39;booleans\u0026#39;} レジストリを設定、及びダンプするには、extend()及びall()を使用します。\n検証 スキーマ自体の検証は、決まったタイミングのみ行われます。\n(when passed to the validator or a new set of rules is set for a document’s field)\n\u0026gt;\u0026gt;\u0026gt; v = Validator({\u0026#39;foo\u0026#39;: {\u0026#39;allowed\u0026#39;: []}}) \u0026gt;\u0026gt;\u0026gt; v.schema[\u0026#39;foo\u0026#39;] = {\u0026#39;allowed\u0026#39;: 1} Traceback (most recent call last): File \u0026#34;\u0026lt;input\u0026gt;\u0026#34;, line 1, in \u0026lt;module\u0026gt; File \u0026#34;cerberus/schema.py\u0026#34;, line 99, in __setitem__ self.validate({key: value}) File \u0026#34;cerberus/schema.py\u0026#34;, line 126, in validate self._validate(schema) File \u0026#34;cerberus/schema.py\u0026#34;, line 141, in _validate raise SchemaError(self.schema_validator.errors) SchemaError: {\u0026#39;foo\u0026#39;: {\u0026#39;allowed\u0026#39;: \u0026#39;must be of container type\u0026#39;}} \u0026gt;\u0026gt;\u0026gt; v.schema[\u0026#39;foo\u0026#39;][\u0026#39;allowed\u0026#39;] = \u0026#39;strings are no valid constraint for allowed\u0026#39; \u0026gt;\u0026gt;\u0026gt; v.schema.validate() Traceback (most recent call last): File \u0026#34;\u0026lt;input\u0026gt;\u0026#34;, line 1, in \u0026lt;module\u0026gt; File \u0026#34;cerberus/schema.py\u0026#34;, line 126, in validate self._validate(schema) File \u0026#34;cerberus/schema.py\u0026#34;, line 141, in _validate raise SchemaError(self.schema_validator.errors) SchemaError: {\u0026#39;foo\u0026#39;: {\u0026#39;allowed\u0026#39;: \u0026#39;must be of container type\u0026#39;}} Serialization Cerberus スキーマは、Python の型(dict, list, stringなど)で構成されています。\nユーザ定義の検証ルールも、スキーマ内ではstring型としてその名前が呼び出されます。\nこれによって、PyYAML など、様々な方法でスキーマを定義することができます。\n\u0026gt;\u0026gt;\u0026gt; import yaml \u0026gt;\u0026gt;\u0026gt; schema_text = \u0026#39;\u0026#39;\u0026#39; ... name: ... type: string ... age: ... type: integer ... min: 10 ... \u0026#39;\u0026#39;\u0026#39; \u0026gt;\u0026gt;\u0026gt; schema = yaml.load(schema_text) \u0026gt;\u0026gt;\u0026gt; document = {\u0026#39;name\u0026#39;: \u0026#39;Little Joe\u0026#39;, \u0026#39;age\u0026#39;: 5} \u0026gt;\u0026gt;\u0026gt; v.validate(document, schema) False \u0026gt;\u0026gt;\u0026gt; v.errors {\u0026#39;age\u0026#39;: [\u0026#39;min value is 10\u0026#39;]} YAML 以外にも、ネストされた辞書を生成できるデコーダーがあれば、どんなシリアライザーも利用できます。\nJSON とか。\n検証ルール 基本は 👇 にまとまってます\nValidation Rules — Cerberus is a lightweight and extensible data validation library for Python\nvaluesrules 検証される全てのデータに適応されるルールを定義します。\n\u0026gt;\u0026gt;\u0026gt; schema = {\u0026#39;numbers\u0026#39;: ... {\u0026#39;type\u0026#39;: \u0026#39;dict\u0026#39;, ... \u0026#39;valuesrules\u0026#39;: {\u0026#39;type\u0026#39;: \u0026#39;integer\u0026#39;, \u0026#39;min\u0026#39;: 10}} ... } \u0026gt;\u0026gt;\u0026gt; document = {\u0026#39;numbers\u0026#39;: {\u0026#39;an integer\u0026#39;: 10, \u0026#39;another integer\u0026#39;: 100}} \u0026gt;\u0026gt;\u0026gt; v.validate(document, schema) True \u0026gt;\u0026gt;\u0026gt; document = {\u0026#39;numbers\u0026#39;: {\u0026#39;an integer\u0026#39;: 9}} \u0026gt;\u0026gt;\u0026gt; v.validate(document, schema) False \u0026gt;\u0026gt;\u0026gt; v.errors {\u0026#39;numbers\u0026#39;: [{\u0026#39;an integer\u0026#39;: [\u0026#39;min value is 10\u0026#39;]}]} エラー ドキュメントが見つからない時、または無効な値の時 cerberus.validator.DocumentError\n\u0026gt;\u0026gt;\u0026gt; document = \u0026#34;\u0026#34; \u0026gt;\u0026gt;\u0026gt; v = Validator(schema) \u0026gt;\u0026gt;\u0026gt; v(document) cerberus.validator.DocumentError: \u0026#39;\u0026#39; is not a document, must be a dict 無効な検証スキーマを検出した場合 cerberus.schema.SchemaError\n\u0026gt;\u0026gt;\u0026gt; schema = {\u0026#34;name\u0026#34;: {\u0026#34;type\u0026#34;: \u0026#34;hoge\u0026#34;}} \u0026gt;\u0026gt;\u0026gt; v = Validator(schema) cerberus.schema.SchemaError: {\u0026#39;name\u0026#39;: [{\u0026#39;type\u0026#39;: [\u0026#39;Unsupported types: hoge\u0026#39;]}]} 参考 Python のバリデーションライブラリ「Cerberus」のよく使うバリデーションルールをまとめてみた | Developers.IO\nCerberus 入門!ばりばりバリデーションしよう! - hogehoge diary\n","permalink":"https://SawaTszm.github.io/post/python-summary-of-cerberus/","summary":"cerberusとは CERBERUS, n. The watch-dog of Hades, whose duty it was to guard the entrance; everybody, sooner or later, had to go there, and nobody wanted to carry off the entrance. - Ambrose Bierce, The Devil’s Dictionary\nケルベロスはシンプルで軽量なデータ検証機能を提供するパッケージです。\n公式曰く、拡張も容易なため、カスタム検証も可能です。\n(以下、9割公式のドキュメントの翻訳です)\n概要 検証用のスキーマを定義し、それを Validator クラスのインスタンスに渡します。\nschma = {\u0026#39;name\u0026#39;: {\u0026#39;type\u0026#39;: \u0026#39;string\u0026#39;}} v = Validator(schema) 次に、validate()を呼び出すことで、簡単にスキーマと辞書を検証できます。\n検証が成功すると True が返されます。\ndocument = {\u0026#39;name\u0026#39;: \u0026#39;john doe\u0026#39;} v.validate(document) # True インストール 安定バージョンはpipから取得できます。\npip install cerberus\n使い方 基本的な使い方 # 概要の通り。スキーマを定義し、Validatorクラスに渡して検証する。 \u0026gt;\u0026gt;\u0026gt; from cerberus import Validator \u0026gt;\u0026gt;\u0026gt; schema = {\u0026#39;name\u0026#39;: {\u0026#39;type\u0026#39;: \u0026#39;string\u0026#39;}} \u0026gt;\u0026gt;\u0026gt; v = Validator(schema) \u0026gt;\u0026gt;\u0026gt; document = {\u0026#39;name\u0026#39;: \u0026#39;john doe\u0026#39;} \u0026gt;\u0026gt;\u0026gt; v.","title":"【Python】cerberusまとめ"},{"content":"poetryとは pythonの環境管理ツールです。\n機能としてはpipenvに近い感じでした。\n本当に触りだけやってみたリポジトリはこちら。\nsample-poetry\nインストール $pip install poetry プロジェクトを作る $poetry new sample-project 実行すると下記のファイル・フォルダが作成されます。\nsample-project ├── README.rst ├── pyproject.toml ├── sample_project │ └── __init__.py └── tests ├── __init__.py └── test_sample_project.py モジュールの追加 $cd sample-project # pyproject.tomlがある階層で $poetry add [--dev] \u0026lt;package name\u0026gt; これでpoetryが管理している仮想環境内にモジュールが追加されます。\nそれに伴って、ファイルと依存関係を管理する pyproject.tomlとpoetry.lock が作成されます。\nRemove Deoendency $poetry remove \u0026lt;package name\u0026gt; This is very simple :)\nUse Virtual Environment # not active $poetry run python -m pytest # active $poetry shell Use Exsting Environment $poetry install [--no-dev] Reference Poetry - Python dependency management and packaging made easy.\nGitHub - python-poetry/poetry: Python dependency management and packaging made easy.\nModern Python Environments - dependency and workspace management | TestDriven.io\nめも Pipenvなんかにはないスマートな依存関係の解決ができるよって話らしいです。\n確かにpipenv uninstallは依存関係を見てないし、言われてみればinstallでコケることも割とあるので、\npoetry removeとそのスマートさがよしなにしてくれるなら嬉しいなーという感じでした。\n参考:Pipenv uninstallよりcleanの方が多分便利 - Qiita\n","permalink":"https://SawaTszm.github.io/post/python-try-poetry/","summary":"poetryとは pythonの環境管理ツールです。\n機能としてはpipenvに近い感じでした。\n本当に触りだけやってみたリポジトリはこちら。\nsample-poetry\nインストール $pip install poetry プロジェクトを作る $poetry new sample-project 実行すると下記のファイル・フォルダが作成されます。\nsample-project ├── README.rst ├── pyproject.toml ├── sample_project │ └── __init__.py └── tests ├── __init__.py └── test_sample_project.py モジュールの追加 $cd sample-project # pyproject.tomlがある階層で $poetry add [--dev] \u0026lt;package name\u0026gt; これでpoetryが管理している仮想環境内にモジュールが追加されます。\nそれに伴って、ファイルと依存関係を管理する pyproject.tomlとpoetry.lock が作成されます。\nRemove Deoendency $poetry remove \u0026lt;package name\u0026gt; This is very simple :)\nUse Virtual Environment # not active $poetry run python -m pytest # active $poetry shell Use Exsting Environment $poetry install [--no-dev] Reference Poetry - Python dependency management and packaging made easy.","title":"【Python】poetryを試してみる"},{"content":"知りたかったこと try-catch の有効範囲はどれくらいなのか(呼び出した関数で起きたエラーも拾えるのか) ネストしたエラーの扱いってどうするのが良いんだろう 結論 呼び出された先の例外もキャッチできますφ(・・\n調べて知ったこと エラーには構文エラーと例外がある 複数の例外を指定することができる except (RuntimeError, TypeError, NameError): pass exceptは上から順に見て、引っかかったタイミングでそのexcept節内部のみを実行する 最後の except 節では例外名を省いて、ワイルドカードにすることができる しかし、ワイルドカードの except 節は通常のプログラムエラーをたやすく隠してしまうため、注意は必要 Try…exceptの中にはelse節を設けることができる。else節は全てのexcept節よりも後ろに置く try 節で全く例外が創出されなかった時に実行されるコードを記述することができる for arg in sys.argv[1:]: try: f = open(arg, \u0026#39;r\u0026#39;) except OSError: print(\u0026#39;cannot open\u0026#39;, arg) else: print(arg, \u0026#39;has\u0026#39;, len(f.readlines()), \u0026#39;lines\u0026#39;) f.close() 参考:\nPython の例外処理(try, except, else, finally) | note.nkmk.me\n8. エラーと例外 — Python 3.8.1 ドキュメント\nExcept 節では例外名の後に変数を指定できる。この変数は例外インスタンスに結び付けられ、instance.argsに例外インスタンス生成時の引数が入る。\n例外インスタンスに実装されている__str__はinstance.argsをわざわざ出力しなくても見られるようになっているので、print(inst)で見られる。便利。 例外ハンドラは、try 節の直下で発生した例外を処理するだけではなく、その try 節から(たとえ間接的にでも)呼び出された関数の内部で発生した例外も処理する。(!)\ndef this_fails(): ... x = 1/0 ... \u0026gt;\u0026gt;\u0026gt; try: ... this_fails() ... except ZeroDivisionError as err: ... print(\u0026#39;Handling run-time error:\u0026#39;, err) ... Handling run-time error: division by zero ","permalink":"https://SawaTszm.github.io/post/python-about-error/","summary":"知りたかったこと try-catch の有効範囲はどれくらいなのか(呼び出した関数で起きたエラーも拾えるのか) ネストしたエラーの扱いってどうするのが良いんだろう 結論 呼び出された先の例外もキャッチできますφ(・・\n調べて知ったこと エラーには構文エラーと例外がある 複数の例外を指定することができる except (RuntimeError, TypeError, NameError): pass exceptは上から順に見て、引っかかったタイミングでそのexcept節内部のみを実行する 最後の except 節では例外名を省いて、ワイルドカードにすることができる しかし、ワイルドカードの except 節は通常のプログラムエラーをたやすく隠してしまうため、注意は必要 Try…exceptの中にはelse節を設けることができる。else節は全てのexcept節よりも後ろに置く try 節で全く例外が創出されなかった時に実行されるコードを記述することができる for arg in sys.argv[1:]: try: f = open(arg, \u0026#39;r\u0026#39;) except OSError: print(\u0026#39;cannot open\u0026#39;, arg) else: print(arg, \u0026#39;has\u0026#39;, len(f.readlines()), \u0026#39;lines\u0026#39;) f.close() 参考:\nPython の例外処理(try, except, else, finally) | note.nkmk.me\n8. エラーと例外 — Python 3.8.1 ドキュメント\nExcept 節では例外名の後に変数を指定できる。この変数は例外インスタンスに結び付けられ、instance.argsに例外インスタンス生成時の引数が入る。\n例外インスタンスに実装されている__str__はinstance.argsをわざわざ出力しなくても見られるようになっているので、print(inst)で見られる。便利。 例外ハンドラは、try 節の直下で発生した例外を処理するだけではなく、その try 節から(たとえ間接的にでも)呼び出された関数の内部で発生した例外も処理する。(!)\ndef this_fails(): ... x = 1/0 .","title":"【Python】エラーについて"},{"content":"目的 投票結果を DB に貯めて、その結果を一位から取得したい。\nDB 構成は、\nId Recipe int str というシンプルな感じです。\nここからレコードの recipe の値を、[a, b, c, b, ...]と言ったリストに直した際、\n「一番投票数の多かったもの」や「投票数が多かった順の要素のリスト」が欲しい。\nTL;DR collectionsを使えば比較的簡単にできます。\n要素のカウントは collections が便利 import collections votes_list = [a, b, c, b] c = collections.Counter(votes_list) # Counter({\u0026#39;b\u0026#39;: 2, \u0026#39;a\u0026#39;: 1, \u0026#39;c\u0026#39;: 1}) # `要素`: `出現回数` recipe = c.most_common() # [(\u0026#39;b\u0026#39;, 2), (\u0026#39;a\u0026#39;, 1), (\u0026#39;c\u0026#39;, 1)] # 出現回数が多い順に並べ替えてくれる recipe = c.most_common()[0][0] # b 参考にさせていただいたもの お世話になりました。\ncollections — コンテナデータ型 — Python 3.8.1 ドキュメント\nPython の Counter でリストの各要素の出現個数をカウント | note.nkmk.me\n","permalink":"https://SawaTszm.github.io/post/pytyon-%E3%83%AA%E3%82%B9%E3%83%88%E3%81%AE%E9%87%8D%E8%A4%87%E8%A6%81%E7%B4%A0%E3%82%92%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%81%99%E3%82%8B/","summary":"目的 投票結果を DB に貯めて、その結果を一位から取得したい。\nDB 構成は、\nId Recipe int str というシンプルな感じです。\nここからレコードの recipe の値を、[a, b, c, b, ...]と言ったリストに直した際、\n「一番投票数の多かったもの」や「投票数が多かった順の要素のリスト」が欲しい。\nTL;DR collectionsを使えば比較的簡単にできます。\n要素のカウントは collections が便利 import collections votes_list = [a, b, c, b] c = collections.Counter(votes_list) # Counter({\u0026#39;b\u0026#39;: 2, \u0026#39;a\u0026#39;: 1, \u0026#39;c\u0026#39;: 1}) # `要素`: `出現回数` recipe = c.most_common() # [(\u0026#39;b\u0026#39;, 2), (\u0026#39;a\u0026#39;, 1), (\u0026#39;c\u0026#39;, 1)] # 出現回数が多い順に並べ替えてくれる recipe = c.most_common()[0][0] # b 参考にさせていただいたもの お世話になりました。\ncollections — コンテナデータ型 — Python 3.8.1 ドキュメント","title":"【Pytyon】リストの重複要素をカウントする"},{"content":"目的 案件で触らせてもらうことになったぜ\n何もわからないぜ\nという状態なので、自分が調べたことについてまとめておきます。\nRadis とは REmote DIctionary Serverの略 読んで字の如く、ネットワーク接続されたKey-Value型のNoSQLデータベース 永続化可能なインメモリデータベース オープンソースのプロジェクトで、Redis Labsがスポンサー。中身はC言語 AWS上でもRedis-serverが提供されている 様々なデータ構造をサポートしている STRING LIST SET HASH ZSET (ソート済みのset) 補足:インメモリDB すべてのデータをコンピュータのメインメモリ上に展開しながら動作する仕組みのことです。\nコンピュータ(サーバ)の電源が落ちれば消えてしまうので、永続化の手段としてデータを別途どこかに保存することがあります。\nインメモリデータベースでサーバが落ちたらデータはどうなる? インメモリとカラム型データベースの可能性を調べる(その3) - Publickey\nインストールと動作確認 少し挙動を試してみたいだけなら、公式チュートリアルの画面でコマンドを叩くことができます。\nTry Redis\nMacであれば下記brewコマンドで一発。\n$brew install Redis インストールできたら、サーバを立ち上げてみます。\n$ redis-server # 立ち上がったら別のタブで動作確認 $ redis-cli 127.0.0.1:6379\u0026gt; set test \u0026#34;hoge\u0026#34; OK 127.0.0.1:6379\u0026gt; get test \u0026#34;hoge\u0026#34; 動作確認までできました。\nこのコマンドを叩く先のredis-serverがローカルにあるかAWS上のサービスとしてあるかが変わってくるだけで、cli側の設定や叩き方は基本的に変わりません。\n(PythonなんかでRedisクライアントを作成する時に指すHOSTが変わってくるくらい、の認識です)\nデータのタイプ Redisは前述の通り様々なデータタイプに対応しています。\nどのデータタイプを使用するかによって、コマンドやデータの指定方法が違ってきます。\nコマンドの詳細などは公式ドキュメントで。\nData types – Redis\nStrings 最も基本的な、KeyとValueが1:1な構造。\nKey = valueの形。\nバイナリセーフ(JPEG画像やシリアル化されたRubyオブジェクトなども格納可能) 最大512MBまで 127.0.0.1:6379\u0026gt; set string-key \u0026#34;value1\u0026#34; # OK 127.0.0.1:6379\u0026gt; get string-key # \u0026#34;value1\u0026#34; Lists 文字列のリスト構造。\nKey = [value1, value2, ...]の形。\n挿入順にソートされる 先頭/末尾に対して追加、削除を実行する リストの最大長は4294967295 リストの両端(先頭、末尾)へのアクセスは早いが、基本的にO(N)操作なので、膨大な量のリストの中間値へのアクセスは遅くなる 127.0.0.1:6379\u0026gt; LPUSH list-key a # (integer) 1 127.0.0.1:6379\u0026gt; LPUSH list-key b # (integer) 2 127.0.0.1:6379\u0026gt; RPUSH list-key c # (integer) 3 127.0.0.1:6379\u0026gt; LRANGE list-key 0 3 # 1) \u0026#34;b\u0026#34; # 2) \u0026#34;a\u0026#34; # 3) \u0026#34;c\u0026#34; Sets 順序、重複なしの文字型集合構造。\nKey = (value1, value2, ...)の形。\nValueの追加、削除、存在のテスト(要素の数に関係なく一定時間で動作)が可能 重複を許可せず、よしなにしてくれるので存在を確認してから追加する必要がない セット内の最大数は4294967295 127.0.0.1:6379\u0026gt; SADD set-key value1 value2 value3 # (integer) 3 127.0.0.1:6379\u0026gt; SMEMBERS set-key # 1) \u0026#34;value3\u0026#34; # 2) \u0026#34;value2\u0026#34; # 3) \u0026#34;value1\u0026#34; Hashes 重複なく、順序のないfield:valueのセットを持つ構造。\nKey = {field1: value1, field2: value2, ...}の形。\nfield:valueのセットの最大数は4294967295 オブジェクトを表すのにも使用される 少量(100くらい)のハッシュは、スペースをほぼ取らない方法で格納されるので、小さなRedisインスタンスに数百万のオブジェクトを格納できる 127.0.0.1:6379\u0026gt; HSET hash-key field1 value1 # (integer) 1 127.0.0.1:6379\u0026gt; HSET hash-key field2 value2 # (integer) 1 127.0.0.1:6379\u0026gt; HGETALL hash-key # 1) \u0026#34;field1\u0026#34; # 2) \u0026#34;value1\u0026#34; # 3) \u0026#34;field2\u0026#34; # 4) \u0026#34;value2\u0026#34; Sorted Sets 重複なし、Scoreによる順序があるvalue:scoreのセットを持つ構造。\nKey = {value1: score1, value2: score2, ...}の形。\nvalueは一意、scoreは重複する可能性がある 要素の追加、削除、更新がO(log(N))操作でできるため高速 要素はscore順で並べられ、後で並べ替えられるわけではない(ランク付けなどに便利) 127.0.0.1:6379\u0026gt; ZADD sort-key 10 user_1 # (integer) 1 127.0.0.1:6379\u0026gt; ZADD sort-key 20 user_2 # (integer) 1 127.0.0.1:6379\u0026gt; ZRANGE sort-key 0 5 WITHSCORES # 1) \u0026#34;user_1\u0026#34; # 2) \u0026#34;10\u0026#34; # 3) \u0026#34;user_2\u0026#34; # 4) \u0026#34;20\u0026#34; まとめ Redisは早くて便利。\n参考にさせていただいたもの Data types – Redis\n【初心者向け】Redisのデータ型とPythonでの使い方サンプル - Qiita\n【入門】Redis - Qiita\n","permalink":"https://SawaTszm.github.io/post/summary-of-redis/","summary":"目的 案件で触らせてもらうことになったぜ\n何もわからないぜ\nという状態なので、自分が調べたことについてまとめておきます。\nRadis とは REmote DIctionary Serverの略 読んで字の如く、ネットワーク接続されたKey-Value型のNoSQLデータベース 永続化可能なインメモリデータベース オープンソースのプロジェクトで、Redis Labsがスポンサー。中身はC言語 AWS上でもRedis-serverが提供されている 様々なデータ構造をサポートしている STRING LIST SET HASH ZSET (ソート済みのset) 補足:インメモリDB すべてのデータをコンピュータのメインメモリ上に展開しながら動作する仕組みのことです。\nコンピュータ(サーバ)の電源が落ちれば消えてしまうので、永続化の手段としてデータを別途どこかに保存することがあります。\nインメモリデータベースでサーバが落ちたらデータはどうなる? インメモリとカラム型データベースの可能性を調べる(その3) - Publickey\nインストールと動作確認 少し挙動を試してみたいだけなら、公式チュートリアルの画面でコマンドを叩くことができます。\nTry Redis\nMacであれば下記brewコマンドで一発。\n$brew install Redis インストールできたら、サーバを立ち上げてみます。\n$ redis-server # 立ち上がったら別のタブで動作確認 $ redis-cli 127.0.0.1:6379\u0026gt; set test \u0026#34;hoge\u0026#34; OK 127.0.0.1:6379\u0026gt; get test \u0026#34;hoge\u0026#34; 動作確認までできました。\nこのコマンドを叩く先のredis-serverがローカルにあるかAWS上のサービスとしてあるかが変わってくるだけで、cli側の設定や叩き方は基本的に変わりません。\n(PythonなんかでRedisクライアントを作成する時に指すHOSTが変わってくるくらい、の認識です)\nデータのタイプ Redisは前述の通り様々なデータタイプに対応しています。\nどのデータタイプを使用するかによって、コマンドやデータの指定方法が違ってきます。\nコマンドの詳細などは公式ドキュメントで。\nData types – Redis\nStrings 最も基本的な、KeyとValueが1:1な構造。\nKey = valueの形。\nバイナリセーフ(JPEG画像やシリアル化されたRubyオブジェクトなども格納可能) 最大512MBまで 127.","title":"【Redis】ってなんぞや"},{"content":"目的 laravelプロジェクトにawsのs3アダプタをインストールしようとして、dockerコンテナ内に入ってcomposer require league/flysystem-aws-s3-v3 ~1.0を実行したら下記の通りKillされました。\nroot@9f833b0a116f:/var/www/html/laravel# composer require league/flysystem-aws-s3-v3 ~1.0 ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) Killed コロサナイデ……\nこれを、ちゃんと殺されずにインストール完了させたいので色々調べました。\nTL;DR Docker for Macのメモリ割り当てをできる範囲で増やす。\n解決法 調べたこと まず、Killedがどういう時に発動するのかを調べました。\nら、OOM Killerと呼ばれる動作らしいです。\nOOM Killer(Out of Memory Killer)は,システムが実メモリーと仮想メモリー空間(スワップ領域)を使い切り,必要なメモリー領域を新たに確保できない場合に,プロセスを強制終了させて空きメモリーを確保する,Linuxカーネルの仕組みです。OOM Killerは,空きメモリーが確保できないことによりシステム自体が停止するという最悪の事態を避けるために用意されています。\n日経XTECHさんより引用\n強制的にプロセスがKillされてしまうのは、システム自体が止まってしまわないようにOOM Killerさんが働いた結果らしいです。\nつまり、今回の原因はメモリ不足。\nDocker for macで、Preferences \u0026gt; Resources \u0026gt; Memoryを見てみると、現在は3.75GB割り当てしていることがわかりました。Swapは1GB。\n合わせてMacのアクティビティモニタでdockerが使っているメモリを調べて見ると、割り当て分ほとんど使い切っていました。\n実行したこと Docker for macのPreferences \u0026gt; Resources \u0026gt; Memoryから、割り当てのメモリをできる範囲で増やしました。\nmac自体は16GBなので、まぁ一回様子見て5GBまであげてみることに。\n改めてcomposer require league/flysystem-aws-s3-v3 ~1.0を実行。\nroot@9f833b0a116f:/var/www/html/laravel# composer require league/flysystem-aws-s3-v3 Using version ^1.0 for league/flysystem-aws-s3-v3 ~略~ Package manifest generated successfully. 38 packages you are using are looking for funding. Use the `composer fund` command to find out more! 無事入りました。\n思ったこと 今回は5GBで足りたけど、例えばいくつかの案件を掛け持ちしていて、常にいくつもDockerコンテナを立ち上げる……という状態だとメモリ割り当て→食いきるのいたちごっこになるのでは?と思いました。\n開発時からコンテナはrestart: alwaysで設定しがちだけど、長く使わないものはちゃんと落としておく、などの対策もした合わせてした方が良いのかもしれないですね。\n","permalink":"https://SawaTszm.github.io/post/increase-memory-allocation-of-docker-to-avoid-killed/","summary":"","title":"Killedと言われないためにDockerのメモリ割り当てを増やす"},{"content":"気になったニュース PythonのデフォルトエンコーディングをUTF-8にするために - methaneのブログ\nPyCon JP Blog: PyCon JP 2021 カンファレンス開催日程仮決定のお知らせ\n楽しみ\nFacebookが大規模スケーラビリティへの挑戦で学んだこと(前編)~800億枚の写真データとPHPのスケーラビリティ問題 - Publickey\n社内勉強会で AWS Organizations 基礎の話をしました | DevelopersIO\n他 書くだけ書いてPushするのを忘れがち。\n","permalink":"https://SawaTszm.github.io/post/diary-2021-02-09/","summary":"","title":"2021 02 09-19 Diary"},{"content":"気になったニュース 【?】「github」の読み方は「ギットハブ」でも「ジットハブ」でもありません。「イ」です。 - Togetter\nGhoti理論って言うものがあって、これはfishと同じ読み方らしい。これに則って読むとgithubが「イ」になる。そうなんだ……\nASCII.jp:Apple Watchがあるとマスクを着けたままiPhoneのロック解除が可能に\nありがとうApple ありがとう世界\nPython向け科学計算パッケージの最新版「NumPy 1.20.0」がリリース:CodeZine(コードジン)\n「NumPy 1.20.0」はこれまでで最大となるアップデートで、Python 3.7~3.9をサポートし、Python 3.6のサポートは終了している。\n新しく使うときに3.6以下使うことはないと思うけど、一応頭の片隅で覚えておこう。\n他 原神くんの事前ダウンロードも終えて準備万端なので明日が楽しみです。\n","permalink":"https://SawaTszm.github.io/post/diary-2021-02-02/","summary":"","title":"2021 02 02 Diary"},{"content":"気になったニュース gitにおけるコミットログ/メッセージ例文集100\nAccess control for GitHub Pages - GitHub Changelog\n社内ドキュメントとしての運用とかにも良さそう。\nエディタ+ mdファイル編集 + GithubにPushで完結するのはとても健康にいい。\n調べたこと BigQueryへの差分アップロード Insert/Upsertを意識するんじゃなくて、updated_dateを持った状態で複数データ入れてしまう方がいいかなと思った。\nInsert/Upsertを実現できるmergeはテーブルサイズ分課金されるので(SELECTと同じ)、日次で取り込むデータサイクルに入れるのは避けたい。\n対して上書きでなくて重複データをInsertする方法では、\n集計するときはCOUNT(DISTINCT x)で重複削除すればいい 重複データが積もってきたらSQLで整理ができる ので、こっちの方が良さげ。\nそうすればBQに移行する日次データは「その日に新規作成されたもの」と「その日に上書きされたもの」だけでよくなる。\n参考:\nBigQuery にデータを差分ロード(UPSERT)する方法まとめ | Developers.IO\nBigQueryでUPDATE?? - Qiita\n標準 SQL の集計関数 | BigQuery | Google Cloud\nSQLのORについて OR使わないといけないかなと思って調べてたら下記記事を見つけた。\nPostgreSQL: 「OR」を避けてパフォーマンスを向上させよう(翻訳)\n「まだマシ」なダメな例をやろうとしていたのと、後半の話は知らなかったのでチョット勉強になった。\nSQL、苦手意識があって若干避けてきたけどそろそろ向き合うべき時が来た気がする。\n他 原神くんの1.3アプデ、鍾離先生の上方修正が確定したので楽しみです。\nコントローラーで操作できるようになるのも楽しみ。\nこれでもうボタンスカって敵の攻撃が直撃するミスがなくなるんだ……。\n","permalink":"https://SawaTszm.github.io/post/diary-2021-02-01/","summary":"","title":"2021 02 01 Diary"},{"content":"目的 「LINEBOT くんのメッセージをタップしたらアプリに飛ぶようにしてほしい!」\nという要件を貰ったけど、\nそのあたり全く初見だったので調べてまとめてみました。\nディープリンクとは 任意のアプリに遷移できるリンク(URL)のことです。\nアプリに遷移できるだけでなく、更にその中の特定の画面を指定して遷移することができます。\nスマホでTwitterやYoutubeのリンクをタップした時に、アプリが立ち上がって見たかった投稿や動画を開いてくれることってありますよね? あの仕組みのことです。\nプラットフォームごとのディープリンク対応 プラットフォーム 種類 対応 URL Android App links Android6.0 以降 WebURL Android App Indexing Android WebURL Apple universal links iOS9 以降 WebURL どちらも Custom URL Scheme iOS,Android カスタム URL Android(Google) App Links App Linksはオープンソースのアプリ連携サービスです。Facebookが提供しています。\nhttps:// から始まる URL を利用できます。\nメリット WebURL から直接アプリを起動できる Android 特有のアプリ選択画面を飛ばせる デメリット 認証情報ファイルを https 通信可能なサーバに上げておく必要がある android 6.0(2015 年 10 月リリース)以降しか対応していない 設定方法 下記が参考になりました。\nApp Linksに対応してみた - Qiita\nApp Indexing App Indexingは、その名の通りアプリのコンテンツをインデックスして、Google検索の結果からアプリに直接遷移することができるサービスです。Googleが提供しています。\n参考になった記事: AppIndexing について - Qiita\niOS(Apple) universal links universal linksは、iOS9から使用できるサービスです。\nhttps:// から始まる URL を利用できます。\n例:LINE(https://line.me/R/)\nメリット(universal links) アプリが端末に入っていない場合の挙動を設定できる(Store に飛ばす等) WebURL から直接アプリを起動できる デメリット(universal links) 認証情報ファイルを https 通信可能なサーバに上げておく必要がある iOS9(2015 年 9 月リリース)以降でしか使えない 設定方法(universal links) こちらが参考になりました。\nUniversal Links を試してみました。関連づけファイル(apple-app-site-association)は S3 に置きました。 | Developers.IO\n共通 Custom URL Scheme amzn://apps/android?asin=B004FRX0MY や comgooglemaps:// など、アプリ独自に決めた scheme を利用する方法です。\nメリット(Custom URL Scheme) iOS8 以前,android 6.0 以前でも動く デメリット(Custom URL Scheme) アプリがインストールされていない場合に動作しない 他のアプリと競合する可能性がある 設定方法(iOS) 2種類の実装方法があるけど内容は同じです。\ninfo.plistから設定する TARGET \u0026gt; infoから設定する Safariから固定 URL(my-app://など)を叩けばアプリを起動できます。\nまとめ 今から実装するとなったらApp Links ≒ universal linksが良さげだなと思いました。\nどちらもWebURLから直接アプリを起動できるので、LINEのメッセージ上から遷移が可能です。\n参考 途中に載せさせて頂いてるサイトも大変参考になりました……ありがとうございます……\n真面目に Deep Link 対応したい話 - Qiita\niOS/Android のディープリンクについての雑な説明 - Qiita\n","permalink":"https://SawaTszm.github.io/post/summary-of-deep-link/","summary":"目的 「LINEBOT くんのメッセージをタップしたらアプリに飛ぶようにしてほしい!」\nという要件を貰ったけど、\nそのあたり全く初見だったので調べてまとめてみました。\nディープリンクとは 任意のアプリに遷移できるリンク(URL)のことです。\nアプリに遷移できるだけでなく、更にその中の特定の画面を指定して遷移することができます。\nスマホでTwitterやYoutubeのリンクをタップした時に、アプリが立ち上がって見たかった投稿や動画を開いてくれることってありますよね? あの仕組みのことです。\nプラットフォームごとのディープリンク対応 プラットフォーム 種類 対応 URL Android App links Android6.0 以降 WebURL Android App Indexing Android WebURL Apple universal links iOS9 以降 WebURL どちらも Custom URL Scheme iOS,Android カスタム URL Android(Google) App Links App Linksはオープンソースのアプリ連携サービスです。Facebookが提供しています。\nhttps:// から始まる URL を利用できます。\nメリット WebURL から直接アプリを起動できる Android 特有のアプリ選択画面を飛ばせる デメリット 認証情報ファイルを https 通信可能なサーバに上げておく必要がある android 6.0(2015 年 10 月リリース)以降しか対応していない 設定方法 下記が参考になりました。\nApp Linksに対応してみた - Qiita\nApp Indexing App Indexingは、その名の通りアプリのコンテンツをインデックスして、Google検索の結果からアプリに直接遷移することができるサービスです。Googleが提供しています。","title":"【ディープリンク】ってなんぞや"},{"content":"気になったニュース Pyston 2.1、本家Python 3.8/3.9よりも十分に高いパフォーマンスを実現 | マイナビニュース\nDropboxが開発元(?)って言うのは知らなかった……\nやってみたこと サイト構築 Github Pages と Hugoでサイト作ってみました。(これ)\n参考にさせてもらったサイト:\nGitHub PagesとHugoでブログをつくった\nHugo+Github Pagesで新しい個人ウェブサイトを作った - DEV Community\n使用テーマはこれ:\nBeautifulhugo | Hugo Themes\n拡張機能系もありそうなのでゆっくり見ていきたいです。\nあと、Hugoの中身はGo言語らしいので、Go勉強し始めることがあったらソース読みたいなと思いました。\n","permalink":"https://SawaTszm.github.io/post/diary-2021-01-28/","summary":"","title":"2021-01-28 Diary"},{"content":"このブログは? 社会人6年目のWebエンジニアが学んだことを書いているブログです。\n誰? 佐和(Sawa)です。\nWebエンジニア4年生(バックエンドメイン/最近フロントエンド勉強中) ネットワーク系SIer2年→転職してWebエンジニアへ 猫と爬虫類とゲームとPythonが好き たまに山に登ったりサイクリングしたりする 何使ってる? 言語 現在はPython(Django)/TypeScript(Vue.js)がメイン。\n今まで触ってきたのはPHP(Laravel)など。\n学生時代はC/Javaを勉強してましたがかなり忘却の彼方です。\n環境 AWS/GCP(チョット)/Docker/\u0026hellip;\n普段はAWSメインで、GCPはBigQuery周りをちょっと触りました。\nどこに生息してる? 愛知近郊に住んでます。\n","permalink":"https://SawaTszm.github.io/page/about/","summary":"このブログは? 社会人6年目のWebエンジニアが学んだことを書いているブログです。\n誰? 佐和(Sawa)です。\nWebエンジニア4年生(バックエンドメイン/最近フロントエンド勉強中) ネットワーク系SIer2年→転職してWebエンジニアへ 猫と爬虫類とゲームとPythonが好き たまに山に登ったりサイクリングしたりする 何使ってる? 言語 現在はPython(Django)/TypeScript(Vue.js)がメイン。\n今まで触ってきたのはPHP(Laravel)など。\n学生時代はC/Javaを勉強してましたがかなり忘却の彼方です。\n環境 AWS/GCP(チョット)/Docker/\u0026hellip;\n普段はAWSメインで、GCPはBigQuery周りをちょっと触りました。\nどこに生息してる? 愛知近郊に住んでます。","title":"About"},{"content":"問い合わせ先 TwitterのDM、もしくはこちらのGoogleフォームよりお問い合わせください。\n","permalink":"https://SawaTszm.github.io/page/form/","summary":"問い合わせ先 TwitterのDM、もしくはこちらのGoogleフォームよりお問い合わせください。","title":"Contact form"},{"content":"当サイトに掲載されている広告について 当サイトでは、第三者配信の広告サービス(Googleアドセンス)を利用しています。\nこのような広告配信事業者は、ユーザーの興味に応じた商品やサービスの広告を表示するため、当サイトや他サイトへのアクセスに関する情報 『Cookie』(氏名、住所、メール アドレス、電話番号は含まれません) を使用することがあります。\n当サイトが使用しているアクセス解析ツールについて 当サイトでは、Googleによるアクセス解析ツール「Google Analytics」を利用しています。\nこのGoogle Analyticsはトラフィックデータの収集のためにCookieを使用しています。\nこのトラフィックデータは匿名で収集されており、個人を特定するものではありません。\nこの機能はCookieを無効にすることで収集を拒否することが出来ますので、お使いのブラウザの設定をご確認ください。\nこの規約に関して、詳しくは下記をクリックしてご確認ください。\nTerms of Service | Google Analytics - Google(Google アナリティクス利用規約) Google のサービスを使用するサイトやアプリから収集した情報の Google による使用 - ポリシーと規約 - Google 当サイトの免責事項について 当サイトで掲載している画像の著作権・肖像権等は各権利所有者に帰属致します。権利を侵害する目的ではございません。記事の内容や掲載画像等に問題がございましたら、各権利所有者様本人が、お問い合わせフォームよりご連絡下さい。確認後、対応させて頂きます。\n当サイトからリンクやバナーなどによって他のサイトに移動された場合、移動先サイトで提供される情報、サービス等について一切の責任を負いません。\n当サイトのコンテンツ・情報につきまして、可能な限り正確な情報を掲載するよう努めておりますが、誤情報が入り込んだり、情報が古くなっていることもございます。\n当サイトに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。\nプライバシーポリシーの変更について 当サイトは、個人情報に関して適用される日本の法令を遵守するとともに、本ポリシーの内容を適宜見直しその改善に努めます。\n修正された最新のプライバシーポリシーは常に本ページにて開示されます。\n","permalink":"https://SawaTszm.github.io/page/privacy_policy/","summary":"当サイトに掲載されている広告について 当サイトでは、第三者配信の広告サービス(Googleアドセンス)を利用しています。\nこのような広告配信事業者は、ユーザーの興味に応じた商品やサービスの広告を表示するため、当サイトや他サイトへのアクセスに関する情報 『Cookie』(氏名、住所、メール アドレス、電話番号は含まれません) を使用することがあります。\n当サイトが使用しているアクセス解析ツールについて 当サイトでは、Googleによるアクセス解析ツール「Google Analytics」を利用しています。\nこのGoogle Analyticsはトラフィックデータの収集のためにCookieを使用しています。\nこのトラフィックデータは匿名で収集されており、個人を特定するものではありません。\nこの機能はCookieを無効にすることで収集を拒否することが出来ますので、お使いのブラウザの設定をご確認ください。\nこの規約に関して、詳しくは下記をクリックしてご確認ください。\nTerms of Service | Google Analytics - Google(Google アナリティクス利用規約) Google のサービスを使用するサイトやアプリから収集した情報の Google による使用 - ポリシーと規約 - Google 当サイトの免責事項について 当サイトで掲載している画像の著作権・肖像権等は各権利所有者に帰属致します。権利を侵害する目的ではございません。記事の内容や掲載画像等に問題がございましたら、各権利所有者様本人が、お問い合わせフォームよりご連絡下さい。確認後、対応させて頂きます。\n当サイトからリンクやバナーなどによって他のサイトに移動された場合、移動先サイトで提供される情報、サービス等について一切の責任を負いません。\n当サイトのコンテンツ・情報につきまして、可能な限り正確な情報を掲載するよう努めておりますが、誤情報が入り込んだり、情報が古くなっていることもございます。\n当サイトに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。\nプライバシーポリシーの変更について 当サイトは、個人情報に関して適用される日本の法令を遵守するとともに、本ポリシーの内容を適宜見直しその改善に努めます。\n修正された最新のプライバシーポリシーは常に本ページにて開示されます。","title":"Privacy Policy"}]