AdonisJSの世界を探求する

MMaximilian Schwarzmüller
Computing/SoftwareSmall Business/StartupsInternet Technology

Transcript

00:00:00ありがとうございます。
00:00:30はい、皆さんこんにちは。今日の配信はAdonis.jsについてです。面白いフレームワークでありライブラリだと思います。これまで使ったことがなかったので、今日の配信で試してみようと思いました。
00:01:00ちょっと準備をさせてください。
00:01:07皆さんお元気でしょうか。参加してくれてありがとうございます。
00:01:16それでは始めましょう。皆さん、こんにちは。今日はAdonisを深掘りして探求してみたいと思います。楽しみのためでもありますが、Adonis.jsは他のフレームワークとはかなり異なるJavaScriptフレームワークだからです。
00:01:38もちろん、今はもう2019年ではありません。ですから、最近のJavaScriptフレームワークの重要性について議論する余地があるかもしれません。フレームワーク戦争の時代は終わりました。毎日新しいフレームワークが登場していたような時代は。
00:01:54そして今日はAIの話題ばかりです。しかし、今はAI全盛の時代だからこそ、あえてAIとは全く関係のないものを扱うライブ配信をしようと考えました。
00:02:08Adonisはかなり興味深いフレームワークでありライブラリです。先ほど言ったように、私は仕事で使ったことはありませんが、存在は知っています。何年も前からなんとなく追いかけてはいました。
00:02:20結局のところ、これはJavaScriptのためのLaravelです。それが私のAdonisに対する理解です。フルスタックフレームワークであり、Reactのフレームワークがフルスタックになる前から存在していました。
00:02:40ですから、Next.jsがリリースされる前…正確な時期は分かりませんが、Next.jsが超人気になるずっと前からあったと思います。
00:02:51はい、興味深い機能が盛りだくさんです。今日の私のアイデアは、公式の入門ガイドを一通り読んで、何が入っているのかを確認し、実際に触ってみて、それが何であり、どう動くのかを見つけることです。
00:03:10おっと、Google AIプランの新しいコンピュータベースのクォータについてのコメントが来ていますね。何か読んだ気がしますが、詳しく見ていないので、それについては何とも言えません。
00:03:24お、これは結構大きいですね。見てみましょう。Adonisとは何でしょうか?バックエンドファーストの型安全なフレームワークです。バックエンドファーストですが、フルスタック機能も備えているのは知っています。
00:03:37Laravelを知っていれば分かるように、これを使ってビューをレンダリングできます。
00:03:42Node.jsとTypeScriptでWebアプリケーションを構築するためのもので、完全なバックエンドを作成・保守するための核となる構成要素を提供し、サードパーティサービスを不要にします。
00:03:52そうなんです。先ほど触れたように、Next.jsのような単なるフルスタックフレームワークとは異なり、サーバー上でReactコンポーネントをレンダリングする機能を提供します。
00:04:06大まかな要約ですが、まあ、それがNext.jsの主なアイデアだと言えるでしょう。
00:04:12ルーティングなどもありますが、AdonisはLaravelのように、それ以上のものを提供します。
00:04:16認証が組み込まれているので、そのために別のライブラリを用意する必要はありません。
00:04:21ファイルアップロード、キャッシング、レート制限などのサポートが組み込まれています。
00:04:26独自のORM、つまりオブジェクト関係マッピング機能も付いています。
00:04:33SQLデータベースを扱うための独自のラッパーなどですね。
00:04:35非常に強力で多機能です。
00:04:38そして、フルスタックアプリケーションを作りたい時に、他の依存関係をあまり必要とせずにAdonis.jsさえあればいい、というのがコンセプトです。
00:04:47もちろん、特に今日の供給連鎖攻撃が多い状況では、依存関係の数を制限できるというのはかなり興味深い点です。
00:04:55当然、Adonis自体が攻撃されたら問題ですが、必要な依存関係が少ない分リスクを抑えられます。
00:05:03おっと、Daki、君の有名なReactコースを終えようとしているところだよ。
00:05:07プレーンなTypeScriptやReact + TypeScriptの次に何を学ぶのがおすすめかな?
00:05:11そうですね、ReactとTypeScriptは良い学びですね。
00:05:12Next.jsも良い選択肢です。
00:05:14あるいはReactを学んだ後にReact Nativeに進んで、モバイルアプリを構築できるようにするのもいいでしょう。
00:05:20それらすべてが合理的な次のステップだと思います。
00:05:24というわけで、長々としたテキストを飛ばして、中身に入っていきましょう。
00:05:28パスを選択しましょう。
00:05:31ここで学ぶことですね。
00:05:33実際、開始してみましょう。
00:05:36一つ注意点として、3つのアプローチがあります。
00:05:40Adonis.jsはフロントエンドを構築するための3つの主要なアプローチをサポートしています。
00:05:44なるほど、それは重要そうですね。
00:05:47それぞれのアプローチは、ビューレイヤーに対する異なる考え方を表しています。
00:05:52ハイパーメディア。
00:05:52ハイパーメディアアプリケーションはサーバー上で完全なHTMLページを生成し、ブラウザに送信します。
00:05:57インターフェースはテンプレートエンジンを使って構築します。
00:06:00そしてAdonis.jsには独自のテンプレートエンジンであるEdgeが付属しています。
00:06:05そしてAlpine.jsのような軽量なJavaScriptライブラリを使ってインタラクティブ性を追加します。
00:06:10必要に応じてHTMXやPolyなども使えますね。
00:06:12このアプローチを使ってみようかと思います。
00:06:16あるいは、AdonisとReactを組み合わせてInertia.jsを使うこともできます。
00:06:25これはLaravel界隈から来たものだと思います。
00:06:28フロントエンドのシングルページアプリケーションと
00:06:32フルスタックアプリケーションのバックエンドとの架け橋のようなものです。
00:06:38もちろん、単にREST APIを構築してバックエンドとして使うこともできます。
00:06:46同じコントローラーで、3つの異なる戻り方ができるのです。
00:06:49なるほど、見てみましょう。
00:06:50Adonisのルーターを使ってルートを登録できます。
00:06:56コントローラーのポストメソッドですね、これがコントローラーです。
00:07:02その中で、viewRenderを呼び出して、以前に定義したビューをレンダリングできます。
00:07:06そしてこの特別な構文が、Adonisに同梱されているEdgeテンプレート言語です。
00:07:16代替案としてはInertiaを使う方法があります。そこでもコントローラーを使いますが。
00:07:20コントローラー内でrenderを呼び出し、ビューを指定してプロップスを渡すことができます。
00:07:28そう、プロップスを渡すのです。
00:07:30そして、ここにJavaScript、つまりReactのコードを置くことができます。
00:07:34そして私の理解では、サーバーサイドレンダリングされるはずです。
00:07:37基本的には、そのReactコンポーネント内でデータを取得する必要はありません。
00:07:42すべてが私たちのために処理されます。
00:07:44それもいいですね。
00:07:45どちらを使うかは、まあ、見てのお楽しみですね。
00:07:47フルスタックアプリを作ってみたいですね。
00:07:50でも、まあ見てみましょう。
00:07:51Edgeテンプレートエンジンから始めて、昔ながらのマルチページアプリケーションを作ろうかと思います。
00:07:57サーバーサイドでHTMLをレンダリングするようなものです。
00:07:59すべてのアプリケーションがクライアントサイドでReactを必要とするわけではありませんから。
00:08:03それは理解しておくべき非常に重要なことです。
00:08:05何を作るかによります。
00:08:07すべてのアプリケーションが超高反応でインタラクティブなフロントエンドを必要とするわけではありません。
00:08:12ブログのようなものを作るのであれば、ほとんどの場合必要ないでしょう。
00:08:16より複雑なアプリケーションであっても、必要ない場合があります。
00:08:20チャットを少し確認させてください。
00:08:22Hi, Max.
00:08:23AIエンジニアリングコースですか。
00:08:24いつかやるかもしれません。ただ、今は物事の移り変わりが非常に早いため、リリースした瞬間に
00:08:28そのコースの内容が時代遅れになってしまうでしょう。
00:08:32それは望んでいません。
00:08:32今日はまだいいです。
00:08:35まずはソフトウェアの基礎などに関するコースを先に作りたいと思います。
00:08:39もちろん、いつか私がAIとどのように仕事をしているかを共有したいとは思っています。
00:08:44ただ、毎週のように状況が変わる現状では、そうするべきではないですね。
00:08:48Hi, Max.
00:08:48Adonisは10年以上メンテナンスされていると聞きましたが、
00:08:51比較的ニッチな市場を考慮すると、これに賭けるのはビジネス上のリスクだと思いますか?
00:08:55はい、本当に良い質問ですね。
00:08:57非常に長い間メンテナンスされているのは知っています。
00:09:0110年とは知りませんでしたが。
00:09:02それでも確かに長い期間です。
00:09:05Adonisの背後にどれほどのチームがいるのかは分かりません。
00:09:09現時点でしっかりメンテナンスされていることは分かります。
00:09:13X(Twitter)上で、リードメンテナーでありAdonisプロジェクトのオーナーが活発に活動しているのを見かけます。
00:09:20世界中で使われているわけではないプロジェクトには、当然ながらある程度のリスクはつきものです。
00:09:30そうは言っても、これほど長期間メンテナンスされている事実は、リードメンテナーの献身的な姿勢を証明していると言えます。
00:09:38しかし、Vercelが支援しているNext.jsのようなプロジェクトの方が、長期間メンテナンスされる保証は高いだろうと言えます。
00:09:50もちろん、何が起こるか分かりませんが。
00:09:52Adonisには当然、Next.jsにはない利点もあります。
00:09:57でも、確かに妥当な懸念ですね。
00:10:00ライブ配信してくれて嬉しいです。
00:10:01プログラミング言語やフレームワークに対するあなたのアプローチが好きです。Adonisは一見面白そうですね。
00:10:05今日何が得られるか興味深いです。
00:10:07私も楽しみです。
00:10:08参加してくれてありがとう。
00:10:09楽しくなりそうですね。
00:10:10画面の領域をハイライトしているツールは何ですか?
00:10:12DemoProというアプリケーションです。
00:10:15Mac専用のアプリだったと思います。
00:10:17何年も前に購入したはずです。
00:10:21素晴らしいですよ。
00:10:21このように画面に描画できる機能をすべて提供してくれます。
00:10:25はい。
00:10:27なぜもっとJavaScriptコミュニティに受け入れられなかったのか不思議です。
00:10:30意見を持ったフレームワークは素晴らしいと思います。
00:10:33みんなSvelteやVueが好きなら、なぜAdonisは違うのか。
00:10:35そうですね。
00:10:36私もいつもそう思っていました。
00:10:37最初にAdonisを見たのは、7、8年前くらいでしょうか。
00:10:44その時もなぜ人気がないのか不思議に思っていました。
00:10:48自分自身、深く潜り込む時間を作れなかったんです。
00:10:52それに、決してメジャーな人気があったわけでもありません。
00:10:54だからコースのトピックとして取り上げることもありませんでした。
00:10:59でも、分かりません。
00:11:00見た目はいいんですよ、本当に。
00:11:02まあ、とにかく始めてみてどれほど良いものか確認しましょう。
00:11:07というわけで、始めましょう。
00:11:09はい。
00:11:10もちろんNodeが必要ですね。新しいアプリケーションを作成するにはnpm create。
00:11:16コピーします。
00:11:19もう小さなフォルダーを作成しました。
00:11:21npmではなく、より高速で少し安全なbunを使います。
00:11:25このフォルダーで作成できますか?
00:11:27うまくいくかな?
00:11:29はい。
00:11:29よし。
00:11:30さて、選択肢があります。
00:11:31ハイパーメディアアプリにしますか?
00:11:33つまりテンプレートエンジン、あるいはReactを使ったビューアプリ。
00:11:38ハイパーメディアで行きます。
00:11:39スターターキットをダウンロードして、依存関係をインストールし、データベースを移行します。
00:11:45基本的なスターターアプリケーションが提供されるようです。
00:11:53コマンド失敗。
00:11:55Node ace migration run。
00:11:58あれ。
00:11:59スタートからこれです。
00:12:01bunを使ったからでしょうか?
00:12:04それとも…
00:12:05最新のNode.jsであるNode 26を使っているせいかもしれません。
00:12:12Nodeで動かそうとしたのが問題だったのかも。
00:12:20見てみましょう。
00:12:21このように実行できるかな?
00:12:24はい。
00:12:25エラーが出ました、新しい例外ですね。
00:12:28おっと。
00:12:29ライブ配信で何か新しいことをやろうとすると必ず失敗する法則があります。
00:12:35Adonis bin console TSからstartenvモジュールが見つかりません。
00:12:45確認させてください。
00:12:47Nodeですか?
00:12:48古いNodeバージョンを使ってみましょう。
00:13:01ダメだ。
00:13:02今度は別のエラーです。
00:13:08バインディングファイルが見つかりません。
00:13:14分かりました。
00:13:14っと。
00:13:15Nodeバージョンの問題かもしれないので、このフォルダーの中身をすべてきれいに消去して
00:13:24今度はNPMで作り直します。供給連鎖攻撃でやられないことを祈ります。
00:13:34最近はNPMを使うのが本当に怖いんです。
00:13:38BUNやPNPMの方が好きです。
00:13:42よし。
00:13:43もう一度。
00:13:44うまくいきますように。
00:13:52ここまでは間違えようがないはずなのですが。
00:14:11コマンド失敗。
00:14:12本当にひどいスタートです。
00:14:19これは知られている問題でしょうか?
00:14:23何か既知のものですか?
00:14:27そうは見えませんが。
00:14:36分かりました。
00:14:37見てみましょう。
00:14:38AIに投げてみるのも手ですね。
00:14:43解決策を見つけてくれるか。
00:14:46今一番気に入っているコーディングエージェント、Piを立ち上げます。
00:14:57このプロジェクトでAdonisを始めようとしています。
00:15:02実行しました。
00:15:03コマンドは何でしたっけ。
00:15:04NPM create…
00:15:09そうです。
00:15:10NPM create。
00:15:13Adonis.js at latest dot。
00:15:17マイグレーションの実行で失敗しました。
00:15:22手動で実行しても失敗しました。
00:15:24エラーログを貼り付けて、どうなるか見てみましょう。
00:15:29おはようございます。
00:15:30あるいはこんばんは。
00:15:32こちらは午後です。
00:15:34AIが助けてくれるか見てみましょう。
00:15:38そのエラーメッセージを解析できるか見てみましょう。
00:15:41Adonis.jsとは何ですか?
00:15:42Adonis.jsはJavaScriptフレームワークです。
00:15:44フルスタックフレームワークですね。
00:15:47JavaScript版のLaravelのようなものです。
00:15:50Laravelを知っていればの話ですが。
00:15:51つまり、必要なものが全て揃ったフレームワークです。
00:15:53Nextとは違います。
00:15:54Next.jsやTanStack Startのようにルーティングやサーバーでのレンダリングが中心というわけではありません。
00:15:59その代わり、認証機能が標準で付いています。
00:16:01独自のORMも備えています。
00:16:03それが特徴です。
00:16:04今、初期セットアップでいくつか問題に直面しています。
00:16:10ああ、なるほど。
00:16:11つまり、それは…
00:16:14分かりました。
00:16:15納得です。
00:16:16Adonisの問題ではないようですね。
00:16:18おそらく。
00:16:19ただ問題は、このセットアップコマンドがライフサイクルスクリプトを実行しようとしたことにあるようです。
00:16:28依存関係に関連付けられた何らかのスクリプトですね。
00:16:31私はサプライチェーン攻撃を避けるためにignore-scriptsをtrueに設定しています。
00:16:35それにBunもデフォルトではスクリプトを実行しません。
00:16:38どうやら実行が必要なスクリプトがあったようです。
00:16:45そこでAIが一時的にこれを無効にしてくれました。
00:16:49そのおかげでマイグレーションが実行できました。
00:16:54なるほど。
00:16:57これで初期セットアップの手順で抜けているものは何もないはずです。
00:17:05やってみないと分かりませんが。
00:17:07もちろん、今から開発サーバーを立ち上げて試してみることはできます。
00:17:15では、やりましょう。
00:17:19いや、ここではそのブラウザは使いたくないですね。
00:17:22どうなるか見てみましょう。
00:17:24よし。
00:17:25画面に何か映りましたね。
00:17:31少し変な見た目です。
00:17:37これで正しいのでしょうか?
00:17:41ふむ。
00:17:43なるほど。
00:17:45まあいいでしょう。
00:17:50では、見ていきましょう。
00:17:51ここでサインアップができますね。
00:18:05これでログイン状態になりました。
00:18:07ログアウトもできます。
00:18:08すべて箱から出した時点で準備完了です。
00:18:12定番の問題は、何もなくていいところで必ず起きますよね。
00:18:15ええ。
00:18:16まさにその通りです。
00:18:17ライブ配信で新しい技術に触れようとすると、今回で3回目くらいの失敗ですよ。
00:18:22でもまあ、なんとかなりました。
00:18:23ええ。
00:18:23今はうまく動いています。
00:18:25問題なく動作しているようです。
00:18:31このtempフォルダは少し気になります。
00:18:33ここが本番データベースの場所でしょうか?
00:18:36それとも開発用ですか?
00:18:37スキーマ。
00:18:38ユーザー。
00:18:39ええ。
00:18:39よし。
00:18:40SQLiteを使っているんですね。軽量でシンプルなので気に入っています。
00:18:45中身については、すぐ後で探求してみましょう。
00:18:48Udemyは講師をフォローして、新しいコンテンツが出た時に通知を受け取る機能を付けるべきですね。
00:18:53本当にそう思います。
00:18:54他の講師仲間とも一緒に、Udemyには追加すべきクールな機能について随分前から伝えてきたのですが。
00:19:01まあ、でも。
00:19:02彼らはやりたくないのでしょうね。
00:19:05AIを使う前に自分で解決しようとする姿勢が良いですね。
00:19:08私なら真っ先にコピペしてAIに投げてしまいます。
00:19:11私は破滅に向かっているようです。
00:19:12まあご覧の通り、私ができなかったことをAIが解決してくれました。
00:19:15ただ、長いエラーログを全部読むのは気が進みませんでした。このストリームはデバッグの場ではなく、Adonisの紹介の場にしたかったので。
00:19:25ですから、特に長いエラーメッセージの解析や推論については、AIは本当に優秀です。
00:19:31ただ、AIに投げる前に一度、自分自身でも軽くエラーメッセージに目を通すのは理にかなっていると思います。
00:19:38なぜなら、A、非常に簡単に解決できる場合があるからです。
00:19:42ポート番号の競合のような単純なことかもしれません。
00:19:45今回は違いましたが、他の問題ではよくあります。
00:19:47それにBとして、何が起きているのか、どこで何が壊れているのか、少なくとも把握しておくことは決して損ではありません。
00:19:58何はともあれ、何があるか見てみましょう。
00:20:01プロジェクトには、明らかにpackage.jsonファイルがありますね。
00:20:08プロジェクトを構成するファイルのマッピングもいくつかあります。
00:20:14Adonisからの依存関係もいくつかありますね。
00:20:19Vineとは何でしょう?
00:20:24バリデーションライブラリですね。了解。
00:20:25バリデーションライブラリ、better-sqlite3、edge.js、これはテンプレート言語のようですね。
00:20:34Luxonとは?
00:20:39それは何でしょう?
00:20:41日時を扱うライブラリですね。
00:20:44なるほど。それからアサーション、テストランナー、型定義、Alpineもあります。
00:20:54Alpineは本質的に、軽量なクライアントサイドJavaScriptを追加するためのライブラリです。Reactのような巨大なライブラリを使わずに済みます。
00:21:05なるほど、adonisrc.tsは設定ファイルのようですね。実験的なフラグやコマンド、登録するaceコマンドの一覧があります。
00:21:15Laravelを使わなくなってから随分経ちますね。
00:21:202014年や2015、2016年頃にはよくLaravel開発をしていました。記憶ではLaravelもAdonisのように多機能で、独自のコマンド登録も可能でした。
00:21:38Laravelではartisanコマンドだったかと思いますが、ここではnodeで実行するaceコマンドのようです。
00:21:49つまりこれはAdonisが提供するツールで、独自のサブコマンドを登録できるということですね。
00:22:05コマンドを登録すれば独自のユーティリティツールのように使えるということでしょう。
00:22:15サービスプロバイダーのインポートと登録…理解としては、これは依存性の注入や、ウェブサーバー起動時に実行される様々なサービスの登録に関連しています。
00:22:26何がありますか?
00:22:28何がありますか?
00:22:28データベースプロバイダーや認証プロバイダーなど、各機能に対応する様々なプロバイダーがあるようです。
00:22:34プリロードもある。つまりこれが設定ファイルということです。
00:22:40他には何がありますか?
00:22:41envファイルがあってポートの設定などがあります。ログレベルやアプリキーもあります。
00:22:50何に使われるのか分かりませんが、パスワードのハッシュ化などでしょうか。
00:23:01セッションドライバーはCookie。認証にCookieを使うということですね。データベース設定もあります。
00:23:12Git管理外。
00:23:14Tempフォルダですね。
00:23:16テストフォルダにはユニットテストがセットアップされています。
00:23:23Resourcesフォルダ。これもLaravelと同じですね。
00:23:27LaravelでもResourcesフォルダには主にフロントエンドのリソースがありました。ここではクライアントサイドのCSSやJavaScript(Alpine使用)があります。
00:23:40Viewフォルダ。これがフロントエンドのページ、つまりページとしてレンダリングされるテンプレートやコンポーネントです。
00:23:49テンプレートシステムの仕組みはまだ分かりません。
00:23:53拡張機能をインストールできるか試してみます。サプライチェーン攻撃に遭わないといいのですが。
00:24:02Edgeテンプレートのサポートですね。Adonis.js公式の構文ハイライターです。
00:24:09インストールします。
00:24:12ああ神様、ハックしないでください。
00:24:16良くなりました。
00:24:18これで構文がハイライトされます。
00:24:20テンプレート言語の考え方ですが、昔は他のJavaScriptフレームワークでもテンプレート言語を使うのが一般的でした。
00:24:32本質的な考え方は、サーバーでHTMLページをレンダリングし、完成したHTMLコードをクライアントに送るというものです。
00:24:39より便利で動的にするために、異なるテンプレートからHTMLファイルを構成し、プレースホルダーを動的な値に置き換えます。
00:24:51ここで言えば、Pagesフォルダにあるホームページは、あるレイアウトをベースにしているようです。
00:25:02レイアウトはいくつか定義できるのでしょう。指定がない場合はデフォルトのレイアウトが使われるのでしょうね。
00:25:09そしてこの部分がレイアウトに注入されます。
00:25:12レイアウト内にはプレースホルダーがあるはずです。
00:25:14レイアウトはcomponentsフォルダに定義されていますね。
00:25:20これがレイアウトファイルです。
00:25:22HTMLの基本構造が見えますね。
00:25:24ボディの中に「main」スロットがあります。
00:25:29これが実際のページコンテンツがレンダリングされる場所を定義する、Edgeテンプレート言語の構文のようです。
00:25:39繰り返しになりますが、この言語の詳しい仕組みは分かりません。
00:25:42読み解こうとしているだけです。
00:25:44名前を指定できるのでしょうか?
00:25:47あるいは予約語かもしれません。
00:25:49分かりません。
00:25:50非同期ですね。
00:25:51興味深いです。
00:25:52awaitしています。
00:25:53つまり、ここがレンダリングされるまでレイアウトのレンダリングは完了しないわけです。
00:25:57「slots main」。
00:25:59どうやらこれが予約語のようですね。
00:26:01それ以外にもLaravelで見かけたパーシャル(部分テンプレート)という概念があります。レイアウトだけでなく、他のページにもコンポーネントを取り込める仕組みです。
00:26:18ヘッダーのパーシャルやフラッシュアラートなど、画面に表示するメッセージ用などがあるようですね。
00:26:26例えばヘッダーのパーシャルはpartialsフォルダのheaderにあります。
00:26:33中身を見てみましょう。
00:26:35リンクをレンダリングするためのテンプレート構文があります。
00:26:40リンクは動的なのでこのようにレンダリングされます。
00:26:43内部リンクの場合、登録したルートに依存します。
00:26:47ここでは「ホーム」というテキストでホームルートへのリンクを設定しています。
00:26:52確認できますね。
00:26:54どこで確認できますか?
00:26:55下の方で見られますか?
00:26:58いや、違う。
00:26:59これです。
00:26:59SVGですね。
00:27:01これが先ほどのSVGだと思います。
00:27:04「home」という名前がフォールバックになっています。
00:27:06クリックするとホームルートへ移動します。
00:27:13ユーザーがログインしているかどうかに応じた条件付きレンダリングもありますね。
00:27:19納得です。
00:27:20これも全部ヘッダーの中ですね。
00:27:23なるほど。
00:27:23こちらのViteという記述ですね。
00:27:26フロントエンドのアセット、CSSやJavaScriptのバンドル管理にViteを使っているようです。
00:27:35最適化されバンドルされたapp.jsとapp.cssがここに注入されるのでしょう。
00:27:45ResourcesフォルダのJSとCSSにあるものがそうですね。
00:27:49そのJavaScriptとCSSファイルです。
00:27:53処理されているのかどうか分かりませんが。
00:27:57なるほど。
00:27:58メインの開発サーバーを立ち上げるとViteサーバーも自動で起動するようですね。
00:28:05なるほど。
00:28:06納得です。
00:28:06全てを理解しているわけではありません。
00:28:08このスタック云々はおそらくデバッグ用でしょう。
00:28:11知りませんが。
00:28:12さらにコンポーネントがありますね。
00:28:15ええ。
00:28:16掘り下げていかないといけませんね。
00:28:17何が起きているのか正確に。
00:28:19追々やっていきます。
00:28:21チャットに戻りましょう。
00:28:22いくつか質問を。
00:28:24LLMモデルはコストが高くなり、補助金もなくなっています。
00:28:28オープンソースや自己ホスト型のモデルがより重要になるでしょうか?
00:28:31その結果、開発者はDevOpsを学ぶべきでしょうか?
00:28:35将来的に、オープンモデルは全体として重要度が増していくと思います。
00:28:42ですが、自分で運用するとなれば当然コストがかかります。
00:28:45高性能なローカルマシンが必要になりますから。
00:28:48Mac Studioに1万ドルかけるとか、そういうレベルの話です。
00:28:52あるいはレンタルするしかありません。
00:28:53つまり、いずれにせよ費用はかかるということです。
00:28:56ですが、フロンティアモデルの価格次第では、オープンモデルは面白い代替案になるかもしれません。
00:29:03何をしたいかにもよりますが、本当に高性能なオープンモデルはまだ多くありません。
00:29:10でも、いずれそうなるでしょう。
00:29:12ただ、だからといってDevOpsを学ぶべきとは思いません。
00:29:16興味があるなら学べばいいことです。
00:29:19しかし、自分のオープンモデルをデプロイして動かすことは、ハードウェアがあるなら、あるいはVPSを借りるなら、一度やってみれば済むことです。
00:29:25一度やってみればいいんです。
00:29:28一度正しくセットアップする方法を知るだけでいいんです。
00:29:32DevOpsの知識が幅広く必要というわけではありませんね。
00:29:36それから、私のFlutterコースを受講してくれてありがとう。
00:29:41素敵な言及をありがとう、Don Solidさん。
00:29:47「なぜ直接AIサービスを使わず、このツールを使う必要があるのですか?」
00:29:51どのツールのことを指しているのか分かりませんが。
00:29:54「Udemyで新しいコースを公開する予定はありますか?」
00:29:57「まだUdemyでコースを出していますか?」
00:30:01時々ですが、出しています。
00:30:02ただ、今のUdemyはあまり良い方向には向かっていませんね。
00:30:07ですから、Courseraによる買収などが今後どう影響するか見ていく必要があります。
00:30:14それと、コンテンツセキュリティポリシーについては、そのレイアウトに行けばいいはずです。
00:30:22必要なものをheadセクションに追加するだけです。
00:30:25結局はただのHTMLですから、ここに追加すればいいのです。
00:30:32ですから、それでうまくいくはずです。
00:30:34ただ、私はAdonisを触り始めたばかりなんですけれどね。
00:30:42よし、これで分かりました。
00:30:44フロントエンドやリソースは、今のところそのままにしておきましょう。
00:30:48startフォルダを見てみましょう。
00:30:50これはサーバーサイドの部分でしょう。他の部分はまだ確認していませんが。
00:30:56他にもあります。
00:30:57databaseがあり、そこにマイグレーションが含まれています。
00:31:00ここでの考え方は他の多くのフレームワークと同じで、データベーステーブルを定義します。
00:31:08マイグレーションファイルを使って、この形式になっているようです。
00:31:12マイグレーションファイルを自動生成するためのコマンドも用意されているはずです。
00:31:17そしてマイグレーションを実行してデータベースに適用し、テーブルやスキーマを計画します。
00:31:24これがschema.tsですね。
00:31:28なるほど、データベースのテーブルをクラスとして設定するということですね。
00:31:33そして、おそらくコマンドを通じてプログラム的にマイグレーションを作成するのでしょう。
00:31:40configもありますね。設定項目がたくさんあります。
00:31:43なるほど、ここでいろいろな設定ができるわけですね。
00:31:50分かりました、必要な時にまた確認することにします。
00:31:53binのserver.ts、これがHTTPサーバーのエントリポイントですね。
00:31:57server.tsファイルはAdonis.jsのHTTPサーバーを起動するエントリポイントです。
00:32:02ファイルを直接実行することも、serveコマンドを使うこともできます。
00:32:05開発サーバーをserveコマンドで起動した時に、これが実行されていたわけですね。
00:32:13中で何をしているのでしょう?
00:32:18インポーター、イグナイターですね。
00:32:23基本的には、サーバーを立ち上げてポートでリッスンを開始しています。
00:32:27どこかでルートを登録しているはずです。
00:32:34consoleはAdonis.jsのコマンドラインフレームワークを起動するエントリポイントです。
00:32:38カスタムコマンドを登録したり、aceコマンドで組み込みコマンドを実行したりする場所だと思います。
00:32:45そしてappですね。
00:32:46ここでスタートアップ関連を登録するのですね。
00:32:49startフォルダは興味深そうです。
00:32:51例えばstartフォルダにはroutes.tsファイルがあります。
00:32:54ここでアプリケーションのルートを登録しているわけです。
00:33:00例えば、スラッシュだけのルートなら。
00:33:02ドメインのトップページですね。
00:33:04ホームページをレンダリングしています。
00:33:06ここではresourcesのviewsフォルダ内のパスを参照しています。
00:33:12つまりresourcesのviews内ですね。
00:33:15例えばrender pages/homeとあれば、pagesフォルダを参照します。
00:33:20そしてその中のhomeをレンダリングします。
00:33:23本質的にはそういうことが起きているわけですね。
00:33:28また、ルートをグループ化することもできます。
00:33:31なぜグループ化するのかというと?
00:33:33共有ミドルウェアを適用するためですよね。
00:33:35ゲストミドルウェアとか。
00:33:38何をするにしても。
00:33:40ここにサインアップとログインのルートがありますね。
00:33:44未認証ユーザーのみがアクセスできるミドルウェアが適用されているのでしょう。
00:33:49その一方で、認証済みユーザーのみがアクセスできるauthミドルウェアもあります。
00:33:56ログアウトのルートなどがそれで、ログアウトする場合にのみ意味を成します。
00:34:00全てのルートは、このように直接何かをレンダリングするか、Laravelでも知られているようにコントローラーとメソッドを接続するのが一般的です。
00:34:21ここではサインアップ用にGETとPOSTのルートがあり、同じコントローラーファイル内で、作成用と保存用のコントローラーメソッドに接続しています。
00:34:35Adonis.jsのサーバー内にあるcontrollers.tsファイルを見てみると。
00:34:47ええ、でもこれは動的に作成されているんでしょう?
00:34:51私たちが作ったのでしたっけ?
00:34:53違いましたか?
00:34:55いえ、ここでコントローラーを登録しています。
00:34:59これは動的に生成されているのだと思います。
00:35:01ここにNewAccountControllerがあります。
00:35:04NewAccountControllerクラスですね。
00:35:08その中にcreateメソッドとstoreメソッドがあります。
00:35:12結局、これらがこの名前の責任を負っているわけです。
00:35:15これもまた動的、あるいは自動的に作成されているのだと思います。
00:35:21GETルート用のcreateでは、ただビューをレンダリングしていますね。
00:35:25もちろん理論上はこれを使わなくても、直接GETでレンダリングもできるはずですが。
00:35:41そうですね、無理なのかな。直接レンダリングはできないのでしょうか?
00:35:46コントローラーを使わないといけないのでしょうか。
00:35:50どうやらそうみたいですね。
00:35:51結局のところ、さっきのようにレンダリングしています。
00:35:56POSTルートでは、組み込みのバリデーターを使ってユーザー入力を検証していますね。
00:36:04そしてユーザーモデルを使って新しいユーザーインスタンスを作成しています。これについてはまた後で。
00:36:11その後、そのユーザーをWeb用に認証します。
00:36:15つまり、セッションベース、クッキーベースの認証ですね。
00:36:18そしてホームページにリダイレクトします。
00:36:21なるほど、見てみましょう。
00:36:24modelsフォルダがありますね。
00:36:26そこにユーザーモデルが定義されています。
00:36:28先ほど、データベーステーブルやスキーマがあると言いましたよね。
00:36:40おそらくモデルを定義するだけで、残りは自動的に生成されるのでしょうが、見てみましょう。
00:36:47結局、アプリケーションでユーザーを使いたいと定義しているわけです。
00:36:53Adonisから提供されている機能を継承しています。
00:36:57ここにinitialsというゲッターがありますね。
00:37:03これは姓名を組み合わせてユーザーの氏名を取得するための単純なヘルパー関数です。
00:37:10こういう計算された値をどのように作成できるかを示すためのものです。
00:37:15分かりました、理解しました。
00:37:17ユーザー用のバリデーターですね。
00:37:19これは初めて知ったwineライブラリを使ったバリデーションファイルで、空ではないメールアドレスと最大長を確保しています。
00:37:31失礼しました。
00:37:36バリデーターの再利用可能なパーツを作っておいて、サインアップなど値の強制が必要な場所で使えるようですね。
00:37:49authミドルウェアはhandleメソッドを持つクラスで、何かをチェックして、ユーザーが向かっているルートへのアクセスを許可するならnextを返します。
00:38:07認証に失敗した場合、次のナビゲーションを防ぐために例外をスローしているのだと思います。
00:38:14ゲストミドルウェアはその逆でしょう。
00:38:21ええ、ユーザーが認証されているか確認して、もしそうならリダイレクトさせます。
00:38:28認証されていない場合にのみ、向かっていた先へのアクセスを許可します。
00:38:32なるほど。
00:38:33Exceptionsで、独自のエラーや例外を定義できます。
00:38:38なるほど。
00:38:40分かりました。
00:38:42そういうことですね。
00:38:45「近い将来、どんな新しいコースをリリースする予定ですか?」
00:38:52BUNに関する何かかもしれません。
00:38:55満足できるコースになるかどうか、まだ検討中です。
00:38:58すでにいくつか録画はしましたが、品質や方向性に満足できるか確認したいのです。
00:39:06ソフトウェア工学の基礎やシステム設計など、今年作りたいコースはいくつかあります。
00:39:12エージェンティックAIについては、売れるとは思いますが先ほど答えた通りです。
00:39:20エージェンティックエンジニアリングやAIとの関わり方を共有するコースを作りたい気持ちはあります。
00:39:26ただ、あまりにも変化が激しすぎます。
00:39:30今の時点では、あまり有益ではないかもしれません。
00:39:33もう少し安定してきたら、エージェンティックエンジニアリングやAIエンジニアリングといった名前のコースを作りたいですね。
00:39:42Puck.jsのようですね。
00:39:44ええ。
00:39:45「2026年に使う人はいるのでしょうか?」
00:39:48「誰もVueは使わないと思います。すべてSPAですよね」
00:39:51ええ、すべてはSPAですね。
00:39:53それについては私は同意見ではありません。
00:39:56私たちはSPAやどこでもReactという環境に慣れすぎてしまいました。
00:40:01Reactは素晴らしいです。
00:40:02それにAIがReactを好むというのは、確かにその通りです。
00:40:07Adonisは全体的にかなりニッチですが。
00:40:10でも、すべてにReactを使うべきだというのは間違った思い込みです。
00:40:17サーバー側でテンプレートをレンダリングするだけで十分な場合も多いのです。
00:40:23それだけで十分なこともあります。
00:40:24Reactを追加することで複雑さが増し、バンドルサイズも大きくなります。
00:40:30ここ数週間に起きたセキュリティ脆弱性について考えてみてください。
00:40:35ただ使い慣れているからという理由で、不必要なものを導入しないことには価値があります。
00:40:41私たちは何でもReactを使うことに慣れてしまい、それを当たり前だと思っています。
00:40:47でもそうとは限りません。
00:40:49ええ、確かに同意します。
00:40:50これは確かに少し古く見えますね。
00:40:53さっき言ったように、私も何年も前にこのような方法でページを書いていました。
00:41:00それでも、今となっては間違っているとは思いません。
00:41:03確かに一般的ではありませんし、ネイティブな感じはしませんが、理にかなっているとも言えます。
00:41:12理屈は通るでしょう。
00:41:14ただ、Adonisはビューをレンダリングする異なる方法もサポートしています。
00:41:23Inertia.jsをブリッジとして使い、フロントエンドにReactを使うこともできます。
00:41:29ですから、このビューベースのアプローチを取らずにフルスタックのAdonis.jsアプリを構築することも十分に可能です。
00:41:38ですが、どのような感じか知りたかったので、今回は試してみたかったのです。
00:41:43Hanoに似ていますね。
00:41:45そうですね、Hanoの方がずっと軽量ですね。
00:41:48Hanoには認証やORMのような機能が最初から組み込まれているわけではありませんから。
00:41:56「Adonis.jsの感触はどうですか?」
00:42:00興味深いですが、これまで一度も使ったことがありません。
00:42:03ですから、今日初めて触ってみているところです。
00:42:05始めたばかりです。
00:42:07一つのフレームワークにすべてが含まれているという考え方はいいなと思います。
00:42:13最近のサプライチェーン攻撃のニュースを考えると特にそうですね。
00:42:16JavaScriptのエコシステムでは、私たちは複雑すぎる解決策を選びがちです。
00:42:21何十ものライブラリを組み合わせることは、サプライチェーンの問題だけでなく、
00:42:26ライブラリが適切にメンテナンスされていないという問題もあります。
00:42:31ですので、「電池付属(オールインワン)」なフレームワークには間違いなく利点があります。
00:42:39「プログラミングの基礎知識があるCS学生には、どう学ぶことを勧めますか?」
00:42:44次のステップは何でしょうか?
00:42:45プロジェクトを作るべきか、AIを探求するべきか。
00:42:46私ならAIを学習のために使います。
00:42:48AIの助けを借りてプロジェクトを作るのも良いですが、AIに依存しきってはいけません。
00:42:53それでは何も学べないからです。
00:42:54ソフトウェア工学の基礎を学ぼうとします。
00:42:57自分自身の手でコードを書こうとします。
00:43:01AIが生成したコードをレビューし、本当に理解しようとします。
00:43:05批判的に検証します。
00:43:07AIをコードの議論相手としても使うかもしれません。
00:43:10正直に言うと、AI時代にどうやって教え、学ぶのがベストか、私もまだ模索中です。
00:43:15日々試行錯誤しています。
00:43:20AIに聞くとき、どうやって学びに変えるプロジェクトを作るのか。
00:43:27ええ。
00:43:27AIをスパーリングパートナーとして使うということです。
00:43:32なるほど。
00:43:32では見てみましょう。
00:43:34さっき話した代替案も確認したいですしね。
00:43:38コードの編集も始めましょう。
00:43:40代替案も見てみたいんです。
00:43:42もし〜を使ったら。
00:43:47これを再現させてみます。
00:43:49最初から作り直したいので。
00:43:51再現させてみます。
00:43:52サーバーを止めて。
00:43:53React Kitを使った代替アプローチを試しましょう。
00:44:01またクラッシュするかもしれませんね。
00:44:08さっと確認させてください。
00:44:15どのコマンドでうまくいったんだっけ。
00:44:19恒久的な。
00:44:20恒久的にはしたくないな。
00:44:27これならいけるはずです。
00:44:32見てみましょう。
00:44:36見てみましょう。
00:44:37おっと。
00:44:38そうするつもりじゃなかった。
00:44:39ドット一つで十分です。
00:44:42よし。
00:44:44これでうまくいくか見てみよう。
00:44:55ズボンをシュワルツミューラー(ドイツ風)にする?
00:44:57それが良いことなのか悪いことなのかは分からないけど。
00:45:09Flutterコースを一から自分で設計したかって?
00:45:11ああ。
00:45:12すべて自分の作品だよ。
00:45:14じゃあ、もう一度起動してみよう。
00:45:21同じように見えるか確認しよう。
00:45:24ああ。
00:45:25同じアプリだ。
00:45:26でも当然、ファイル構造は変わっているはずだ。
00:45:29見てみよう。
00:45:32appフォルダ。
00:45:36今、transformerがある。
00:45:38でも、あれは単なるバックエンド関連の物だと思う。
00:45:42いや。
00:45:42サーバーからクライアントへデータを送信するためのものだと思う。
00:45:46フロントエンドへのね、見てみよう。
00:45:48bin、config、database、inertia。
00:45:53なるほど。
00:45:53Inertiaがフロントエンドのフォルダなんだな。
00:45:56CSS。
00:45:57ああ。
00:45:57よし。
00:45:58さて、ここには何があるかな?
00:45:59app.tsxファイルがある。
00:46:11何なのかは分からないけど、フロントエンドをハイドレーションしてバックエンドと接続するためにあるんだと思う。
00:46:18createInertiaAppだ。
00:46:20ページタイトルを設定しているみたいだね。
00:46:22App。
00:46:23よし。
00:46:24viteのconfigファイルがエラーを表示しているけど、それは非推奨だからだ。
00:46:29問題ない。
00:46:32Server-side rendering TSX。
00:46:34つまり、サーバーサイドレンダリングのエントリーポイントとクライアントのエントリーポイントということか。
00:46:39よし。
00:46:39Inertiaがどう動くのか、この2時間ほどの仕組みがどうなっているのか全然分からない。
00:46:46ホームページがここにある。
00:46:47つまり、これは普通のReactコンポーネントなんだな。
00:46:51特別なことは何もない。
00:46:52レイアウトとかはあるかな?
00:46:53ああ、レイアウトがあるね。
00:46:54default.tsx。
00:46:55これはどこで設定されている?
00:46:56appで設定されているのか?
00:46:59ページコンポーネントを解決。
00:47:00pagesフォルダの中を探す。
00:47:03layout、layout、layout、layout。
00:47:05レイアウトがインポートされている。
00:47:07なるほど。
00:47:08そういう仕組みになっているんだな。
00:47:10ここにレイアウトがある。
00:47:12そしてデフォルトのレイアウトがある。
00:47:16よし。
00:47:16おっ、useEffectがある。
00:47:19それは禁止だ。
00:47:24よし。
00:47:25ああ。
00:47:26つまり、本当にただのReactなんだ。
00:47:27僕たちが知っているように、linkコンポーネントはInertiaから来ている。
00:47:30あるいはAdonis.jsと、そのInertiaパッケージからだ。
00:47:35よし。
00:47:37僕の理解だと、そうだな。
00:47:47ああ。
00:47:47childrenは明らかに...
00:47:51よし。
00:47:52よし。
00:47:53よし。
00:47:54面白い。
00:47:54childrenは、もちろんReactのいつものように、タグの間のコンポーネントだ。
00:48:05でもchildrenにはuserプロパティを持つpropsオブジェクトもある。
00:48:13それがどこかのコントローラーで値を代入されているんだと思う。
00:48:20サインアップのコントローラーか、Inertiaレンダリングの新しいセッションのコントローラーか。
00:48:29でもそこではpropsを渡していないな。
00:48:32セッションコントローラーか。
00:48:35どこでこれに値が入っているんだ?
00:48:36ここにはtransformerというものがあって、それがサーバーサイドからクライアントサイドへのデータ変換用かと思っていた。
00:48:46確信はない。
00:48:50これを返す、このリソース、何なのか。
00:48:56データベースからデータを取得するためだけのものかもしれない。
00:48:59分からない。
00:49:01よし。
00:49:02設定は分かった。
00:49:03公式ガイドを続けよう。
00:49:05まず自分でコードベースを探索するのが本当に好きなんだ。
00:49:08ガイドに従う前に、自分で理解しようと試みるのがいい。
00:49:12そうする方が少しは学習できるような気がするから。
00:49:16それに、最近は誰もコードを読まないだろう?
00:49:18だから、配信でやってみるのもいいんじゃないか。
00:49:22冗談だよ。
00:49:23ちゃんとコードは読んでいる。
00:49:26フォルダ構造。
00:49:28よし。
00:49:28今、フォルダ構造を探索したところだ。
00:49:31appフォルダ。
00:49:32appディレクトリは、アプリケーションのドメインロジックのコードを整理する。
00:49:36例えば、コントローラー、モデル、メールなどだ。
00:49:39Laravelのように、メール送信もサポートしていて、とても便利になり得る。
00:49:44binディレクトリには、Adonis.jsアプリケーション、コンソール、サーバーTSを起動するためのエントリーポイントファイルが含まれている。
00:49:50アプリのブート方法をカスタマイズしたい場合を除いて、通常はこれらのファイルを修正する必要はない。
00:49:56よし。
00:49:56config、すべてのアプリケーションおよびサードパーティの設定ファイルはconfigディレクトリ内にある。
00:50:01アプリケーションローカルの設定もこのディレクトリ内に保存できる。
00:50:05そう、configフォルダにはすでにデータベースのようなものがあって、SQLiteを使っている。
00:50:13Postgresデータベースなどにも接続できるはずだ。
00:50:20クライアントを選択できる。
00:50:21だからBunのSQLiteクライアントなどが使えるかもしれない。
00:50:24分からないけど。
00:50:25データベースのパス、一時パスを定義する。
00:50:28つまり、tempフォルダ、マイグレーション、その他には何があるかな。
00:50:34config、inertia、server-side rendering、サーバーサイドレンダリングモードの切り替え。
00:50:39ああ、サーバーサイドレンダリングが欲しいから、これをtrueにしよう。
00:50:47Logger、ああ。
00:50:48なるほど、理にかなっている。
00:50:50すぐに確認したい。
00:50:52これをfalseに設定したら、ページソースを見ると、データが渡されたdiv appがあるはずだ。
00:51:06ああ、でもクライアントサイドレンダリングなので、主要なHTMLコンテンツが欠けている。
00:51:10クライアントサイドレンダリングを行うスクリプトをインポートしているんだ。
00:51:15検索エンジン最適化には良くない。
00:51:18だからこれをtrueに設定すると、ほら、中身がずっと増えている。
00:51:26すべてインラインなので少し読みづらいが、実際のHTMLコンテンツが存在する。
00:51:31だから、これはtrueにしておく。
00:51:34よし、データベースだ。
00:51:35databaseディレクトリは、データベースレイヤー関連のアーティファクトを保持する。
00:51:39デフォルトでは、Lucid ORMを使用している。
00:51:43ORMの考え方は、データベーステーブルをモデルとして、コード内のクラスとして表現するというものだ。
00:51:51そして、基盤となるスキーマとマイグレーションが自動的に生成される。
00:51:57このフレームワークを探索するのは初めてなので、すべてがどう機能するのか解明しているところだ。
00:52:03データベースの切り替えでこのフォルダを再構成する必要はない。マイグレーション、バージョン、スキーマ変更、シードデータ、管理ユーザーの初期データなどがある。
00:52:15よし、providersだ。
00:52:16providersディレクトリは、アプリケーションで使用されるサービスプロバイダーを格納するために使用される。
00:52:20サービスプロバイダーとは何か?
00:52:22サービスプロバイダー。
00:52:22このガイドがサービスプロバイダーをカバーしている。
00:52:24全部を読み通すことはないだろうけど。
00:52:27サービスプロバイダーは、アプリケーションの起動や終了の特定の時点で実行されるライフサイクルフックを持つJavaScriptクラスだ。
00:52:35これにより、IoCコンテナへのバインディングの登録、マクロを使用したフレームワーククラスの拡張、正確なタイミングでの初期化、終了時のリソースのクリーンアップが可能になる。
00:52:53つまり、組み込みプロバイダーがあるわけだ。
00:52:58どこにあるんだ?
00:53:02前にも見たはずだ。
00:53:04組み込みプロバイダーはどこだ?
00:53:09Providers。
00:53:09ここにAPIプロバイダーがある。
00:53:12APIレスポンス用のカスタムシリアライザーだ。
00:53:17なるほど、データをシリアライズするためのプロバイダーがあるようだ。
00:53:22デフォルトのミドルウェアなどを登録する認証などを助ける、組み込みのプロバイダーがもっとあると思う。
00:53:30そう推測する。
00:53:33保存はしないでおこう。
00:53:35よし、publicだ。publicディレクトリには未加工の静的アセットが含まれている。
00:53:39このフォルダを見落としていたかな?
00:53:40Public。
00:53:46publicフォルダがない。
00:53:48でも、公開用のアセットがないなら必要ないということか。
00:53:51最適化されない未加工のアセットを置くために、publicフォルダを追加することはできるだろう。
00:54:05Adonisには求人がほとんどないように見える。
00:54:07なぜ需要のないものを探索しているんだ?
00:54:10ただの趣味?
00:54:10もし君が仕事を探しているなら、Adonis.jsは...
00:54:15ああ、それはとても難しい質問だ。
00:54:17つまり、求職中ならAdonis.jsは役には立たないだろうね。
00:54:22でも、代替案を探索することは常に視野を広げてくれる。
00:54:27他の技術スタックを持つ他のアプリケーションにも応用できる新しい概念を学べるかもしれない。
00:54:33楽しいからというのは、とても有効な理由だ。
00:54:36それに、もし求職中ではなく、自分のSaaSやビジネスを構築しようとしているなら、一つの有効な選択肢になるかもしれない。
00:54:48仕事を探している場合、場所によっては非常にニッチかもしれない。
00:54:52正直に言うと、とてもニッチすぎて仕事を見つけるのは難しいだろう。
00:54:58でも当然、その仕事がある地域なら競争相手は少ないはずだ。
00:55:01まあ、それは理論上の話だけど。
00:55:07とにかく、僕にとっては今はただ楽しいんだ。
00:55:088年前に読んだことがあるから探索したいだけさ。
00:55:10そして、ようやくそれがどう動くのかを理解したいんだ。
00:55:15リソースディレクトリはEdgeテンプレートと、Inertiaアプリ内のCSSやJavaScriptなどのコンパイルされていないフロントエンドアセットを保存する。
00:55:19リソースディレクトリには、Inertiaアプリにおけるエッジテンプレートや、CSSやJavaScriptファイルといったコンパイル前のフロントエンドアセットが格納されます。
00:55:30リソースはあるかな?
00:55:32Inertial layout。
00:55:33ああ。
00:55:35なるほど。
00:55:35つまり、このReactアプリがレンダリングされる未加工のHTMLスケルトンのようなものだ。
00:55:41ここでコンテンツセキュリティポリシーを設定できるな。
00:55:44ここにいくつかの静的アセットを持ち込めると思う。
00:55:48すでに持っているものに加えて、メタデータを登録できる。
00:55:51よし。
00:55:52Inertiaディレクトリは、Inertiaスターターキットを使用しているプロジェクトにのみ存在する。
00:55:56理にかなっている。
00:55:57それはフロントエンドのソースコードを含むサブアプリケーションを表している。
00:56:01整理するためにコンポーネント、レイアウト、utilsなどの追加フォルダを自由に作成できる。
00:56:06つまり、本質的にはそこでビューやReactアプリを構築しているわけだ。
00:56:09フロントエンドとバックエンドの明確な分離。
00:56:11Adonis.jsはバックエンドとフロントエンドの間に明確な境界線を維持する。
00:56:14何も公開しないように、あるいはNode.js APIがブラウザのクライアントでは実行できないのでクラッシュしないように、バックエンドコードをフロントエンドにインポートしてはいけない。
00:56:30実際には、フロントエンドはHTTPリクエストを通じてバックエンドと通信し、プレーンなJSONデータを受け取る。
00:56:35Adonis.jsは、この現実を明確にモデル化するよう推奨している。
00:56:39データはAPIレスポンスを介してフェッチされ、変換される。
00:56:43Inertiaを使っている時、正確にはどうやって通信しているのか興味がある。
00:56:49ログインしてみよう。
00:56:52ここにフォームがある。
00:56:54ああ。
00:56:54そして面白い。
00:56:56それはAdonis.jsフレームワークから来ているコンポーネントだ。
00:57:01ルートを指定しますが、普通のReactアプリのように自分たちで構築したREST APIへHTTPリクエストを送るわけではないですよね?
00:57:12その代わり、昔ながらのマルチページアプリケーションのように、フォームをルートに接続して構築しました。
00:57:19フォームを送信すると、舞台裏でInertiaとAdonisがリクエストを作成し、そのルートへ送信してくれると想定しています。
00:57:28すべてが本質的に自動で処理されるというわけですね。
00:57:31つまり、自分でリクエストを送信したり、レスポンスを待ったり、状態を管理したりする必要はないのです。
00:57:37ここではその必要がありません。
00:57:42ええ。
00:57:44新しいフレームワークを学ぶとき、どのような思考プロセスをたどりますか?
00:57:48他のフレームワークと比較したりしますか?
00:57:51それとも、全く新しいものとして扱いますか?
00:57:53自動的に、自分がすでに知っているものと常に少し比較してしまいますね。
00:57:57ですが、例えばNext.jsなどとはAdonisはあまりに異なるので、比較しすぎることはありません。
00:58:03最初に立てた主な比較の軸は、これが全く異なる哲学に基づいているということを理解する必要があるという点です。
00:58:10単にルーティングしてコンポーネントをレンダリングするだけでなく、至れり尽くせりのフレームワークなのです。
00:58:18ですから、あまり比較はしていません。
00:58:19かなり新しいものとして捉えています。
00:58:21Laravelについては少し比較しますね。JavaScript版Laravelですから。
00:58:25Bleemさん、素敵なコメントをありがとうございます。
00:58:29コンテンツを気に入ってもらえて嬉しいです。
00:58:32さて。
00:58:34共有型ですね。
00:58:35フロントエンドは、Adonis.jsによって自動生成される共有のTypeScript型に引き続き依存できます。
00:58:40これらは.adonis.jsクライアントディレクトリに保存され、ルートやプロップなどの型定義が含まれているため、TypeScriptを活用できます。
00:58:48スタート。
00:58:49startディレクトリには、アプリケーションの起動ライフサイクル中にインポートしたいファイルが含まれています。
00:58:55例えば、ルートを登録したりイベントリスナーを定義したりするためのファイルは、このディレクトリ内に置くべきです。
00:59:00Adonis.jsはstartからファイルを自動インポートしません。
00:59:03Adonis.jsは単に類似ファイルをグループ化するための慣習として使用されています。
00:59:06なるほど。
00:59:07というわけで、そのstartフォルダーにkernel TSファイルがありますね。
00:59:12ああ、そうですね、もう見ました。
00:59:14そう、そうですね。
00:59:16ここで新しいミドルウェアを登録できるはずです。ガイドの一部としてそれを行う必要があるかどうかは、これから確認していきます。
00:59:24テストフォルダーがあります。
00:59:25データベースのような一時ファイル用のtempフォルダーもあります。
00:59:28Ace.jsはaceコマンドを実行するためのエントリーポイントです。
00:59:33ここにありますか?
00:59:35Ace。
00:59:36Aceですね。
00:59:37はい。
00:59:38このファイルは変更しないでください。
00:59:39わかりました。
00:59:41ええ。
00:59:44プロジェクトマニフェストですか?
00:59:46Lintパッケージを使用します。
00:59:48設定を使用します。
00:59:49わかりました。
00:59:51開発環境の設定。
00:59:54Adonisアプリケーションには、完全に構成された開発環境が付属しています。
00:59:57そう、コードエディターですね。
01:00:01ええ、Edge拡張機能はすでにインストールしましたが、InertiaとReactを使うなら必要ないでしょう。
01:00:09TypeScriptですね。
01:00:10理解している限りでは、すべて設定されているはずです。
01:00:12時間を無駄にしたくはありません。
01:00:14構成と環境ですね。
01:00:18Adonisの構成は3つの明確なシステムに整理されており、それぞれが特定の目的を果たしています。
01:00:23設定ファイルには、configフォルダー内のアプリケーション設定が含まれています。
01:00:28.env内の環境変数には、実行時のシークレットや環境間で変更される値が保持されます。
01:00:33理にかなっていますね。
01:00:34ちなみに、シークレットに関しては、特に昨今のサプライチェーン攻撃を考えると、.envファイルに保存しないことをお勧めします。
01:00:41コースなどではすぐに削除するのでそうするかもしれませんが、とにかく推奨はしません。
01:00:47ですが、継続的に使用するシークレットなら、InPhysicalのようなサービスを使うでしょう。
01:00:53彼らから報酬はもらっていませんよ。
01:00:54Dopplerなどを使ってもいいですね。
01:00:57これらはクラウドサービスです。
01:00:58InPhysicalなら無料で開始できます。
01:01:01ええ。
01:01:02シークレットをクラウドに保存して、CLI経由で取得できます。
01:01:06もしマシンが侵害されても、シークレットは抽出されません。あるいは、抽出されるのが難しくなります。
01:01:14これはただのサイドノートです。
01:01:17Adonis R-CTSファイルはフレームワーク自体を構成します。
01:01:20わかりました。
01:01:20ですから、設定ファイルはアプリケーション用で、そちらはフレームワーク自体用というわけですね。
01:01:26ここで、デフォルトで検索するフォルダー名を変更したりできるのでしょう。
01:01:33構成はconfigディレクトリにあります。
01:01:35典型的なAdonisプロジェクトには複数のconfigファイルが含まれています。
01:01:38それも見ました。
01:01:39これがデータベース設定ファイルの見た目です。
01:01:42メール設定ですね。
01:01:43このconfigファイルがどのように環境変数を参照しているかに注目してください。
01:01:46これが環境変数の正しい使い方です。
01:01:49ええ。
01:01:49理にかなっています。
01:01:50例えば、メールを送信するアプリケーションがある場合、メールの送信方法を構成できます。
01:01:55ですが、一部の値に関しては、設定ファイルにハードコーディングしないように.endファイルに入れています。
01:02:02それは設定の調整のための一般的な構成であり、具体的な値やシークレットについては、それらを環境変数として読み込んでいるのです。
01:02:12設定ファイルはアプリケーションの起動サイクル中に読み込まれます。
01:02:16つまり、Edgeテンプレートは使っておらず、Edgeテンプレートの環境変数ではなく、.envが自動的に読み込まれているのでしょう。
01:02:25App Keyは、Adonis.jsがクッキーの暗号化、セッションの署名、その他の暗号操作に使用する特別な環境変数です。
01:02:35キーを生成してApp Keyを作成しますが、すでに一つ持っています。
01:02:41わかりました、理解しました。
01:02:46デフォルトで問題ないだろうと想定しています。
01:02:49設定ファイルをいじり回して配信時間を無駄にしたくはありません。
01:02:53ではデプロイを続けましょう。
01:02:58ええ、デプロイはしたくありません。
01:03:00FAQを構築して、開発ショーケース、コミュニティショーケースのウェブサイトを完全に機能するものにしたいです。
01:03:11このチュートリアルでは開発ショーを構築します。
01:03:14ええ、それをやりたいです。
01:03:17でも、まずは質問ですね。
01:03:21GitHub ActionsがTanStackのセキュリティ問題の主な原因だと思いますか?それともTanStackのせいですか?
01:03:27厳密に言えばTanStackの過失ですね。私の記憶が正しければ、彼らはこの問題が起きないように構成できたはずですから。
01:03:38ですが、GitHub Actionsのようなシステムが、この特定のエラーを発生させやすくしていたのであれば、それもまた良くはありません。
01:03:50今、言っておきますが、私はCICDの専門家ではありません。
01:03:55何年もの間、あらゆる種類の自動化のためにGitHub Actionsを使ってきました。
01:04:00ですが、5つのチームが絶えず同じリポジトリにプッシュし、多様なエッジケースや複雑なワークフローがあるような大企業で働いているわけではありません。
01:04:12ですからGitHub Actionsには満足しています。
01:04:14ただ、異なる形式で使用しています。
01:04:18すべてが超シンプルというわけではありませんが、これまで見た中で最も洗練されたワークフローというわけでもありません。
01:04:29JavaScriptコースについて聞きたいです。
01:04:3190本以上の動画を見てまだ理解できないというのは間違っていますか?
01:04:33何も理解できていないのであれば、それは良い兆候ではありません。
01:04:38私にとってもそうかもしれませんね。
01:04:39でも、そうやって答えるのは難しいです。
01:04:43ですが、動画を順番に見ているなら、何かがクリックされるはずだと思います。
01:04:51ただ、私はWindowsを使っていて、あなたはAppleを使っていたので難しいところです。
01:04:54でも、それで違いが出るはずです。
01:04:56JavaScriptはJavaScriptですから。
01:04:57そうですね。繰り返しになりますが、理解できないということがJavaScriptの構文を理解できていないということであれば、実際は同じことですよ。
01:05:07ですので、WindowsかAppleかというのは問題ではないはずです。
01:05:10こんにちは、マックス。
01:05:11コミュニティへの多大な貢献に感謝します。
01:05:13こんにちは、温かい言葉をありがとうございます。
01:05:16ReactとAngular、どちらで作業するのが好きですか?それともプロジェクトによりますか?
01:05:20プロジェクトによります。
01:05:21ですが最近は、AIのお気に入りということもあり、主にReactを使っています。
01:05:26そして、良くも悪くも、コーディングにAIを多用しています。
01:05:33AIの前は、強い好みはありませんでした。
01:05:36もし何かを挙げるなら、Vueの構文や使いやすさ、特にVue 2が好きだったかもしれません。
01:05:42しかし、それも遠い昔の話です。
01:05:44だから、どちらでもいいのです。
01:05:46新しいフレームワークの概念を学ぶ上で、何が重要だと思いますか?
01:05:51私にとっては、深く掘り下げることが重要です。
01:05:54裏でどのように動作しているのかを理解したいのです。
01:05:57単に表面的で基本的な答えを得るだけではいけません。
01:06:03物事がどうつながっていて、なぜ特定の方法で物事を行うのか、いつ特定のアプローチを使うべきなのかを理解したいのです。
01:06:10私は物事を疑問視し、少し深掘りするように努力しています。
01:06:16さあ、これを構築しましょう。
01:06:19Adonis.jsハイパーメディアから始めています。
01:06:22Inertiaを使っています。
01:06:23うまくいくか見てみましょう。
01:06:27ええ、ルートはありますね。
01:06:29私の方にもあるはずです。
01:06:34どこにいますか?
01:06:35スタートにいます。
01:06:36ええ、スタートフォルダーのルートですね。
01:06:39はい、ここにもあります。
01:06:40同じように見えますね。
01:06:43スターターキットにはサインアップ、ログイン、ログアウトのルートがあります。
01:06:45ゲストミドルウェアによって、ログインしていないユーザーのみがサインアップやログインにアクセスでき、認証ミドルウェアがログアウトルートを保護していることに注目してください。
01:06:53それはすでに理解しました。
01:06:55コントローラーの仕組みです。
01:06:56サインアップコントローラーを見て、リクエストがどのようにアプリケーションを流れるか確認しましょう。
01:07:07ええ、アプリコントローラーにある新しいアカウントコントローラーを見てみましょう。
01:07:12もちろんEdgeではなくInertiaを使っていますが、それでもね。
01:07:19各コントローラーメソッドは、最初のパラメーターとしてHTTPコンテキストオブジェクトを受け取ります。
01:07:26これですね。
01:07:28コンテキストには、現在のリクエスト、リクエストデータ、レスポンスオブジェクト、オフステート、ビューレンダラーなど、すべてが含まれています。
01:07:34必要なプロパティだけを構造化します。
01:07:39作成メソッドは単にサインアップフォームを表示します。
01:07:42ええ、理解しました。
01:07:44私たちの場合、Inertiaを使っているので、Inertiaというものを受け取っています。
01:07:48他にもいろいろあります。
01:07:50URLなどを調べるためにリクエストを取得することもできます。
01:07:57ですが、ここではビューをレンダリングするためにこのInertiaオブジェクトを使っています。
01:08:01そしてこの投稿ルートでは、リクエスト本文を検証するためにvalidateメソッドを使用するように、リクエストを抽出しているようです。
01:08:12ええ。
01:08:17コントローラーがユーザーモデルとサインアップバリデーターを参照していることにお気づきかもしれません。
01:08:21スターターキットにはすでにそれらが含まれています。
01:08:23後の章で探索します。
01:08:27わかりました。
01:08:30コントローラーがビューレンダラーを呼び出すと、テンプレートファイルを検索してレンダリングします。
01:08:34ええ、それはわかります。
01:08:35ビューはリソースフォルダーにあります。
01:08:38アカウント作成を試しましょう。
01:08:39ええ、もうやりました。
01:08:40コマンドラインとREPLですね。
01:08:42なぜ機能を構築する前にCLIとREPLを取り上げるのか不思議に思うかもしれません。
01:08:46理由はこれです。
01:08:46このチュートリアルを通じて、コントローラー、モデル、その他のファイルを生成するために常にACEコマンドを使用します。
01:08:51今CLIに慣れておくことで、後でフローを中断しなくて済みます。
01:08:54わかりました。
01:08:55利用可能なコマンドはnode ace listで見ることができます。
01:08:59やってみましょう。
01:09:02こんにちは。
01:09:05わかりました。
01:09:06というわけで、実行できる組み込みコマンドがいくつもあります。
01:09:11Adonisパッケージをインストールして構成します。
01:09:14ビルド、イジェクト、シーダーを実行するためのデータベースコマンドなどです。
01:09:19キーの生成。
01:09:21ルートの一覧表示。
01:09:23リスナーを設定したいイベントの作成などですね。
01:09:29あるいは新しいミドルウェアやモデルの作成。
01:09:32わかりました。
01:09:32ええ。
01:09:38REPL。
01:09:39ええ。
01:09:40実は先へ進みます。
01:09:42リスクを恐れません。
01:09:54この章では、投稿とコメントリソースのためのモデルとマイグレーションを作成します。
01:09:59関係性を確立します。
01:10:01ダミーデータを生成する。
01:10:01OK。
01:10:02この章ではAdonisJSのORM、Lucidを紹介します。
01:10:06生のSQLクエリを書く代わりに、モデルと呼ばれるJavaScriptクラスを使ってデータベーステーブルを表現します。
01:10:11まあ、前にも言いましたが。
01:10:14重要な区別です。
01:10:15モデルはデータの操作方法を定義しますが、データベースの構造自体は変更しません。
01:10:20それはマイグレーションの仕事です。
01:10:21ええ。
01:10:21モデルがあります。
01:10:22コード内でモデルを使って
01:10:24データを操作します。
01:10:25でも、そのためにはデータベーステーブルが必要です。
01:10:27それを作成するために「マイグレーション」というものが必要です。
01:10:31これは小さなスクリプトのようなものです。
01:10:33あるいは、必要なテーブルを持つようにデータベースを調整するための設計図とも言えます。
01:10:37そして、そのマイグレーションはモデルから派生します。
01:10:40モデルクラスからですね。
01:10:42Laravelではそう機能します。
01:10:43Adonisでも同じように機能すると理解しています。
01:10:49では、Postモデルを追加しましょう。
01:10:54「node ace make:model post」で。
01:11:01これで「models/post.ts」ファイルが作成されます。
01:11:05そして、新しいマイグレーションファイルも同時に作成されます。
01:11:09さっき言った通り、モデルとマイグレーションの両方が必要だからです。
01:11:11これでPostモデルができました。
01:11:13今は空のクラスです。
01:11:19これはIDEのTypeScriptエラーかもしれません。
01:11:26いや、違いますね。
01:11:27まだ作成されていないからだと思います。
01:11:28マイグレーションを設定していないので。
01:11:33スキーマを。
01:11:34テーブルの形状をまだ設定していませんから。
01:11:41マイグレーションでテーブル構造を定義する必要があります。
01:11:43そうですね。
01:11:43それをする必要があります。
01:11:45コピーしましょう。
01:11:48Postのファイルへ行きます。
01:11:53マイグレーションファイルですね。
01:11:54ベーススキーマ。
01:11:56ええ。
01:11:56これで合っています。
01:11:59最初は、postsという名前のテーブルを基本構成で作成します。
01:12:07IDとタイムスタンプが追加されます。
01:12:10今からこの3行を追加します。
01:12:14これをコピーして。
01:12:16ここに貼り付けます。
01:12:18タイトル、URL、サマリーを投稿に追加します。
01:12:24そうですね。
01:12:25null許容にしない設定にして、値を必須にします。
01:12:28空にしてはいけません。
01:12:30OK。
01:12:31これを実行する必要があります。
01:12:34ええ。
01:12:34upで作成して。
01:12:36downで削除できるようにします。
01:12:39次はコメントモデルを作成します。
01:12:40コメントモデルを作りましょう。
01:12:43そうしましょう。
01:12:45開発サーバーを一度止めます。
01:12:47変更を反映させるには再起動が必要だと思うので。
01:12:51再度、新しいモデルを作成します。
01:12:53コメントモデルです。
01:12:54前と同じように。
01:12:56新しいマイグレーションファイルができました。
01:12:57新しい。
01:13:01どこですか?
01:13:02新しいモデルです。
01:13:03ここですね。
01:13:04そしてマイグレーションファイルも。
01:13:06これも基本のスケルトン。
01:13:09何を追加しますか?
01:13:10コンテンツ用に1行だけのようです。
01:13:13コンテンツですね。
01:13:18OK。
01:13:21これでデータベースにテーブルを追加できます。
01:13:27良さそうです。
01:13:29では確認しましょう。
01:13:31開発サーバーを再起動します。
01:13:35さっきのエラーは消えましたね。
01:13:36マイグレーションを適用したことで型が生成されたのだと思います。
01:13:47ええ。
01:13:48データベースのスキーマTSが更新されました。
01:13:51データベースフォルダのスキーマTSにあります。
01:13:56これは自動で管理されています。
01:13:58Adonisがスキーマを作成してくれました。
01:14:02aceコマンドがですね。
01:14:04回答してくれてありがとうございます、Maxさん。
01:14:11あなたのコースをいくつか購入しました。
01:14:12ソフトウェア開発者としてのキャリアにとても役立ちました。
01:14:16ええ。
01:14:17本当にありがとうございます。
01:14:18コースに参加してくれて、そんな嬉しい言葉をかけてくれてありがとう。
01:14:21コンテンツが役に立ったと聞いて本当に幸せです。
01:14:24あなたのキャリアに少しでも貢献できたなら。
01:14:27本当にありがとうございます。
01:14:31さて、リレーションシップの追加方法を見ていきましょう。
01:14:33コメントと投稿の間に関係を持たせたいですよね。
01:14:37すべての投稿に1つ以上のコメントが付くようにしたいのです。
01:14:44そして、すべてのコメントは1つの投稿に属します。
01:14:47つまり、1対多の関係です。
01:14:54コメントは投稿に属し、投稿はユーザーに属する。
01:14:57ええ、その通り。
01:14:57それも必要です。
01:14:58外部キーのためのマイグレーションを作成しましょう。
01:15:01次のコマンドで既存のテーブルを変更する新しいマイグレーションファイルを作成します。
01:15:04OK、見てみましょう。
01:15:06これは何をするのか?
01:15:09「make:migration add_foreign_keys」
01:15:11これは単なる追加のマイグレーションファイルです。
01:15:13以前はモデルと共にマイグレーションが作成されました。
01:15:16今回はマイグレーションファイルだけを使います。
01:15:22モデルやクラスは必要ないからです。
01:15:25ただ、データベースの設定を微調整してテーブルに新しいカラムを追加するために、マイグレーションが必要です。
01:15:40関係を設定するためのカラムを追加したいのです。SQLデータベースでの関係は、コメントにuser_idやpost_idなどのカラムを追加することで表現されます。
01:15:53コピーします。
01:15:55コピーします。
01:15:56これは投稿への外部キーですね。
01:16:00作成したのはこれでしょうか?
01:16:05外部キーを追加。
01:16:11ちょっと待ってください。
01:16:22お、今します。
01:16:23実行していなかった?
01:16:25いや、これだ。
01:16:28ファイル名が違うだけですね。
01:16:31まあ、大丈夫です。
01:16:34貼り付けます。
01:16:35何をしていますか?
01:16:37投稿テーブルに、integerでunsignedのuser_idカラムを追加します。正の数専用ですね。
01:16:45nullにはできません。
01:16:45外部キー関係を設定します。
01:16:48ユーザーが削除されたら、投稿も削除されます。
01:16:51コメントについても同様に、ユーザーだけでなく投稿にもリンクさせます。
01:16:58そしてdownマイグレーションで元に戻せます。
01:17:01OK。
01:17:03実行します。
01:17:07実行します。
01:17:11開発サーバー起動。
01:17:13Postモデルで関係を定義します。
01:17:15データベースに外部キーができたので、モデルを更新して関係を定義します。
01:17:20コピーします。
01:17:22Postモデルに行って貼り付けます。
01:17:27クラス内に、コメントプロパティを追加します。値はありませんが、デコレータを使います。
01:17:43Adonisが提供するデコレータで、投稿は多くのコメントを持ち、ユーザーに属すると記述します。
01:17:57Laravelと同じような表現ですね。
01:18:02読みやすくて理解しやすいです。
01:18:05プロパティを宣言するだけというのは少し奇妙に感じるかもしれません。
01:18:11初期値がないとTypeScriptの問題が出るので「declare」を使います。
01:18:18これがあれば大丈夫。
01:18:20そういうことです。
01:18:22コメントモデルにも関係性が必要です。
01:18:26貼り付けましょう。
01:18:28コメントは投稿に属し、ユーザーに属します。
01:18:31どの視点から見るかでhasやbelongが変わります。
01:18:36両方設定します。
01:18:39OK。
01:18:40これで完了です。
01:18:41ユーザーモデルへの逆のhasManyは追加していません。このチュートリアルでは不要ですから。
01:18:46必要になれば後から追加できます。
01:18:51OK。
01:18:52このチュートリアルではユーザーの投稿を探すことはなさそうです。
01:18:58ユーザーの全投稿をクエリしたいなら、設定が必要になりますが。
01:19:04ここでは全投稿をクエリして、それぞれの投稿がどのユーザーのものかを表示するだけです。
01:19:16AngularとNestの子供みたいなフレームワークですね。
01:19:20巨大で複雑なフレームワークは今でも重要なんですね。
01:19:24機能が統合されているので、理論的には素晴らしいと思います。
01:19:30最初は圧倒されるかもしれません。
01:19:33ですが、自分で追加するものがあまりないのが大きな利点です。
01:19:39多くのアプリケーションでは、そのまま動くはずです。
01:19:48Next.jsやTanStackは好きですが、Adonis.jsは使ったことがありません。
01:19:54素晴らしいから使ってと言えるほどではないですが。
01:19:56自分で使ったことがないので。
01:19:58Next.jsやAngularなどでは、認証やデータベース用に外部ライブラリを自分で追加する必要があります。
01:20:07PrismaなどのORMも必要になるかもしれません。
01:20:14ライブラリを繋ぎ合わせるのは、サプライチェーン攻撃のリスクもあり厄介です。
01:20:21メンテナンスも大変ですし。
01:20:23理論的には、これが素晴らしいはずです。
01:20:26AIなしでコーディングしていて、懐かしい気分になります。
01:20:30ああ、そうですね。
01:20:31懐かしい感じがあります。
01:20:33AIを使わないのは、何が起きているのかを理解したいからです。
01:20:38新しいことを学ぶときには重要だと思います。
01:20:42もしAIが全部やってしまったら、ライブストリームも面白くないでしょう。
01:20:47それに、AI任せのコードにも限界があります。
01:20:52モデルとデータベースの準備ができたので、開発やテストのためにダミーデータを入れます。
01:20:57ファクトリーはリアルな偽データを作成するための設計図として機能します。
01:21:03一度定義するだけです。
01:21:04OK。
01:21:05投稿ファクトリーを作って、偽の投稿を生成しましょう。
01:21:10「make:factory」コマンドを実行します。
01:21:14投稿をどうやって生成するかを定義するファイルが作成されます。
01:21:21コピーして見てみましょう。
01:21:25偽の投稿を生成します。
01:21:30fakerツールが選べるタイトルリストを持たせます。
01:21:37適当なURLとダミーのLorem Ipsum段落を追加します。
01:21:45プログラミング的にデータを追加する方法ですね。
01:21:48最近ならAIも使えますが。
01:21:51トークンを使わない安上がりな昔ながらの方法でいきましょう。
01:21:56コメントファクトリーも作成します。
01:22:02こちらです。
01:22:03ここにコードをコピーしましょう。
01:22:06ここではダミーのロレムイプサム段落を出力します。
01:22:11次にシーダーが必要です。
01:22:12これで偽データを生成できるファクトリーができました。
01:22:15でも、その偽データをどうすればいいでしょう?
01:22:17データベースに入れたいですね。
01:22:19そこでシーダーの出番です。
01:22:23作成しましょう。
01:22:24これらは一般的な概念です。
01:22:26ファクトリーとシーダー。
01:22:27Adonisに限った話ではありません。
01:22:28Laravelでも使われています。
01:22:29あるいは、どんな構成でもこうした概念は使えます。
01:22:37Next.jsアプリケーションでも、データベースに初期データを投入したい場合がありますよね。
01:22:41もちろん、node aceコマンドはAdonis特有のものです。
01:22:45では、シーダーを作成します。
01:22:47投稿シーダーを見てみましょう。
01:22:49これはデータベースに初期データを投入するために実行できるファイルです。
01:22:54そのために、何をするか定義する必要があります。
01:22:57ここでやりたいのは、ダミーの投稿とコメントを作成して関連付け、データベースに保存するような処理だと思います。
01:23:07Adonisではどうなるか見てみましょう。
01:23:10貼り付けて見てみます。
01:23:13find or fail を使っています。
01:23:17ユーザーを探そうとしています。
01:23:19失敗するはずです。
01:23:21作成するという記述がないし、そのユーザーはまだいないからです。
01:23:25そこでユーザーを探しにいきます。
01:23:26作成しなければなりませんね。
01:23:28そしてこのユーザーをマージします。
01:23:33そして多数の新しい投稿を作成し、このコマンドでそのユーザーに関連付けます。
01:23:37さらに各投稿に対してダミーコメントを作成し、それらもその投稿とユーザーに関連付けます。
01:23:46コメント数はランダムで、プラス3つです。
01:23:51つまり各投稿につき最低3つ、最大で合計6つのコメントを作成します。
01:24:023から6つのコメントということですね。
01:24:06まず、このメールアドレスでユーザーを取得します。
01:24:09これは前章で作成したユーザーです。
01:24:12自分でユーザーを作成します。
01:24:15さっとやってしまいましょう。
01:24:19サーバーを起動します。
01:24:23いや、まだシーダーを実行していませんでしたね。
01:24:26それはうまくいくはずです。
01:24:27でも、これは違いますね。
01:24:28手早くサインアップします。
01:24:34そうそう。
01:24:36いや、これじゃない。
01:24:37よし。
01:24:39これを使います。
01:24:44よし。
01:24:45別のメールアドレスを使います。
01:24:47もちろんこれです。
01:24:50test@example.com
01:24:52よし。
01:24:53これでいけます。
01:25:02はい、続けてください。
01:25:03このストリーム。
01:25:03気に入っています。
01:25:04ええ、絶対に続けていくつもりです。
01:25:06ちなみに、毎週木曜日にこのようなストリームを配信する予定です。
01:25:13来週はちょっとできないのですが。
01:25:16他の予定が入っていて。
01:25:18でも基本的には、毎週木曜日のこの時間、中央ヨーロッパ夏時間で午後5時から配信する予定です。
01:25:26個人的には、Anthropicは自社のツールをかなり推し進めたいのだと感じます。
01:25:40Claude Codeだけを普及させたいようです。
01:25:42ユーザーを囲い込みたいのでしょう。
01:25:43まあ、どうなるか見てみましょう。
01:25:45Claudeを他のあらゆるツールで自由に使えるようになるとはあまり思えません。
01:25:51少なくともサブスクリプションでトークン料金を払う形では難しいでしょう。
01:25:55APIを使えば可能でしょうけどね。
01:25:58もちろん、それだと非常に高額になりますが。
01:26:02では、シーダーを実行します。
01:26:06サーバーを停止します。
01:26:09実行します。
01:26:10これでダミーデータが作成されました。
01:26:12アプリの準備ができていなくても、データは確認できるはずです。
01:26:17データベース上で、投稿テーブルとコメントテーブルが確認できます。
01:26:21ユーザーテーブルには私のユーザーがあります。
01:26:23そして投稿テーブルには、ダミーの投稿が入っています。
01:26:27コメントテーブルにも、ダミーコメントが入っています。
01:26:33各コメントは、特定のユーザーと投稿IDに関連付けられています。
01:26:36当然、ユーザーは一人しかいません。
01:26:38なので、すべてその一人のユーザーに紐付いています。
01:26:40シーダーにそう書きましたからね。
01:26:41そして投稿については、5つのコメントが付いた投稿がここにあります。
01:26:47こちらは3つのコメントですね。
01:26:50コードの内容通りです。
01:26:52よし。
01:26:53何をしたか理解できました。
01:26:55REPLでデータをクエリしても同じことですね。
01:26:57すでにデータがあるのは確認済みです。
01:27:00まあ、でも。
01:27:01コードを見てみましょう。
01:27:02面白いのは、モデルベースのアプローチだと、SQLクエリを直接書く必要がないという点です。
01:27:10その代わりに、モデルを使うか、すべてのモデルにアクセスするだけです。
01:27:17そのモデル名で登録したので、モデルが使えます。
01:27:20そして、すべての投稿を取得するにはallのようなメソッドが使えます。
01:27:24あるいは、ここで見られるように、where句を使って投稿数を制限するクエリを書くこともできます。
01:27:30これがORMの仕組みです。
01:27:32SQL文を書かずに、プログラムでデータをクエリできるのです。
01:27:37正直に言うと、私はORMの大ファンではありません。反対というわけではないのですが、普段は使っていません。
01:27:46特に今はAIがあるので、生のSQLクエリを書くのがこれまでになく簡単です。
01:27:52なので、私は普段のアプリケーションでは生のSQLクエリを使っています。
01:27:58ORMは使いません。
01:28:00生のクエリを書けば、もちろん最大限の力が発揮できますからね。
01:28:06それにAIが登場する前でも、多くのクエリはそれほど難しいものではありませんでした。
01:28:10JOINを含めても、大したことありません。
01:28:13もちろん、SQLクエリはかなり複雑になることもあり、AIが間違えることもあります。
01:28:18ですが私の経験では、かなり複雑なものを含め、ほとんどのクエリで優秀です。
01:28:22まあ、これは私の個人的な意見です。
01:28:24ですが、ここではORMを使っているので、それに合わせます。
01:28:29ルート、コントローラー、そしてビュー。
01:28:32前章で、投稿とコメントのモデルを、データベーステーブルとリレーションとともに作成しました。
01:28:37今回は、ユーザーが投稿を実際に閲覧できるページを構築することで、それらのモデルに命を吹き込みます。
01:28:46今のところ投稿とコメントはデータベースにしか存在しません。
01:28:49サーバーはすでに立ち上がっています。
01:28:52では、新しいコントローラーを作成しましょう。
01:28:54このフレームワークの考え方として、ルートがあり、コントローラーがあり、ビューがあるという構成です。
01:29:02つまり、昔ながらのMVCですね。
01:29:07モデル・ビュー・コントローラー。
01:29:09ウェブアプリに限らず、アプリケーションを構築するかなり古い手法です。
01:29:18でも、古いからといって悪いわけではありません。念のため。
01:29:24ただ、最近のNext.jsアプリケーションなんかではあまり見かけない気がしますね。
01:29:30まあ、そうですね。
01:29:31別のタブで、新しい投稿コントローラーを作成しましょう。
01:29:38これが空のファイルです。ここにメソッドを登録し、4つの異なるルートで何が起こるかを定義します。
01:29:44時間を節約するため、また貼り付けます。
01:29:47ここにあるのはindexメソッドです。
01:29:52ここでHTTPコンテキストを取得します。あらゆるデータが入っているあのオブジェクトです。
01:29:57そして、実はこれを修正する必要があります。Inertiaを使う必要があるからです。
01:30:05Inertiaを使わなければなりません。もちろん、このコンポーネントも追加する必要があります。
01:30:09でも、ここでやっているのは、以前定義したモデルファイルからのPostクラスの使用ですね。
01:30:16先ほど定義したPostクラスです。
01:30:20そしてこれがORMの動きです。クエリを作成しています。
01:30:24ユーザーのプリロードはおそらくそこにあります。投稿を取得するたびに何度も読み込まないように一度で済ませるためでしょう。
01:30:32そして投稿を作成日順に、降順で並べ替えます。
01:30:38つまり最新の投稿が最初に来ます。
01:30:45あとはレンダリングするだけですが、これを追加する必要があります。
01:30:53ルートを定義します。
01:30:56ルートへ行くには、start routesに行きます。
01:31:03そしてここに追加しました。
01:31:07どこに追加してもいいのですが。
01:31:10なぜうまく動かないのでしょう?
01:31:12なぜ動かないのか。
01:31:13開発サーバーを再起動する必要があるのでしょうか?
01:31:16おっと、これは間違っています。
01:31:18ああ、開発サーバーを起動していませんでした。
01:31:21私のミスです。
01:31:22では、起動してみましょう。うまくいくといいのですが。
01:31:25自動作成されました。
01:31:26つまりAdonisが型定義を動的に作成しているのです。
01:31:31これで完了です。
01:31:34Adonisに対して、GETリクエストが/postsに来たら、と伝えます。
01:31:40postsコントローラーのindexメソッドをトリガーしたいのです。
01:31:43もちろん、それがこのメソッドです。
01:31:47あとはビューが必要です。
01:31:50新しいビューを作成します。
01:31:53Inertiaビューを作るコマンドが正しいのかわかりません。
01:31:56見てみましょう。
01:31:59node ace listを実行して、何が作れるか確認できます。
01:32:04ビューは作成できますが、あれはedge.jsテンプレートファイルです。
01:32:08そうじゃないんです。
01:32:11手動で作るしかなさそうですね。
01:32:20手動で作成しますが、そう難しくはないはずです。
01:32:24inertia pagesに行きましょう。
01:32:29そこにpostsを追加します。
01:32:31そしてそこにindex.jsファイルを追加しますよね。
01:32:34そしてデフォルトのエクスポート関数を書きます。
01:32:38名前はpostsにしましょう。
01:32:41マイ・ポストといった内容にします。
01:32:44ただのReactコンポーネントです。
01:32:50これでエラーは消えました。
01:32:51だって、あれを追加しましたから。
01:32:55postsフォルダーにindex.jsファイルを追加したのです。
01:32:58まさにここで言った通りです。
01:32:59こうやってリンクされるわけですね。
01:33:02そして今のところ、開発サーバーが起動しているので、
01:33:05/postsに行けば、投稿を確認できます。
01:33:09これで動いています。
01:33:10あとはコントローラーからコンポーネントにデータを渡すだけです。
01:33:20実際、すでにpropsとして渡していると思います。
01:33:23問題は、ここでそれを受け取れるかですね。
01:33:30さて、どうすれば…
01:33:33ああ、childrenを使わないといけないのかな。
01:33:36他のファイルではどうなっていますか?
01:33:40データを送信しているファイルはありますか?
01:33:45ありません。
01:33:46ありません、ありません、ありません。
01:33:50レイアウトでは?
01:33:52children。
01:33:54これが必要なんだろうな。
01:33:58でも、やったことがない。
01:34:00何とかしてみましょう。
01:34:19ここにありませんか?
01:34:23ああ、そうか、私のミスです。
01:34:25もちろん、これはTypeScriptとして正しくありません。
01:34:27こうすべきですね。
01:34:30よし。
01:34:30インポートを追加します。
01:34:36インポート。
01:34:38正しいはずです。
01:34:40ここにありますか?
01:34:41データ、生成されたデータ。
01:34:42そう。
01:34:43OK。
01:34:45OK。
01:34:45さて、見てみよう。
01:34:46ここにフラグメントを追加できるかな?
01:34:50そして、何かこんな感じのことを。
01:34:54Children。
01:34:57Props。
01:34:59うーん。
01:35:02User。
01:35:03ああ、共有プロップスじゃないかもしれないな。
01:35:04どうやって取得すればいいんだ?
01:35:06たぶん、中を調べてみる必要があるな。
01:35:10見てみよう。
01:35:11Inertiaのドキュメントを調べる必要があるな。
01:35:15ガイド。
01:35:17Inertiaはどこだ?
01:35:19どうやってコンポーネントにプロップスを渡すんだ?
01:35:24必要なのは。
01:35:25トランスフォーマーが必要かな?
01:35:29モデルインスタンスをプレーンなオブジェクトにシリアライズするためにトランスフォーマーを使う。
01:35:33なるほど。
01:35:34なるほど。
01:35:35なるほど。
01:35:37よし。
01:35:37よし、ここで少しずるをしよう。
01:35:40AIの力を借りるぞ。
01:35:44ええと。
01:35:48Adonis JSアプリを構築中だ。
01:35:51投稿を取得する必要がある。
01:35:53投稿を取得する必要がある。
01:35:56見て。
01:35:57投稿コントローラー。
01:36:02自分のInertia投稿に。
01:36:04おっと。
01:36:05これが君にとって読みにくいのがわかるよ。
01:36:10OK。
01:36:10OK。
01:36:10ちょっと待って。
01:36:18OK。
01:36:18Adonis JSアプリを構築中だ。
01:36:20アプリ。
01:36:21投稿を取得する必要がある。
01:36:24投稿コントローラーから。
01:36:27追加。
01:36:28おっと。
01:36:28投稿を追加。
01:36:30コントローラー。
01:36:32投稿の中に。
01:36:35ビュー。
01:36:35Inertia。
01:36:37ビュー。
01:36:39というわけで、ここが投稿フォルダーのindexだ。
01:36:45これらのページにリンクするよ。
01:36:48確認してくれ。
01:36:50そして。
01:36:56それを手伝ってもらう。
01:36:59それができるか見てみよう。
01:37:03ええと。
01:37:03ORMはスキーマ変換や共同作業には便利だ。
01:37:07うーん。
01:37:08ああ。
01:37:09繰り返しになるけど。
01:37:09私は言わない。
01:37:10ORMが悪いとは。
01:37:11ただ。
01:37:11私のプロジェクトに個人的に必要ないだけだ。
01:37:14でも繰り返しになるけど。
01:37:14大規模なチームで働いているわけじゃないからね。
01:37:18うーん。
01:37:18私は。
01:37:19確かに。
01:37:20言っておくけど。
01:37:21マイグレーションは使っているよ。
01:37:23だから。
01:37:23別に。
01:37:24使わないという。
01:37:25わけじゃない。
01:37:26そんな感じの何かじゃない。
01:37:27うーん。
01:37:28ただ。
01:37:29自分で書いているんだ。
01:37:30あるいは。
01:37:31LLMに書かせている。
01:37:32だからマイグレーションはすごく便利だ。
01:37:34ただORMの部分は必要ないだけだ。
01:37:36聞こうと思っていたんだ。
01:37:36ワイプコーディングについて。
01:37:37良いかどうか。
01:37:38私は思わない。
01:37:39ワイプコーディングが。
01:37:40ワイプコーディングが。
01:37:41良いとは。
01:37:42真剣な何かに。
01:37:43でも。
01:37:44ワイプコーディングは。
01:37:44間違いなくすごく良い。
01:37:45もし単に必要なら。
01:37:46クイックな。
01:37:47ユーティリティツール。
01:37:48あるいは単に必要があるなら。
01:37:48仕事を終わらせるために。
01:37:50そう。
01:37:50ソフトウェアを構築していて。
01:37:51売るつもりなら。
01:37:52もし。
01:37:53何か真剣なことに取り組んでいるなら。
01:37:55流通させる計画があるなら。
01:37:56あるいは仕事で。
01:37:57ワイプコーディングは。
01:37:58すべてを失わせる。
01:37:59追跡を。
01:38:00理解していない。
01:38:01コードベースで何が起きているかを。
01:38:02そして最終的に。
01:38:03壁にぶつかる。
01:38:04そしてわからないだろう。
01:38:04どうやって続ければいいか。
01:38:06だから。
01:38:07コードを気にしないことは。
01:38:08良い解決策じゃない。
01:38:09そういう。
01:38:09状況には。
01:38:11でも繰り返しになるけど。
01:38:11もし単に必要なら。
01:38:13ええと。
01:38:13クイックな。
01:38:15ツール。
01:38:16自分のマシンで動かすとか。
01:38:17あるいはそんな感じの何かなら。
01:38:18気にしないかもしれない。
01:38:19ええと。
01:38:20すべてを。
01:38:21詳細を。
01:38:23などなど。
01:38:24そう、だから。
01:38:25ワイプコーディングは良いかもしれない。
01:38:26そしてそう。
01:38:26ライブコーディングは常に。
01:38:28常に挑戦的だ。
01:38:29でもAIが解決できるか見てみよう。
01:38:31ここでリンティングエラーと戦っているようだ。
01:38:36でもそう。
01:38:38私はただAIを使っている。
01:38:40ちなみに。
01:38:40普段なら自分でやるんだけど。
01:38:41自分で構築して。
01:38:44でも20分後には出かけなきゃいけないんだ。
01:38:47完成したコードを今手に入れたい。
01:38:49それに取り組むために。
01:38:51そして今。
01:38:52その後もここで続けられるように。
01:38:54それが主な理由だ。
01:38:56よし。
01:38:56今ここで何かした。
01:38:58まずは動くか確認しよう。
01:39:00説明し始める前に。
01:39:02そして何をしたか見てみよう。
01:39:04良さそうだ。
01:39:05スタイリングはひどい。
01:39:07でもわかるように。
01:39:10投稿がレンダリングされている。
01:39:12そしてユーザーにリンクしているのがわかる。
01:39:16だから。
01:39:17コントローラーからデータを送信する。
01:39:19うまくいくみたいだ。
01:39:19どう動くか見てみよう。
01:39:20どうやって動くのか。
01:39:22繰り返しだけど。
01:39:22公式ドキュメントへのリンクを渡した。
01:39:24だから単に。
01:39:28それが単に。
01:39:31ドキュメントが教えてくれることだ。
01:39:34投稿コントローラーで。
01:39:36投稿を取得している。
01:39:38ここで変わったのは。
01:39:39本質的には。
01:39:40私たちが。
01:39:41投稿を渡すということ。
01:39:42でも生のままでなく。
01:39:43その代わりに。
01:39:44投稿トランスフォーマーの助けを借りて。
01:39:45それが新しく追加されたものだ。
01:39:47このファイルは新しい。
01:39:48投稿トランスフォーマー。
01:39:50それはクラスだ。
01:39:51ベーストランスフォーマーを拡張する。
01:39:53OK。
01:39:53その中に。
01:39:54説明するんだ。
01:39:55投稿をシリアライズする方法を。
01:39:56だから言っている。
01:39:57ねえ。
01:39:58これら全てのプロパティを選択して
01:40:01そして。
01:40:02ユーザーのために。
01:40:03ユーザーも変換して。
01:40:04本質的には。
01:40:05今回の場合。
01:40:06変換処理はとても単純なはずです。
01:40:08おそらく必要なのは
01:40:11ISO形式の
01:40:12日付くらいでしょう。
01:40:13その他。
01:40:14生のデータは
01:40:15詰め込むことができます。
01:40:16JavaScriptオブジェクトに。
01:40:17こんなふうに。
01:40:18つまり、基本的には
01:40:19定義するんです。
01:40:20どう変換するかを。
01:40:21クラスをですね。
01:40:21中にはいろいろ含まれていて
01:40:23簡単には変換できないものも
01:40:25JSONへ。
01:40:26それをどう変換するか。
01:40:27JSONにするか。
01:40:28それが
01:40:28トランスフォーマーの役割です。
01:40:30私の理解では。
01:40:33はい。
01:40:33そこで投稿を設定します。
01:40:34そして今度は
01:40:35ビューで。
01:40:40ビューの中で。
01:40:41ページを取得します。
01:40:42はい。
01:40:43設定するだけです。
01:40:43ページプロップスをこんなふうに。
01:40:44はい。
01:40:45設定するんです。
01:40:46プロップスの型を。
01:40:47TypeScriptの型を。
01:40:48Inertiaのプロップスを使って。
01:40:51その代わりに。
01:40:51生成された型をいくつか。
01:40:54あるいは。
01:40:55AIが。
01:40:56それを追加する。
01:40:57そうですね。
01:40:58標準的な型を。
01:40:58いくつか。
01:41:00そう。
01:41:00AIが生成したものではなく。
01:41:02そして。
01:41:02こう言います。
01:41:03いいですか。
01:41:03ええ。
01:41:04ここに。
01:41:04投稿キーを持たせます。
01:41:06そして。
01:41:06それは。
01:41:07型を持つ。
01:41:08そう。
01:41:08つまり。
01:41:09自動生成された
01:41:10型ですね。
01:41:10私たちの。
01:41:11投稿に対する。
01:41:12そして思います。
01:41:13この型は
01:41:14生成されるのだと。
01:41:15私たちがどう
01:41:15変換するかによって。
01:41:16投稿を。
01:41:17ここの投稿。
01:41:20この部分は
01:41:23そう。
01:41:24投稿トランスフォーマーから来ています。
01:41:25その通り。
01:41:27はい。
01:41:28そしてそれを
01:41:29ここで描画できます。
01:41:30難しくはありません。
01:41:32わかりました。
01:41:35はい。
01:41:36繰り返しますが。
01:41:36公式のチュートリアルでは
01:41:38Edgeビューを使っています。
01:41:39そこで。
01:41:39私はInertiaを使っています。
01:41:40そして。
01:41:41ご覧の通り。
01:41:41結局はReactアプリです。
01:41:43最後は。
01:41:44そこでもまた
01:41:46変換して。
01:41:46送信します。
01:41:48プロップスを。
01:41:50はい。
01:41:53単一の投稿を表示する。
01:41:54はい。
01:41:55もちろん。
01:41:55では今。
01:41:55追加できます。
01:41:56もう一つ。
01:41:56メソッドを。
01:41:58コントローラーに。
01:42:00なぜなら
01:42:00投稿コントローラーには
01:42:01現時点では
01:42:02一つの
01:42:02インデックス
01:42:03メソッドしかないからです。
01:42:03すべての投稿を
01:42:04表示するための。
01:42:05でも今は
01:42:05メソッドを
01:42:05追加したいのです。
01:42:06単一の
01:42:07投稿を表示するための。
01:42:08だから
01:42:08showメソッドを
01:42:08追加します。
01:42:09ここで。
01:42:09のようです。
01:42:10名前は
01:42:10自由です。
01:42:10後で。
01:42:11ルートファイルで
01:42:11接続する際には
01:42:12一致するように
01:42:12注意してください。
01:42:12すぐに見ることに
01:42:13なりますが。
01:42:14ここで
01:42:14パラメーターを取得しています。
01:42:16動的なルートがあるからです。
01:42:16Reactなどで
01:42:17ご存知かもしれませんが。
01:42:18ルートには
01:42:18コロンが付いた
01:42:19パラメーターとか。
01:42:19あるいはファイル名に
01:42:19ドル記号があるものですね。
01:42:20例えば。
01:42:20ここで。
01:42:21動的パラメーターを
01:42:21取得します。
01:42:23これらルートの登録方法は
01:42:23すぐに確認します。
01:42:24そして期待するのは
01:42:25IDパラメーターがあることです。
01:42:25つまり
01:42:26特定のIDを持つ
01:42:26投稿を探しています。
01:42:26見つからなければ
01:42:27失敗させたい。
01:42:28404エラーを表示するために。
01:42:28あるいは
01:42:28他のエラーでも。
01:42:29思うに。
01:42:29ビューではなく
01:42:30描画したいですね。
01:42:30代わりに。
01:42:31描画したいのです。
01:42:31Inertiaを取得して。
01:42:32再利用します。
01:42:32投稿トランスフォーマーを。
01:42:33渡すために。
01:42:33投稿を。
01:42:34ええ。
01:42:34その通り。
01:42:35そうですね。
01:42:35ではまた。
01:42:35公式チュートリアルでは
01:42:36Edgeビューを使っています。
01:42:37Inertiaを使っています。
01:42:38そして。
01:42:38ご覧の通り。
01:42:39結局はReactアプリです。
01:42:39最後は。
01:42:40そこでもまた
01:42:40変換して。
01:42:41送信します。
01:42:42プロップスを。
01:42:43はい。
01:42:43単一の投稿を表示する。
01:42:44はい。
01:42:44もちろん。
01:42:45では今。
01:42:46メソッドを
01:42:46追加できます。
01:42:46もう一つ。
01:42:47コントローラーに。
01:42:48なぜなら
01:42:49投稿コントローラーには
01:42:49現時点では
01:42:50一つの
01:42:50インデックス
01:42:51メソッドしかないからです。
01:42:52404エラーを表示する
01:42:53表示するための。
01:42:54でも今は
01:42:55メソッドを
01:42:55追加したいのです。
01:42:57単一の
01:42:58投稿を表示するための。
01:42:58だから
01:42:59レンダリングしたい。
01:43:05そうですね。
01:43:05ここで
01:43:06Inertiaを使います。
01:43:09そして再利用します。
01:43:10投稿の
01:43:11トランスフォーマーを使って
01:43:12渡します。
01:43:13投稿を
01:43:14その
01:43:17表示用コンポーネントに
01:43:18ですね。
01:43:18例えば。
01:43:19では
01:43:20
01:43:20Inertiaの
01:43:21フォルダー
01:43:21投稿の
01:43:22フォルダー内に
01:43:22必要です。
01:43:23作成するのが
01:43:23show
01:43:24.tsxか
01:43:24あるいは
01:43:25detail
01:43:26.tsx
01:43:26
01:43:26何か
01:43:27そんな感じのものですね。
01:43:28そして
01:43:29
01:43:29その中に
01:43:31あります。
01:43:35投稿
01:43:35投稿の
01:43:35コンポーネントが
01:43:36ここに。
01:43:36実際は
01:43:38名前を付けましょう。
01:43:40Postで。
01:43:42Post
01:43:45Post
01:43:47こんな風に。
01:43:48そして
01:43:49前と同じように
01:43:50素早く
01:43:50コピーして
01:43:51持ってきます。
01:43:55手に入ります。
01:43:55単一の投稿が
01:43:56ここに。
01:43:56配列ではなく。
01:44:00これを選択して
01:44:01そうすれば
01:44:01返すことができます。
01:44:02はい。
01:44:05確かに。
01:44:05投稿の
01:44:06タイトルを
01:44:06こんな風に。
01:44:07ハロー。
01:44:11ええ
01:44:12こうして
01:44:12分かりました。
01:44:13ここでは何をしていますか?
01:44:16ですから
01:44:17そしてもちろん
01:44:19同じように
01:44:19投稿の
01:44:19概要も
01:44:20例えば。
01:44:21よし。
01:44:21これでうまくいくはずです。
01:44:21
01:44:22登録する必要があります。
01:44:23Routesフォルダーに。
01:44:23これで新しく追加できます。
01:44:24おっと。
01:44:25GETルートを
01:44:26スラッシュ
01:44:27posts。
01:44:28そして
01:44:30こうやって動的ルートを登録するのだと思います。
01:44:30見てみましょう。
01:44:31はい
01:44:32コロンIDで。
01:44:33よくあるパターンですね。
01:44:34そして今
01:44:35コントローラーで
01:44:35興味があるのは
01:44:36showメソッドです。
01:44:37なぜなら
01:44:38そのコントローラーで
01:44:39このメソッドを
01:44:41showと名付けたからです。
01:44:42もし別の名前にしたなら
01:44:44こちらでも別の名前にしなければなりません。
01:44:45でも今はshowを使っているので
01:44:46うまくいくはずです。
01:44:46では
01:44:47どのリンクがありますか?
01:44:48ああ
01:44:49詳細へのリンクではありませんね。
01:44:51でももしposts/1を追加すれば
01:44:52読み込まれます。
01:44:53スタイルはめちゃくちゃですが
01:44:54一番下に
01:44:54コンテンツが見えます。
01:44:56こちらも別の名前にする必要があります
01:44:58ですが私はshowという名前を使っているので
01:44:59ここにあります。
01:45:02完全にスタイルが崩れていますが
01:45:05機能はしています。
01:45:08ルートは確認できました。
01:45:08もちろんスタイルは修正できますが
01:45:10今はそこが一番重要ではありません。
01:45:13はい
01:45:14ビューを取得できました。
01:45:15すでに全て揃っています。
01:45:16名前付きルートを使って。
01:45:17それは興味深いです。
01:45:18今のところ
01:45:19URLをハードコードしています。
01:45:20そして実際
01:45:21リンクを全く設定していません。
01:45:22なので
01:45:24ルート定義でコントローラーを使う時
01:45:25Adonis.jsは自動的にルート名を生成します。
01:45:26コントローラー名と
01:45:27メソッド名に基づいて。
01:45:28もしcontrollers.posts.indexがあれば
01:45:31それは
01:45:32自動的にposts.indexという名前になります。
01:45:35ですから、行けるはずです。
01:45:36Postsのインデックスページに。
01:45:37投稿が全てある場所ですね。
01:45:39そしてこのようなアンカータグを使う代わりに
01:45:40リンクコンポーネントを使えます。
01:45:40Inertia.js Reactから来る
01:45:41ここにもあります。
01:45:44そして
01:45:47確信が持てませんが
01:45:49ルート定義でコントローラーを使うと、
01:45:51Adonis.jsが自動的にルート名を生成します。
01:45:54コントローラーとメソッド名に基づいてね。
01:45:56そしてこのように書けるはずです。
01:45:58routes
01:45:59posts.show。
01:46:02こう書くと動作しないようです。
01:46:05投稿がすべて表示されるインデックスページへ移動して
01:46:08アンカータグをそのまま使う代わりに
01:46:11別のアプローチを試しています。
01:46:12このリンクコンポーネントを使いたいのです。
01:46:13もう一度。
01:46:17どこかにありましたか?
01:46:18リンクルート。
01:46:19ああ、分かりました。
01:46:21単純な
01:46:21ことでした。
01:46:23分かりました。
01:46:26Linkです。
01:46:29Route。
01:46:34なぜrouteでエラーが出るのでしょう?
01:46:42リンクの作成
01:46:49リンクコンポーネントはナビゲーションリンクを作成します。
01:46:49ああ
01:46:50インポートが間違っています。
01:46:53インポートする必要があります。
01:46:55ここから。
01:46:57Adonisパッケージから。
01:46:59これでルートのサポートができました。
01:46:59これでpostsだけになります。
01:47:01単なる文字列ですね。
01:47:02単なる文字列です。
01:47:04分かりました。
01:47:08ですから
01:47:11Route。
01:47:12よし。
01:47:14これで入力補完が効くようになりました。
01:47:15そしてパラメーターを設定する必要があります。
01:47:16ここからインポートする必要があります。
01:47:20ここです。
01:47:20Adonisパッケージからですね。
01:47:22これでルートが使えるようになりました。
01:47:24今は「posts」になっています。
01:47:33ただの文字列ですね。
01:47:34ただの文字列です。
01:47:35なるほど。
01:47:35つまり、これ。
01:47:37ルート。
01:47:38OK。
01:47:38これで自動補完が効きます。
01:47:40次はパラメータを設定します。
01:47:43ルートパラメータ。
01:47:45postsのid。
01:47:48いや。
01:47:49postのidですね。
01:47:53ということは、オブジェクトにする必要があります。
01:47:57idをpostのidに設定して。
01:48:00これで投稿ごとに動的なルートが生成されるはずです。
01:48:03そして、その動的なプレースホルダーに投稿IDが挿入されるはずです。
01:48:07では、ここでリロードしてみます。
01:48:09ここではありません。
01:48:10こちらです。
01:48:14なぜ更新されないのでしょう?
01:48:16開発サーバーを再起動する必要があるのでしょうか?
01:48:20ああ。
01:48:21ファイルを保存することも必要ですね。
01:48:24そうですね。
01:48:24これでクリックして投稿に移動できるようになりました。
01:48:28もちろん、スタイリングはひどいものですが。
01:48:30でも、機能はしています。
01:48:33そしてもちろん。
01:48:34ここでルート名を使う利点は、パスを変更しても
01:48:38リンクを変更する必要がないことです。
01:48:40ルート名が変わらない限りは。
01:48:42それはもちろん便利な点です。
01:48:44さて。
01:48:45パスを頻繁に変更することはあまりないかもしれませんが。
01:48:47それでも。
01:48:48かなり便利ですね。
01:48:52やあ。
01:48:52Kiddie meです。
01:48:53そして、そうですね。
01:48:55これはLaravelに触発されています。
01:48:57まさにそうです。
01:48:58彼ら自身も「JavaScriptのためのLaravel」としてブランディングしていると思います。
01:49:07手でソフトウェアを書かないといけないんですか?
01:49:09そんなの赤ん坊のおもちゃですよ。
01:49:12まあ。
01:49:17そうですね。
01:49:18何かを学ぶときは。
01:49:19間違いなく手を動かすでしょう。
01:49:21間違いなく手でコードを書きます。
01:49:23なぜなら、読むだけでは...
01:49:26私はその両方を組み合わせます。
01:49:28でも、ライブ配信では当然ですが。
01:49:29AIに全て任せてしまうと、あまり面白くないでしょう。
01:49:30ただ、ほんの数分前に使ったばかりなんですけどね。
01:49:33でも、そうですね。
01:49:36でも、ええ。
01:49:37学習のためには間違いなく。
01:49:39中に入り込んで。
01:49:40読むだけでは。
01:49:44読むだけでは物事を十分に理解できません。
01:49:46さて。
01:49:47すべてのコードを自分で書くとは言いません。
01:49:504年前のように。
01:49:52そんなことは全くありません。
01:49:54でも、少なくとも基本は重要です。
01:49:56感覚を掴むためには。
01:49:56つまり、ここで。
01:49:57参加したばかりですよね。
01:49:58私が書いたものをコピーしていただけですけど。
01:49:59いや、その...
01:50:01コード。
01:50:03ええ。
01:50:03ええ。
01:50:03わかっています。
01:50:03わかっていますよ。
01:50:04伝わりました。
01:50:05気を悪くしないでください。
01:50:06ただ。
01:50:07コードを書くことについては。
01:50:09一般的に良いポイントだと思います。
01:50:10だからコメントしているんです。
01:50:12私は。
01:50:14コードを書くことは、学習において今でも良いことだと思います。
01:50:18でも。
01:50:19冗談だったとしても。
01:50:21あるいは引用だとしても。
01:50:24それは。
01:50:26それは。
01:50:26明らかに変化しています。
01:50:28さっきも聞かれました。
01:50:32新しいコースについて。
01:50:33そして1つの問題。
01:50:34あるいは私が理解しようとしているのは。
01:50:35どのようにして。
01:50:37今、テクノロジーを最もよく学べるかということです。
01:50:41そして、それがまだ重要なのか。
01:50:42私は「はい」と答えます。
01:50:43それは間違いなく重要です。
01:50:45でも、そうですね。
01:50:46まさにその点です。
01:50:47どれくらい手で書くのか。
01:50:48どれくらいコピーして貼り付けるのか。
01:50:50どれくらいAIに説明させたり生成させたりするのか。
01:50:52それは。
01:50:53ただ長々と話してしまいました。
01:50:54長々と話してしまいました。
01:50:54でも、これは間違いなく変化していることです。
01:50:57そして、これがAdonis JSです。
01:51:00つまり。
01:51:00基本的にはJavaScriptのためのLaravelです。
01:51:09よし。
01:51:09というわけで。
01:51:14ええ。
01:51:15コメント。
01:51:16それはしないと思います。
01:51:18あと10分で出ないといけないので。
01:51:20なので、ここはこのままにしておきます。
01:51:22残りの数ページを簡単に見ていきましょう。
01:51:28ここのページ。
01:51:29このガイドにはあまり残っていません。
01:51:31かなり順調に進めましたね。
01:51:33フォームとバリデーション。
01:51:35ここでアイデアとしては。
01:51:37もちろん、コントローラー関数を持つこともできます。
01:51:40POSTリクエストで呼び出されるコントローラーメソッドを。
01:51:43それを確認できます。
01:51:45ユーザーコントローラーはないのでしょうか?
01:51:48ありませんか。
01:51:52ユーザー。
01:51:54これです。
01:51:54新しいアカウントコントローラー。
01:51:56ここです。
01:51:57ストア。
01:51:57それは。
01:51:59コントローラーメソッドです。
01:52:00呼び出されるのは。
01:52:02POSTリクエストで。
01:52:04これですね。
01:52:05そして。
01:52:06したがって。
01:52:07これは単なる通常のメソッドです。
01:52:08しかし、その中で既に見ることができます。
01:52:10validateUsingメソッドを使えることを。
01:52:13メソッド。
01:52:13そしてバリデーターを定義します。
01:52:14それは最終的に。
01:52:16小さなユーティリティオブジェクトです。
01:52:18そのVineツールで作られたものです。
01:52:21どんなデータを。
01:52:22受け入れたいか、そのルールを定義できます。
01:52:24そうすれば。
01:52:24エラーが自動的に生成されます。
01:52:26もし。
01:52:27バリデーション基準が満たされていない場合。
01:52:29つまり、全体のアイデアです。
01:52:30LaravelやAdonisの背後にあるのは。
01:52:30Adonis。
01:52:31彼らは多くの作業を肩代わりしてくれます。
01:52:33そしてあなたは。
01:52:33論理を定義できます。
01:52:34かなり高いレベルで。
01:52:36一方。
01:52:37Next.
01:52:37JS。
01:52:37などでは。
01:52:38多くの場合、非常に具体的になる必要があります。
01:52:41そして明らかに。
01:52:41自分でバリデーションライブラリを持ってくる必要があります。
01:52:43その他すべての楽しいことと一緒に。
01:52:52ここでしていることは。
01:52:54ルートを登録することです。
01:52:56それについてはもう見ましたね。
01:52:59今回、新しいビューを作成しています。
01:53:00ここでフォームを作成しています。
01:53:02これらはすべて、いくつか特定の
01:53:05コードスニペットです。
01:53:06でももちろん。
01:53:08ここにもそれがあります。
01:53:12どこでしょう?
01:53:13ログイン。
01:53:14そう。
01:53:14Inertiaを使っていればそれが見えます。
01:53:17ここにフォームコンポーネントがあります。
01:53:19これはAdonis.jsのInertiaパッケージからのものです。
01:53:22これもルートにリンクされています。
01:53:24トリガーされるはずの。
01:53:25もしフォームが送信されたら。
01:53:26それがこのストアルートです。
01:53:27今見た。
01:53:28あるいはそのストアコントローラーアクション。
01:53:30最終的には。
01:53:31そのルートによって呼び出されます。
01:53:33そしてデータは。
01:53:34推測ですが。
01:53:36リクエストにパックされて。
01:53:37バックエンドに自動的に送信されます。
01:53:39それはもちろん便利です。
01:53:40自分でそのコードを書かなくていいので。
01:53:42あるいはAIに書いてもらう必要もない。
01:53:45もしEdgeを使っているなら。
01:53:46フォーム入力をこのようにレンダリングできます。
01:53:48そして間違いなく。
01:53:50これは少し考えやすく。
01:53:51読みやすいと思います。
01:53:56そしてバリデーターを作成できます。
01:53:57先ほどすでに1つ見ました。
01:53:58あのVineのものですね。
01:54:00単純に定義するだけです。
01:54:01データについて。
01:54:02受け取る予定の。
01:54:04ルールは何ですか。
01:54:05最小長。
01:54:06最大長。
01:54:07データ型。
01:54:08などです。
01:54:10storeメソッドを取得して、
01:54:11そして再び
01:54:11ORMを使います。
01:54:13クラスを使って、
01:54:14静的なcreateメソッドを呼び出して、
01:54:16データを保存します。
01:54:19コメントも
01:54:20同じようにします。
01:54:23ユーザーとリンクさせて、
01:54:24IDを通して
01:54:26ユーザーを取得します。
01:54:28そのauthを通して。
01:54:30プロパティです。
01:54:31これは自動的に取得できます。
01:54:32繰り返しになりますが、
01:54:33それはまるで
01:54:33Adonisが裏でやってくれているようなもので、
01:54:35認証を自動的に処理してくれます。
01:54:37登録されている
01:54:39ミドルウェアのおかげでね。
01:54:40そうですね。
01:54:40ルートでは、
01:54:40いくつかの
01:54:41認証ミドルウェアが
01:54:42適用されています。
01:54:43例えば
01:54:44ルートはすべて認証を必要とします。
01:54:46中にあるルートも同様です。
01:54:48ですから、
01:54:48同じように。
01:54:51このauthも取得できます。
01:54:53プロパティです。
01:54:54これを使って
01:54:55データを取得したり、
01:54:56現在認証されている
01:54:57ユーザーに関する情報ですね。
01:54:58あるいは、これを使って
01:54:59ユーザーをログアウトさせることもできます。
01:55:00今回のようにね。
01:55:01他にも色々。
01:55:02すべて簡単です。
01:55:03セットアップさえしてしまえば、
01:55:04かなり便利ですね。
01:55:06少なくともそう思います。
01:55:07以前これを使ったことが
01:55:08あるわけではありませんが、
01:55:09ええ。
01:55:11学びました。
01:55:11あなたから自由に見て、
01:55:12原則を転送しました。
01:55:14コードなどの
01:55:14コードへ。
01:55:15質の高いコードを書くための、
01:55:16あなたのレッスンは
01:55:16今でも価値があります。
01:55:17良いプロンプトのために。
01:55:18ええ。
01:55:18あと、私が探索していることの一つは、
01:55:20どのように
01:55:20将来のコースに
01:55:22盛り込むかということです。
01:55:23エージェントスキルや、
01:55:24追加のドキュメントのようなものを。
01:55:25エージェントに読み込ませて、
01:55:26エージェントが
01:55:27より良いコードを書く手助けを
01:55:28できるようにするためのものです。
01:55:31もちろん、
01:55:32保証はできませんが。
01:55:33エージェントは
01:55:34いつでも独自の判断で動く可能性があるからです。
01:55:37ですが、それも
01:55:38私が探索していることの一つです。
01:55:39もちろん。
01:55:40AdonisとVue 3、
01:55:40どちらが好きかということですが。
01:55:41Adonisは
01:55:42使い始めたばかりで、
01:55:43これまで使ったことはありません。
01:55:45そしてVue 3は、
01:55:46厳密には
01:55:47代替品ではありません。
01:55:48なぜならAdonisはフルスタックで、
01:55:49Vueは
01:55:50クライアント側のフロントエンドだからです。
01:55:52Nuxtを使えば、
01:55:52フルスタックになりますが、
01:55:53それでも
01:55:54哲学が異なります。
01:55:55Adonisは
01:55:55「電池付属(すぐに使える状態)」なので、
01:55:57認証機能なども
01:55:58標準装備です。
01:55:59一方でNuxtやNextは、
01:56:00自分でライブラリを
01:56:00探して導入する必要があります。
01:56:01最終的にどちらが
01:56:02好きかは分かりません。
01:56:03Adonisのアプローチは好きですし、
01:56:04フルスタックアプリケーションを
01:56:06構築するなら
01:56:06間違いなく価値があると思います。
01:56:07ただ、私はNext.jsに
01:56:08慣れすぎていて、
01:56:09今さらAdonisに乗り換えるかと言うと、
01:56:11今の環境の方が
01:56:11素早く開発できるので、
01:56:12どうなるかは分かりません。
01:56:13ですが、
01:56:14外部依存関係が少ないといった
01:56:15明確な利点もあるので、
01:56:16今後も
01:56:17少しずつ触って、
01:56:17何が有益か、
01:56:18何がそうでないかを評価していくつもりです。
01:56:19ええ、それが計画です。
01:56:21あと、
01:56:22スタイリングについては
01:56:23CSSで何とでもなるので
01:56:25あまり気にしていません。
01:56:27ただ、認証(認可)機能については、
01:56:28詳しく見てみたいですね。
01:56:28Adonisエコシステムの一部として
01:56:29インストールできるパッケージがあるんです。
01:56:30認可機能用ですね。
01:56:31これは
01:56:31特定の操作を行う権限がない
01:56:32ユーザーをブロックするためのものです。
01:56:33認証(ログイン)と認可(アクセス権限)は別物です。
01:56:34例えば、
01:56:35ユーザーがログインしていても、
01:56:36他の人の投稿を
01:56:37編集できてはいけません。
01:56:37それは理にかなっていますよね。
01:56:38なので、
01:56:39認証だけでは不十分で、
01:56:40認可も必要になるのです。
01:56:41そこをチェックしたいと思っています。
01:56:41おっと、
01:56:43少し長くなりそうですね。
01:56:44とにかく、
01:56:45まずはここまで。
01:56:46さて、
01:56:46次のセクションに
01:56:47進みましょう。
01:56:48認証と認可について、
01:56:49より深く掘り下げていきます。
01:56:50準備はいいですか?
01:56:51では始めましょう。
01:56:51まず、
01:56:52認証ミドルウェアから見ていきましょう。
01:56:53これがあれば、
01:56:54特定のルートを
01:56:55ログインしたユーザーのみに
01:56:55制限できます。
01:56:56例えば、
01:56:57ダッシュボードへのアクセスなどは
01:56:58そうすべきですよね。
01:56:58その後、ユーザー情報を取得して、
01:57:00画面に表示するのも
01:57:02とても簡単です。
01:57:03ここでのポイントは、
01:57:03認証されたユーザーは
01:57:04自動的に利用可能になるということです。
01:57:05これについては
01:57:07また別の機会に詳しく話しましょう。
01:57:07ええ。
01:57:08では次に、
01:57:08ログアウト機能も見てみましょう。
01:57:09これもauthプロパティで
01:57:10一発です。
01:57:10メソッドを呼ぶだけで
01:57:12ログアウトが完了します。
01:57:13本当に便利ですよね。
01:57:16さて、ここまでは認証の話でしたが、
01:57:18ここからは
01:57:19「認可」についてです。
01:57:20こちらもAdonisでは
01:57:21Bouncerというパッケージが
01:57:22標準で用意されています。
01:57:24これを使えば、
01:57:25誰が何ができるかを
01:57:27簡単に定義できます。
01:57:27例えば、
01:57:28自分の投稿以外は
01:57:29編集できないようにするといった
01:57:30制限がかけられます。
01:57:31認証だけでは
01:57:33防げないセキュリティリスクも、
01:57:35これで対応可能です。
01:57:36これが認可の役割ですね。
01:57:37認証で本人確認し、
01:57:39認可でアクセスを制御する。
01:57:40この組み合わせが重要なんです。
01:57:41アプリケーション開発において、
01:57:42非常に大事なポイントなので
01:57:43ぜひ覚えておいてください。
01:57:44それではコードを見ていきましょう。
01:57:46Bouncerの
01:57:46設定方法から始めます。
01:57:47投稿を編集することは
01:57:48できないように
01:57:49すべきです。
01:57:51つまり。
01:57:52認証だけでは
01:57:52不十分なんです。
01:57:53多くの場合、
01:57:54認可も
01:57:55必要になります。
01:57:57そこで
01:57:57このBouncerパッケージが
01:57:58役に立ちそうです。
01:58:01これを使えば
01:58:01いわゆる
01:58:02ポリシーというものを
01:58:03作成できるようです。
01:58:04見てみましょう。
01:58:05ポリシーとはクラスです。
01:58:07Adonisの
01:58:07クラスを
01:58:08継承したクラスで、
01:58:09Bouncer
01:58:10パッケージから提供されます。
01:58:11そして、ここで定義できます。
01:58:13そうですね。
01:58:13基本的に
01:58:15ここで権限を定義します。
01:58:16例えば
01:58:17編集が許可されるのは
01:58:18ユーザーIDが
01:58:20投稿したユーザーのIDと
01:58:21一致する場合、
01:58:22といった具合です。
01:58:23編集しようとしている
01:58:24投稿の削除も同様です。
01:58:26そして、
01:58:27そのポリシーを適用できます。
01:58:29見てみましょう。
01:58:30ええ。
01:58:30設定できました。
01:58:34コントローラーのメソッドに追加します。
01:58:43どこで適用しているかというと、
01:58:44ああ、そうですね。
01:58:45ここです。
01:58:45つまり
01:58:46コントローラー内で、
01:58:48そう。
01:58:48ここ。
01:58:49新しいメソッドが追加されました。
01:58:50編集メソッドです。
01:58:51これはトリガーされるはずです。
01:58:52当然ですが。
01:58:52もし
01:58:53フォームを送信して、
01:58:54投稿を編集したい場合や、
01:58:56あるいは
01:58:57ページを読み込みたい場合など、
01:58:58投稿の編集画面ですね。
01:58:59今見てみるとですね。
01:59:01このメソッドの中で
01:59:02私たちは
01:59:03投稿を見つけて、
01:59:04編集するわけですが、
01:59:05その後、
01:59:06ビューを返す前に、
01:59:08このBouncerパッケージが
01:59:09機能を提供してくれます。
01:59:11ポリシーを読み込んで、
01:59:12適用したい
01:59:13ポリシーですね。
01:59:14そこで基本的に
01:59:15ポリシーを通して、
01:59:16そのユーザーが
01:59:17編集しようとしている内容が
01:59:19許可されているかを確認します。
01:59:23なるほど。
01:59:25わかりました。
01:59:27そうですね。
01:59:29チャット。
01:59:30AIなら同じライブラリで
01:59:3110通りの方法で
01:59:32アプリを構築できます。
01:59:33ですから、
01:59:34プログラミングパラダイムに
01:59:35焦点を当てるべきでしょう。
01:59:37そうですね。
01:59:38全くその通りです。
01:59:38重要なスキルだと思います。
01:59:39開発者にとってもAIにとっても。
01:59:41ドキュメントを通じて、
01:59:42スキルを通じて、
01:59:44教えることですね。
01:59:45特定のパターンや、
01:59:46知っているはずの
01:59:47基本などを。
01:59:48だからこそ
01:59:49私も計画しているんです。
01:59:50プログラミングの基礎や、
01:59:51システム設計など、
01:59:52そんな楽しい講座を。
01:59:53バックエンドWeb APIを
01:59:54作るなら、
01:59:55C#のような
01:59:55厳密に型付けされた言語が
01:59:57良い選択かもしれません。
01:59:58(なぜか音声が消されましたが)。
02:00:00あるいは、型が削除され、
02:00:01NPMパッケージに
02:00:02脆弱性が
02:00:03山ほどある
02:00:03TypeScriptとNode.jsに
02:00:05頼るという手もあります。
02:00:06最終的には、
02:00:07バックエンド言語については
02:00:081時間でも話せますが、
02:00:09時間がありませんね。
02:00:12Node.jsと
02:00:13JavaScriptエコシステム全体の
02:00:15その話だけで1時間くらい
02:00:16話せてしまうほどです
02:00:17非常に精通していることです。
02:00:18AIを
02:00:20開発に使うなら
02:00:21パッケージが
02:00:22そしてJavaScriptの
02:00:23もちろん、
02:00:24サプライチェーン攻撃といった
02:00:24巨大なリスクもありますが。
02:00:26その通りですね。
02:00:28他の言語なら
02:00:28より良いパフォーマンスが得られます。
02:00:30Go、Rust、
02:00:31C#など、
02:00:32関心のあるものを
02:00:33調べてみるのは
02:00:34非常に良いことだと思います。
02:00:35バックエンド開発に。
02:00:36ただ、私の経験上、
02:00:38TypeScriptは
02:00:39開発速度が速いです。
02:00:41なぜなら
02:00:41AIが
02:00:42非常によく
02:00:42理解しているからです。
02:00:44私もよく理解しているので、
02:00:45AIが
02:00:46間違った方向に進んでも
02:00:47すぐに
02:00:48修正できます。
02:00:49ですから、
02:00:50TypeScriptです。
02:00:51とはいえ、
02:00:52確かに
02:00:53他のバックエンド言語を使う
02:00:55メリットも
02:00:56十分にあります。
02:00:56すべてJavaScriptである
02:00:57必要はありません。
02:00:58なぜNestJSの方が人気があるのか、
02:00:59正直わかりません。
02:01:01なぜAdonisが
02:01:02これほどニッチなのか、
02:01:02納得のいく
02:01:04説明はできません。
02:01:05さて、
02:01:06行く時間になりました。
02:01:06面白いテーマでした。
02:01:06楽しかったですね。
02:01:07Adonisを
02:01:08掘り下げられて、
02:01:09みなさんも楽しんで
02:01:10いただけたなら幸いです。
02:01:11また参加してくれてありがとう。
02:01:12JavaScriptである必要はありません
02:01:14なぜNestJSの方が人気があるんでしょうね?
02:01:16その翌週については
02:01:17追って案内します。
02:01:19Discordで
02:01:19告知しています。
02:01:22もし未参加なら、
02:01:23[akadamind.com/community](https://www.google.com/search?q=https://akadamind.com/community)
02:01:24から
02:01:24参加してください。
02:01:25あるいは
02:01:26チャンネル登録をして、
02:01:28フォローしておけば
02:01:29わかるはずです。
02:01:30木曜日の
02:01:31午後5時、
02:01:32中央ヨーロッパ夏時間です。
02:01:32いつもこのくらいの時間に
02:01:34終了します。
02:01:35それでは、みなさん。
02:01:36良い一日を、
02:01:37あるいは素敵な夜を。
02:01:39また次回
02:01:40お会いしましょう。
02:01:40ご参加いただき、
02:01:41本当にありがとうございました。
02:01:42さようなら。
02:01:43(音楽など)
02:01:45(音楽など)
02:01:46(音楽など)
02:01:47(音楽など)
02:01:48(音楽など)
02:01:48(音楽など)
02:01:49(音楽など)
02:01:50まだ参加していないなら
02:01:51こちらへどうぞ
02:01:51akadamind.com
02:01:53のコミュニティまで
02:01:54Discordに参加してください
02:01:54そこで告知します
02:01:56もちろん
02:01:56登録して
02:01:57フォローしてくれれば
02:01:58そこでも確認できます
02:01:59とにかく
02:02:00木曜日の
02:02:01午後5時
02:02:03中央ヨーロッパの
02:02:04夏時間です
02:02:05いつもと同じ時間に
02:02:06終わる予定です
02:02:07今終わるこの時間ですね
02:02:09はい
02:02:09皆さんありがとう
02:02:11素晴らしい一日を
02:02:13夜を
02:02:13朝を
02:02:14人それぞれの時間を過ごしてください
02:02:15また会えることを願っています
02:02:17ではまた
02:02:17皆さん参加してくれてありがとう

Key Takeaway

Adonis.jsはLaravelのような「オールインワン」の哲学を持ち、多数のサードパーティライブラリを組み合わせる代わりに、単一のフレームワーク内で認証やデータベース管理を完結させることで依存関係のリスクを低減するNode.jsフレームワークである。

Highlights

  • Adonis.jsは、認証、ORM、レート制限などの機能を標準で備えた「電池付属」型のNode.jsおよびTypeScriptフルスタックフレームワークである。

  • フロントエンドの構築において、Adonis.jsはサーバーサイドレンダリング用のEdgeテンプレート、Inertia.jsを介したReact統合、REST APIの3つのアプローチをサポートしている。

  • セキュリティ脆弱性への対策として、不要な外部依存関係を制限できることはAdonis.jsの重要な利点である。

  • CLIコマンド「node ace」により、モデルやマイグレーションの作成、ルートの一覧表示などのタスクをプログラム的に実行できる。

  • 開発サーバーの立ち上げ時にViteが自動的に実行され、CSSやJavaScriptのバンドル管理を担当する。

Timeline

Adonis.jsの概要と設計哲学

  • Adonis.jsはJavaScriptにおけるLaravelのような位置づけのフルスタックフレームワークである。
  • 外部ライブラリへの依存を最小限に抑えることで、供給連鎖攻撃のリスクを低減させる設計になっている。

Adonis.jsはバックエンドファーストでありながらフルスタック機能を持つ型安全なフレームワークです。Next.jsのようなサーバーサイドのReactレンダリングだけでなく、標準で認証、レート制限、ORMを提供し、他のライブラリの追加を不要にします。

フロントエンド構築の3つの手法

  • Adonis.jsはEdgeテンプレートによるマルチページアプリ、Inertia.jsによるReact統合、REST APIの構築という3つのアプローチを提供している。
  • 全てのアプリケーションがクライアントサイドでReactを必要とするわけではなく、要件に応じた選択が可能である。

Adonis.jsはテンプレートエンジンEdgeを使用したサーバーサイドレンダリングや、Inertia.jsをブリッジとしたReactの利用をサポートしています。複雑なフロントエンドが不要なブログ等の場合は、軽量なEdgeテンプレートの使用が推奨されます。

プロジェクトの構成とコマンドラインツール

  • node aceコマンドはAdonisのCLIツールであり、独自のサブコマンド登録やマイグレーション実行が可能である。
  • プロジェクト構造はLaravelに類似しており、appディレクトリにロジック、resourcesにフロントエンドリソースが配置される。

Adonis.jsでは設定ファイルや環境変数の管理が明確に分かれており、adonisrc.tsでフレームワークの構成を定義します。マイグレーションファイルはデータベースのスキーマを定義し、プログラム的にテーブルを操作可能です。

ORM「Lucid」によるデータベース操作

  • Lucid ORMを使用することで、SQLクエリを直接書くことなくモデルクラスを通じてデータベース操作ができる。
  • マイグレーションはモデルと連動し、テーブルの生成や外部キーの設定を管理する設計図として機能する。

モデルを使用してデータベーステーブルをクラスとして表現し、ファクトリーとシーダーを利用して開発用のダミーデータをプログラム的に生成できます。これにより生のSQLを記述せずとも、モデル間のリレーションシップを管理しクエリを実行可能です。

コントローラー、ビュー、認可の設定

  • コントローラーメソッドはHTTPコンテキストを受け取り、Inertiaを介してデータを変換してビューに送信する。
  • Bouncerパッケージによるポリシー定義で、認証後のユーザーに対して操作権限の制限(認可)が可能である。

MVCアーキテクチャに基づき、ルート、コントローラー、ビューを接続します。Bouncerパッケージを使用することで、認証されたユーザーが編集権限を持つかをポリシークラスで判定する認可ロジックを実装可能です。

Community Posts

No posts yet. Be the first to write about this video!

Write about this video