<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>OZの教える×プログラミング成長記</title>
	<atom:link href="https://oz006.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://oz006.com</link>
	<description></description>
	<lastBuildDate>Wed, 17 Sep 2025 03:48:47 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://oz006.com/wp-content/uploads/2024/10/cropped-OZLogo-32x32.png</url>
	<title>OZの教える×プログラミング成長記</title>
	<link>https://oz006.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>OAuth 2.0って何？</title>
		<link>https://oz006.com/oauth/</link>
					<comments>https://oz006.com/oauth/#respond</comments>
		
		<dc:creator><![CDATA[oz]]></dc:creator>
		<pubDate>Wed, 17 Sep 2025 03:48:46 +0000</pubDate>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[Google認証]]></category>
		<category><![CDATA[OAuth2.0]]></category>
		<guid isPermaLink="false">https://oz006.com/?p=754</guid>

					<description><![CDATA[実際の流れを見てみよう 実際のプログラムを見てみよう セキュリティは大丈夫？ まとめ]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="1000" height="1000" src="https://oz006.com/wp-content/uploads/2025/09/OAuth2.0.jpg" alt="" class="wp-image-757" srcset="https://oz006.com/wp-content/uploads/2025/09/OAuth2.0.jpg 1000w, https://oz006.com/wp-content/uploads/2025/09/OAuth2.0-300x300.jpg 300w, https://oz006.com/wp-content/uploads/2025/09/OAuth2.0-150x150.jpg 150w, https://oz006.com/wp-content/uploads/2025/09/OAuth2.0-768x768.jpg 768w" sizes="(max-width: 1000px) 100vw, 1000px" /></figure>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="プロ太" class="speech-icon-image"/></figure><div class="speech-name">プロ太</div></div><div class="speech-balloon">
<p class="wp-block-paragraph">さて、今日はGoogle認証について学習していきましょう♫<br>OZくんは「OAuth 2.0」という仕組みを聞いたことある？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="OZ" class="speech-icon-image"/></figure><div class="speech-name">OZ</div></div><div class="speech-balloon">
<p class="wp-block-paragraph">オーオース…？初めて聞きます。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">難しく考えなくて大丈夫。身近な例で説明するね。<br>OZくんが友達に「代わりに宿題を取りに行って」って頼む場面を想像してみて。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">了解です！想像しました！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">でも、先生は友達のことを知らないから「あなた誰？」ってなりますよね。そこでOZくんが友達に<strong>「私の代わりに宿題を取りに行ってください」という手紙</strong>を渡したとします。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">あ！分かった！<span class="bold">委任状</span>みたいなものですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そう！！それが理解できたら、OAuth 2.0も理解できるよ！OAuth 2.0も同じ考え方なんだよ。</p>
</div></div>



<ol class="wp-block-list">
<li>あなた（ユーザー）が写真印刷サービスを使いたい</li>



<li>サービスが「Googleフォトから写真を取得していいですか？」と聞く</li>



<li>あなたが「はい、いいですよ」と<strong>許可</strong>する</li>



<li>Googleが「この人は許可しました」という<strong>証明書</strong>をサービスに渡す</li>



<li>サービスがその証明書を使って、あなたの写真を取得</li>
</ol>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！パスワードを教えるんじゃなくて、「この人は信頼できます」っていう証明書を渡すんですね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">その通り！しかも、この許可はいつでも取り消せるし、「写真だけアクセスOK、でもメールはダメ」みたいに細かく設定できるんだ。</p>
</div></div>



<h2 class="wp-block-heading">実際の流れを見てみよう</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">じゃあ、実際にユーザーがGoogle認証を使う時の流れを見てみましょう。OZくんが新しいアプリに登録する場面を想像してください。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">はい！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><strong>ステップ1</strong>: アプリで「Googleアカウントでログイン」ボタンを押してください。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">ポチッ！っとな！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><strong>ステップ2</strong>: すると、Googleのページに飛ばされます。そこで「○○アプリにログインしますか？」って聞かれる</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">おぉ！よく見る画面ですね！ここで「許可」を押すんですよね？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><strong>ステップ3</strong>: そう！「許可」を押すと、元のアプリに戻されて&#8230;</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">ログイン完了！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><strong>ステップ4</strong>: その通り！この時、裏ではGoogleからアプリに「この人の名前はOZで、メールアドレスは○○です」みたいな情報が送られてるんだよ。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">へぇ〜！でも、その情報って勝手に送られちゃうんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">いい質問だね！<strong>ユーザーが「許可」ボタンを押さない限り、何も送られません</strong>。しかも、送られる情報も事前に「名前とメールアドレスにアクセスします」って表示されるから、何を共有するかが分かるんだよ。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">安心ですね！勝手に全部見られちゃうのかと思いました。</p>
</div></div>



<h2 class="wp-block-heading">実際のプログラムを見てみよう</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">今度は、実際にどうやってプログラムを書くのか見てみましょう。Laravelという技術を使った例です。<br>まず、ユーザーが「Googleでログイン」ボタンを押した時の処理から見ていきましょう。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-php" data-lang="PHP"><code>// Googleの認証画面に送る処理
public function redirectToGoogle()
{
    return Socialite::driver(&#39;google&#39;)-&gt;stateless()-&gt;redirect();
}</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">これだけでGoogleのページに飛ばせるんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうだよ！<span class="bold"><span class="marker-under">「Socialite」っていう便利なツール</span></span>が全部やってくれるんです。次は、Googleから帰ってきた時の処理を見ていこう！</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-php" data-lang="PHP"><code>public function handleGoogleCallback()
{
    // Googleからユーザー情報をもらう
    $googleUser = Socialite::driver(&#39;google&#39;)-&gt;stateless()-&gt;user();
    
    // このメールアドレスの人、もう登録済み？
    $existingUser = User::where(&#39;email&#39;, $googleUser-&gt;getEmail())-&gt;first();
    
    if ($existingUser) {
        // 既に登録済み → ログインさせる
        Auth::login($existingUser);
    } else {
        // 初めての人 → 新しくアカウントを作る
        $user = User::create([
            &#39;name&#39; =&gt; $googleUser-&gt;getName(),
            &#39;email&#39; =&gt; $googleUser-&gt;getEmail(),
            // ... その他の情報
        ]);
        Auth::login($user);
    }
}</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！既に登録している人と初めての人で処理を分けてるんですね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">その通り！既に登録している人はそのままログインして、初めての人は自動で新しいアカウントを作ってからログインさせてるんだよ。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">自動でアカウントが作られるなんて、便利ですね！</p>
</div></div>



<h2 class="wp-block-heading">セキュリティは大丈夫？</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">でも先生、こんなに便利だと、逆にセキュリティが心配になってきました。悪い人に悪用されたりしないんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">実は、Google認証をちゃんと実装するには、いくつか注意が必要なんだよ。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">どんなことに注意するんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">まず一番重要なのは、<strong>HTTPS</strong>を使うことだよ</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">HTTPSって、URLの最初に鍵マークが付くやつですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そう！暗号化されていないと、通信の途中で悪い人に認証情報を盗まれる可能性があるんだよ。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">怖い…他にはどんな対策があるんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">二つ目は、<strong>秘密の情報をソースコードに直接書かない</strong>ことだね。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-php" data-lang="PHP"><code>// &#x274c; 危険：コードに直接書く
&#39;client_secret&#39; =&gt; &#39;abc123def456&#39;,

// &#x2705; 安全：設定ファイルで管理
&#39;client_secret&#39; =&gt; env(&#39;GOOGLE_SECRET&#39;),</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！家の鍵を玄関に置きっぱなしにしないのと同じ感じですね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そして、三つ目は、<strong>必要最小限の情報だけもらう</strong>ことだね。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-php" data-lang="PHP"><code>// &#x274c; 危険：何でもかんでも取得
$scopes = [&#39;email&#39;, &#39;profile&#39;, &#39;calendar&#39;, &#39;drive&#39;, &#39;photos&#39;];

// &#x2705; 安全：本当に必要な分だけ
$scopes = [&#39;email&#39;, &#39;profile&#39;];</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">確かに！必要ない情報までもらわない方が安全ですもんね。</p>
</div></div>



<h2 class="wp-block-heading">まとめ</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">というわけで、Google認証は、ユーザーがGoogleアカウントを使って他のサイトにログインできる仕組みです。OAuth 2.0という国際標準を使用していて、ユーザーの許可を得て安全に情報を共有します。Laravelだと、Laravel Socialiteを使って、簡単に実装することができる。既存ユーザーかどうかをメールアドレスで判定し、新規の場合は自動でアカウントを作成する仕組みを使えるということを押させておきましょう♫</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">はい！ありがとうございました！！</p>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://oz006.com/oauth/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>LaravelとRailsのデプロイはどう違う？初心者向け完全ガイド</title>
		<link>https://oz006.com/laravel-rails-deploy/</link>
					<comments>https://oz006.com/laravel-rails-deploy/#respond</comments>
		
		<dc:creator><![CDATA[oz]]></dc:creator>
		<pubDate>Thu, 26 Jun 2025 05:48:20 +0000</pubDate>
				<category><![CDATA[Laravel]]></category>
		<category><![CDATA[プログラミング]]></category>
		<guid isPermaLink="false">https://oz006.com/?p=744</guid>

					<description><![CDATA[Laravel（PHP）のデプロイ &#8211; 「引っ越し」方式 Laravel デプロイの特徴 Rails（Ruby）のデプロイ &#8211; 「お店開業」方式 なぜ「常駐」が必要？ PHP（Laravel）の場 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img decoding="async" width="1000" height="571" src="https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-26-14.47.24-A-split-screen-illustration-showing-the-deployment-process-for-Laravel-PHP-on-one-side-and-Ruby-on-Rails-on-the-other.-The-Laravel-side-shows-icons-.webp" alt="" class="wp-image-748" srcset="https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-26-14.47.24-A-split-screen-illustration-showing-the-deployment-process-for-Laravel-PHP-on-one-side-and-Ruby-on-Rails-on-the-other.-The-Laravel-side-shows-icons-.webp 1000w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-26-14.47.24-A-split-screen-illustration-showing-the-deployment-process-for-Laravel-PHP-on-one-side-and-Ruby-on-Rails-on-the-other.-The-Laravel-side-shows-icons--300x171.webp 300w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-26-14.47.24-A-split-screen-illustration-showing-the-deployment-process-for-Laravel-PHP-on-one-side-and-Ruby-on-Rails-on-the-other.-The-Laravel-side-shows-icons--768x439.webp 768w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-26-14.47.24-A-split-screen-illustration-showing-the-deployment-process-for-Laravel-PHP-on-one-side-and-Ruby-on-Rails-on-the-other.-The-Laravel-side-shows-icons--120x68.webp 120w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-26-14.47.24-A-split-screen-illustration-showing-the-deployment-process-for-Laravel-PHP-on-one-side-and-Ruby-on-Rails-on-the-other.-The-Laravel-side-shows-icons--160x90.webp 160w" sizes="(max-width: 1000px) 100vw, 1000px" /></figure>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">先生、こんにちは！今日はLaravelとRailsのデプロイについて教えてください！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">OZくん、こんにちは！いい質問だね。まず「デプロイ」って何か分かる？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">えーっと…作ったWebアプリを、みんながアクセスできるようにサーバーに置くことですよね？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">その通りだよ。でも、LaravelとRailsでは、その「置き方」が全然違うんだ。</p>
</div></div>



<h2 class="wp-block-heading">Laravel（PHP）のデプロイ &#8211; 「引っ越し」方式</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">まずLaravelから説明するね。LaravelはPHPで作られているから、デプロイはとても簡単なんだ。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">どれくらい簡単なんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">例えるなら「引っ越し」みたいなものかな。</p>
</div></div>



<pre class="wp-block-code"><code>1. 作ったファイルをzipに圧縮
2. レンタルサーバーにアップロード
3. 解凍
4. はい、完成！</code></pre>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">え、それだけですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">基本的にはね！共有レンタルサーバー（月額500円とか）でも動くから、お財布にも優しいよ。</p>
</div></div>



<h3 class="wp-block-heading">Laravel デプロイの特徴</h3>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="302" src="https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-143320-1024x302.png" alt="" class="wp-image-745" srcset="https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-143320-1024x302.png 1024w, https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-143320-300x88.png 300w, https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-143320-768x226.png 768w, https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-143320.png 1052w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">Rails（Ruby）のデプロイ &#8211; 「お店開業」方式</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">一方、Railsのデプロイは「お店を開業する」みたいなものなんだ。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">お店を開業…？どういうことですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">コンビニを想像してみて。コンビニって、お客さんが来ても来なくても、店員さんがずっと店にいるでしょ？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">あ、確かに！24時間営業ですもんね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">Railsも同じで、ユーザーがアクセスしてもしなくても、サーバー上で<strong>ずっと動き続けている</strong>必要があるんだ。</p>
</div></div>



<h2 class="wp-block-heading">なぜ「常駐」が必要？</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">これが重要なポイントなんだ。</p>
</div></div>



<h3 class="wp-block-heading">PHP（Laravel）の場合</h3>



<pre class="wp-block-code"><code>1. ユーザーがアクセス
2. その瞬間だけPHPが起動
3. 結果を返す
4. PHP終了（お疲れ様）</code></pre>



<h3 class="wp-block-heading">Rails の場合</h3>



<pre class="wp-block-code"><code>1. Rails アプリを起動（ずっと待機）
2. ユーザーがアクセス
3. 待機中のRailsが応答
4. また待機状態に戻る（終了しない）</code></pre>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！宅配便の人（PHP）と、コンビニ店員（Rails）の違いですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうそう！そんなイメージでOKだよ。</p>
</div></div>



<h2 class="wp-block-heading">共有レンタルサーバーでRailsが動かない理由</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">でも、共有レンタルサーバーでRailsが動かないのはなぜですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">いい質問だね。共有レンタルサーバーを「シェアハウス」だと思ってみて。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">シェアハウス？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そう。1つの建物（サーバー）を100人でシェアして使うんだ。もし100人全員が「コンビニ店員」（Rails）を自分の部屋に常駐させたら…</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">あ！電気代（メモリ）がすごいことになりますね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">正解！だから共有レンタルサーバーでは「常に動き続けるアプリは禁止」になってるんだ。</p>
</div></div>



<h3 class="wp-block-heading">Rails デプロイの特徴</h3>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="293" src="https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-143853-1024x293.png" alt="" class="wp-image-746" srcset="https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-143853-1024x293.png 1024w, https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-143853-300x86.png 300w, https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-143853-768x220.png 768w, https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-143853.png 1048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">実際のコスト比較</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">結局、どっちがお金かかるんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">一般的にはRailsの方が高くなるね。比較してみよう！</p>
</div></div>



<h3 class="wp-block-heading">個人ブログレベル</h3>



<ul class="wp-block-list">
<li><strong>Laravel</strong>: ロリポップ（月額500円）</li>



<li><strong>Rails</strong>: さくらVPS（月額1,000円〜）</li>
</ul>



<h3 class="wp-block-heading">本格的なWebサービス</h3>



<ul class="wp-block-list">
<li><strong>Laravel</strong>: 共有サーバー高級プラン（月額3,000円）</li>



<li><strong>Rails</strong>: AWS EC2（月額5,000円〜20,000円）</li>
</ul>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-12 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ02.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">うわー、Railsって結構お金かかるんですね…</p>
</div></div>



<h2 class="wp-block-heading">それでもRailsが人気な理由</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">でも、大きなWebサービスでRailsがよく使われるのには理由があるんだよ。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">どんな理由ですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">主に3つあるね。</p>
</div></div>



<h3 class="wp-block-heading">1. 開発効率が抜群</h3>



<pre class="wp-block-code"><code>Laravel: 複雑な機能は時間がかかる
Rails: 「魔法」のような機能で開発が早い</code></pre>



<h3 class="wp-block-heading">2. 大規模サービスに強い</h3>



<pre class="wp-block-code"><code>Laravel: アクセス増加時の対応が大変
Rails: スケールアップが比較的簡単</code></pre>



<h3 class="wp-block-heading">3. セキュリティが堅牢</h3>



<pre class="wp-block-code"><code>Laravel: 自分で対策を考える部分が多い
Rails: フレームワークが自動で守ってくれる</code></pre>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！「安い」より「作りやすい」を重視するってことですね。</p>
</div></div>



<h2 class="wp-block-heading">初心者はどちらを選ぶべき？</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">僕みたいな初心者は、どっちから始めるのがいいですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">目的によって違うよ。</p>
</div></div>



<h3 class="wp-block-heading">こんな人はLaravel（PHP）がおすすめ</h3>



<ul class="wp-block-list">
<li>個人ブログやポートフォリオサイトを作りたい</li>



<li>とにかく費用を抑えたい</li>



<li>簡単にWebサイトを公開したい</li>



<li>HTMLやCSSの知識がある</li>
</ul>



<h3 class="wp-block-heading">こんな人はRails（Ruby）がおすすめ</h3>



<ul class="wp-block-list">
<li>本格的なWebアプリを作りたい</li>



<li>プログラミングをしっかり学びたい</li>



<li>将来エンジニアとして働きたい</li>



<li>サーバー管理も覚えたい</li>
</ul>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">は将来エンジニアになりたいから、Railsの方がいいのかな？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうだね！Railsは確かに学習コストは高いけど、得られるスキルも多いよ。</p>
</div></div>



<h2 class="wp-block-heading">まとめ：どちらも素晴らしい技術</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">最後に大事なことを言うね。LaravelもRailsも、どちらも素晴らしい技術なんだ。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうなんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">うん。「どちらが優れているか」ではなく、「何を作りたいか」「どんなエンジニアになりたいか」で選ぶのが正解だよ。</p>
</div></div>



<h3 class="wp-block-heading">選択の指針</h3>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="958" height="310" src="https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-144507.png" alt="" class="wp-image-747" srcset="https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-144507.png 958w, https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-144507-300x97.png 300w, https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-144507-768x249.png 768w" sizes="auto, (max-width: 958px) 100vw, 958px" /></figure>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">よく分かりました！ありがとうございます、プロ太先生！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">どういたしまして！どちらを選んでも、しっかり学べば素晴らしいエンジニアになれるよ。頑張って！</p>
</div></div>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://oz006.com/laravel-rails-deploy/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Rails 開発者必見！Stimulus で React の useState のような動的 UI 更新を実現する方法</title>
		<link>https://oz006.com/rails-stimulus/</link>
					<comments>https://oz006.com/rails-stimulus/#respond</comments>
		
		<dc:creator><![CDATA[oz]]></dc:creator>
		<pubDate>Mon, 23 Jun 2025 15:48:00 +0000</pubDate>
				<category><![CDATA[プログラミング]]></category>
		<guid isPermaLink="false">https://oz006.com/?p=740</guid>

					<description><![CDATA[Scene 1: 問題発見！文字数が更新されない &#x1f631; Scene 2: Stimulus って何？&#x1f914; Stimulus の特徴 **HTML 中心**: HTML に`data-*`属性を [&#8230;]]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1000" height="1000" src="https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-24-00.47.11-A-conceptual-illustration-representing-the-Stimulus-JavaScript-framework-used-in-Ruby-on-Rails-applications-with-the-word-Stimulus-prominently-disp.webp" alt="" class="wp-image-741" srcset="https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-24-00.47.11-A-conceptual-illustration-representing-the-Stimulus-JavaScript-framework-used-in-Ruby-on-Rails-applications-with-the-word-Stimulus-prominently-disp.webp 1000w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-24-00.47.11-A-conceptual-illustration-representing-the-Stimulus-JavaScript-framework-used-in-Ruby-on-Rails-applications-with-the-word-Stimulus-prominently-disp-300x300.webp 300w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-24-00.47.11-A-conceptual-illustration-representing-the-Stimulus-JavaScript-framework-used-in-Ruby-on-Rails-applications-with-the-word-Stimulus-prominently-disp-150x150.webp 150w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-24-00.47.11-A-conceptual-illustration-representing-the-Stimulus-JavaScript-framework-used-in-Ruby-on-Rails-applications-with-the-word-Stimulus-prominently-disp-768x768.webp 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure>



<h2 class="wp-block-heading"><strong>Scene 1: 問題発見！文字数が更新されない &#x1f631;</strong></h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-12 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ02.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">プロ太先生、大変です！面談記録の文字数カウントが全然更新されないんです&#8230;</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">どれどれ、見せてみたまえ。ああ、これはよくある問題だね。JavaScript で`getElementById`を使って実装しているが、Rails の`form_with`で生成されるフォーム要素との相性が悪いんだ。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-12 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ02.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">React なら useState を使えばすぐに解決できるのに&#8230;Rails だと難しいんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">いや、実は Rails には<strong><span class="marker-under">**Stimulus**という素晴らしいツール</span></strong>があるんだ！React の useState のような動的な更新を、Rails らしい方法で実現できるよ。</p>
</div></div>



<h2 class="wp-block-heading"><strong>Scene 2: Stimulus って何？&#x1f914;</strong></h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-12 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ02.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">Stimulus&#8230;初めて聞きました！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">Stimulus は <strong><span class="marker-under">Rails 標準の JavaScript フレームワーク</span></strong>だよ。<strong>**HTML-first**</strong>の思想で、既存の HTML に JavaScript の機能を後から追加できるんだ。</p>
</div></div>



<h3 class="wp-block-heading"><strong>Stimulus の特徴</strong></h3>



<p class="wp-block-paragraph"> <strong>**HTML 中心**</strong>: <span class="marker-under">HTML に`data-*`属性を追加するだけ</span></p>



<p class="wp-block-paragraph"> <strong>**軽量**</strong>: React/Vue のような大きなライブラリは不要</p>



<p class="wp-block-paragraph"> <strong>**Rails 標準**</strong>: Turbo・Hotwire と連携して動作</p>



<p class="wp-block-paragraph"> <strong>**段階的導入**</strong>: 既存のプロジェクトに簡単導入</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！でも具体的にはどう使うんですか？</p>
</div></div>



<h2 class="wp-block-heading"><strong>Scene 3: 実際のコードで学ぼう！&#x1f4bb;</strong></h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">OZ君の文字数カウンター問題を例に、実際のコードを見てみよう。</p>
</div></div>



<h3 class="wp-block-heading">1.<strong>Stimulus コントローラーの作成</strong></h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">まず、`app/javascript/controllers/character_counter_controller.js`を作成するよ！</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-js" data-lang="JavaScript"><code>
// Stimulusの基本クラスをインポート
import { Controller } from &quot;@hotwired/stimulus&quot;;

// Stimulusコントローラーを定義（クラス名は自由だが、ファイル名と対応させる）
export default class extends Controller {
  // HTMLのどの要素をターゲットにするか定義
  // &quot;input&quot;と&quot;counter&quot;という名前のターゲットを設定
  static targets = [&quot;input&quot;, &quot;counter&quot;];

  // HTMLから渡される値を定義
  // 最小文字数(min)と最大文字数(max)を数値として受け取る
  static values = { min: Number, max: Number };

  // コントローラーがDOMに接続された時に自動実行
  // Reactの useEffect(() =&gt; {}, []) に相当
  connect() {
    this.updateCount(); // 初期表示時に文字数を更新
  }

  // 文字数カウントを更新するメソッド
  // Reactの setState() に相当する処理
  updateCount() {
    // inputTargetから現在のテキストを取得
    const text = this.inputTarget.value;
    const count = text.length;

    // counterTargetに文字数を表示
    // ReactのuseStateで状態を更新するのと同じ効果
    this.counterTarget.textContent = count;

    // 文字数に応じてスタイルを動的に変更
    // 条件によってCSSクラスを切り替え
    if (count &lt; this.minValue) {
      this.counterTarget.className = &quot;text-red-600&quot;; // 文字数不足：赤色
    } else if (count &gt; this.maxValue) {
      this.counterTarget.className = &quot;text-red-600&quot;; // 文字数超過：赤色
    } else {
      this.counterTarget.className = &quot;text-green-600&quot;; // 適切な文字数：緑色
    }
  }
}</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">おお！これがコントローラーですか。React のコンポーネントみたいですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">その通り！そして次は、HTML でこのコントローラーを使うんだ。</p>
</div></div>



<h3 class="wp-block-heading"><strong>2. HTML ビューでの使用方法</strong></h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">以下が、<br>`app/views/auth/interview_record.html.erb`の該当部分だよ。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;!-- data-controller属性でStimulusコントローラーを指定 --&gt;
&lt;!-- data-*-value属性で値をJavaScriptに渡す --&gt;
&lt;div data-controller=&quot;character-counter&quot;
     data-character-counter-min-value=&quot;10&quot;
     data-character-counter-max-value=&quot;2000&quot;&gt;

  &lt;label class=&quot;block text-sm font-medium text-gray-700 mb-2&quot;&gt;
    面談内容 &lt;span class=&quot;text-red-500&quot;&gt;*&lt;/span&gt;
  &lt;/label&gt;

  &lt;!-- textareaをinputターゲットとして指定 --&gt;
  &lt;!-- data-action属性でイベントとメソッドを紐付け --&gt;
  &lt;%= form.text_area :content,
        rows: 12,
        class: &quot;w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 resize-none&quot;,
        data: {
          character_counter_target: &quot;input&quot;,           # inputターゲットとして指定
          action: &quot;input-&gt;character-counter#updateCount&quot; # inputイベント時にupdateCountメソッド実行
        } %&gt;

  &lt;p class=&quot;mt-2 text-sm text-gray-500&quot;&gt;
    10文字以上2000文字以内で入力してください。
    &lt;span class=&quot;ml-2&quot;&gt;
      &lt;!-- counterターゲットとして指定：ここに文字数が表示される --&gt;
      現在: &lt;span data-character-counter-target=&quot;counter&quot;&gt;0&lt;/span&gt;文字
    &lt;/span&gt;
  &lt;/p&gt;
&lt;/div&gt;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！HTML の`data-*`属性で JavaScript と連携するんですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうです。では、具体的にどう連携するのか、step-by-step で詳しく見てみよう。</p>
</div></div>



<h4 class="wp-block-heading"><strong>Step 1: `data-controller` でコントローラーを接続</strong></h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;!-- ① この div要素にStimulusコントローラーを接続 --&gt;
&lt;div data-controller=&quot;character-counter&quot;&gt;
  &lt;!-- この要素の中で character-counter が有効になる --&gt;
&lt;/div&gt;</code></pre></div>



<p class="wp-block-paragraph">何が起こるかの説明</p>



<p class="wp-block-paragraph">&#8211; `character-counter` → `CharacterCounterController` クラスを自動で探す</p>



<p class="wp-block-paragraph">&#8211; ファイル名: `character_counter_controller.js` → クラスと自動マッピング</p>



<p class="wp-block-paragraph">&#8211; この div の中でコントローラーの `connect()` メソッドが実行される</p>



<h4 class="wp-block-heading"><strong>Step 2: `data-*-target` で要素を指定</strong></h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;div data-controller=&quot;character-counter&quot;&gt;
  &lt;!-- ② inputターゲットとして textarea を指定 --&gt;
  &lt;textarea data-character-counter-target=&quot;input&quot;&gt;&lt;/textarea&gt;

  &lt;!-- ③ counterターゲットとして span を指定 --&gt;
  &lt;span data-character-counter-target=&quot;counter&quot;&gt;0&lt;/span&gt;
&lt;/div&gt;</code></pre></div>



<p class="wp-block-paragraph">何が起こるかの説明</p>



<div class="hcb_wrap"><pre class="prism off-numbers lang-js" data-lang="JavaScript"><code>// JavaScript側で、こうアクセスできるようになる
this.inputTarget; // ← textarea要素を取得
this.counterTarget; // ← span要素を取得

// つまり、getElementById() の代わりに、こんな感じ：
// Before: document.getElementById(&#39;my-textarea&#39;)
// After:  this.inputTarget</code></pre></div>



<h4 class="wp-block-heading"><strong>Step 3: `data-action` でイベントを紐付け</strong></h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;div data-controller=&quot;character-counter&quot;&gt;
  &lt;!-- ④ inputイベントが発生したらupdateCountメソッドを実行 --&gt;
  &lt;textarea
    data-character-counter-target=&quot;input&quot;
    data-action=&quot;input-&gt;character-counter#updateCount&quot;
  &gt;&lt;/textarea&gt;

  &lt;span data-character-counter-target=&quot;counter&quot;&gt;0&lt;/span&gt;
&lt;/div&gt;</code></pre></div>



<p class="wp-block-paragraph">何が起こるかの説明</p>



<p class="wp-block-paragraph">&#8211; `input` = イベント名（文字入力のたび）</p>



<p class="wp-block-paragraph">&#8211; `character-counter` = コントローラー名</p>



<p class="wp-block-paragraph">&#8211; `updateCount` = 実行するメソッド名</p>



<p class="wp-block-paragraph">&#8211; つまり: <strong>**「文字入力されたら updateCount メソッドを呼び出して」**</strong></p>



<h4 class="wp-block-heading"><strong>Step 4: `data-*-*-value` で値を渡す</strong></h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;div
  data-controller=&quot;character-counter&quot;
  data-character-counter-min-value=&quot;10&quot;
  data-character-counter-max-value=&quot;2000&quot;
&gt;
  &lt;textarea
    data-character-counter-target=&quot;input&quot;
    data-action=&quot;input-&gt;character-counter#updateCount&quot;
  &gt;&lt;/textarea&gt;

  &lt;span data-character-counter-target=&quot;counter&quot;&gt;0&lt;/span&gt;
&lt;/div&gt;</code></pre></div>



<p class="wp-block-paragraph">何が起こるかの説明</p>



<div class="hcb_wrap"><pre class="prism off-numbers lang-js" data-lang="JavaScript"><code>// JavaScript側で、こう使える
this.minValue // ← 10 が入る（Number型に自動変換）
this.maxValue // ← 2000 が入る（Number型に自動変換）

// values定義があるから自動で型変換される
static values = { min: Number, max: Number }</code></pre></div>



<h2 class="wp-block-heading"><strong>実際の動作フロー</strong></h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">つまり、どういう順番で動くんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">実際の動作を順番に見てみよう。</p>
</div></div>



<p class="wp-block-paragraph">1&#xfe0f;&#x20e3; ページ読み込み</p>



<p class="wp-block-paragraph">↓</p>



<p class="wp-block-paragraph">2&#xfe0f;&#x20e3; data-controller=&#8221;character-counter&#8221; を発見</p>



<p class="wp-block-paragraph">↓</p>



<p class="wp-block-paragraph">3&#xfe0f;&#x20e3; CharacterCounterController の connect() が実行</p>



<p class="wp-block-paragraph">↓</p>



<p class="wp-block-paragraph">4&#xfe0f;&#x20e3; this.updateCount() で初期の文字数表示</p>



<p class="wp-block-paragraph">↓</p>



<p class="wp-block-paragraph">5&#xfe0f;&#x20e3; ユーザーがテキストエリアに文字入力</p>



<p class="wp-block-paragraph">↓</p>



<p class="wp-block-paragraph">6&#xfe0f;&#x20e3; inputイベント発生</p>



<p class="wp-block-paragraph">↓</p>



<p class="wp-block-paragraph">7&#xfe0f;&#x20e3; data-action で指定された updateCountメソッド実行</p>



<p class="wp-block-paragraph">↓</p>



<p class="wp-block-paragraph">8&#xfe0f;&#x20e3; this.inputTarget.value で現在の文字を取得</p>



<p class="wp-block-paragraph">↓</p>



<p class="wp-block-paragraph">9&#xfe0f;&#x20e3; this.counterTarget.textContent で文字数を表示更新</p>



<h2 class="wp-block-heading"><strong>Stimulus の魔法のポイント</strong></h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！`data-*`属性だけで、こんなに連携できるんですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうなんだ！ポイントは以下の 4 つだよ。</p>
</div></div>



<p class="wp-block-paragraph">1. <strong>**自動マッピング**</strong>: `data-controller=&#8221;character-counter&#8221;` → `CharacterCounterController`</p>



<p class="wp-block-paragraph">2. <strong>**自動要素取得**</strong>: `data-*-target=&#8221;input&#8221;` → `this.inputTarget`</p>



<p class="wp-block-paragraph">3. <strong>**自動イベント設定**</strong>: `data-action=&#8221;input-&gt;*#updateCount&#8221;` → 自動でイベントリスナー設定</p>



<p class="wp-block-paragraph">4. <strong>**自動型変換**</strong>: `data-*-*-value=&#8221;10&#8243;` → `this.minValue` (Number 型)</p>



<h2 class="wp-block-heading"><strong>**再利用性**の高さ</strong></h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">この`character-counter`って、他の場所でも使えるんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">もちろん！OZ君も既に気づいているはずだよ。モーダルでも同じコントローラーを使っているだろう？</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;!-- &#x1f44d; 同じコントローラーを別の場所で再利用 --&gt;
&lt;div data-controller=&quot;character-counter&quot; data-character-counter-min-value=&quot;5&quot; data-character-counter-max-value=&quot;500&quot;&gt;
  &lt;!-- コメント用のフォーム --&gt;
&lt;/div&gt;

&lt;div data-controller=&quot;character-counter&quot; data-character-counter-min-value=&quot;10&quot; data-character-counter-max-value=&quot;2000&quot;&gt;
  &lt;!-- 面談記録用のフォーム --&gt;
&lt;/div&gt;</code></pre></div>



<h2 class="wp-block-heading"><strong>Scene ４: 実践！他の使用例</strong></h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">理解を深めるために、他の例も見ておこう。</p>
</div></div>



<h3 class="wp-block-heading">例１：<strong>自動保存機能</strong></h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-js" data-lang="JavaScript"><code>// auto_save_controller.js
import { Controller } from &quot;@hotwired/stimulus&quot;;

export default class extends Controller {
  static targets = [&quot;form&quot;, &quot;status&quot;];
  static values = { url: String, interval: Number };

  connect() {
    this.autoSave = setInterval(() =&gt; {
      this.save();
    }, this.intervalValue);
  }

  save() {
    // フォームデータを自動保存
    this.statusTarget.textContent = &quot;保存中...&quot;;
    // Ajax処理...
  }
}</code></pre></div>



<h3 class="wp-block-heading"><strong>例 2: 検索の候補表示</strong></h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-js" data-lang="JavaScript"><code>// search_controller.js
import { Controller } from &quot;@hotwired/stimulus&quot;;

export default class extends Controller {
  static targets = [&quot;input&quot;, &quot;results&quot;];

  search() {
    const query = this.inputTarget.value;
    if (query.length &gt; 2) {
      // 検索API呼び出し
      this.showResults(results);
    }
  }
}</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！いろんな場面で使えるんですね！</p>
</div></div>



<h2 class="wp-block-heading">まとめ</h2>



<p class="wp-block-paragraph"><strong>Stimulus のポイント</strong></p>



<p class="wp-block-paragraph">1. <strong>**HTML-first**</strong>: HTML が主役、JavaScript は脇役</p>



<p class="wp-block-paragraph">2. <strong>**軽量**</strong>: 必要最小限の機能で高速</p>



<p class="wp-block-paragraph">3. <strong>**Rails 標準**</strong>: Turbo/Hotwire との連携が抜群</p>



<p class="wp-block-paragraph">4. <strong>**再利用性**</strong>: 一度作れば色々な場所で使える</p>



<p class="wp-block-paragraph">5. <strong>**学習コスト**</strong>: 基本的な JavaScript の知識があれば十分</p>



<p class="wp-block-paragraph"><strong>いつ使うべき？</strong></p>



<p class="wp-block-paragraph">&#8211; &#x2705; <strong>**部分的な動的機能**</strong>が欲しい時</p>



<p class="wp-block-paragraph">&#8211; &#x2705; <strong>**既存の Rails アプリ**</strong>に機能追加したい時</p>



<p class="wp-block-paragraph">&#8211; &#x2705; <strong>**軽量な解決策**</strong>が欲しい時</p>



<p class="wp-block-paragraph">&#8211; &#x2705; <strong>**Rails Way**</strong>に沿って開発したい時</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">プロ太先生、ありがとうございました！Stimulus が Rails での動的 UI 更新の強い味方だということがよく分かりました！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうだね。React の useState のような機能を Rails らしい方法で実現できるのが Stimulus の魅力だ。これからの Rails 開発では必須のツールになるよ！</p>
</div></div>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://oz006.com/rails-stimulus/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>完成した統一認証システム</title>
		<link>https://oz006.com/rails-quick-mendan-login-function/</link>
					<comments>https://oz006.com/rails-quick-mendan-login-function/#respond</comments>
		
		<dc:creator><![CDATA[oz]]></dc:creator>
		<pubDate>Tue, 17 Jun 2025 01:30:39 +0000</pubDate>
				<category><![CDATA[プログラミング]]></category>
		<guid isPermaLink="false">https://oz006.com/?p=734</guid>

					<description><![CDATA[統一された認証フロー セッションベース認証の実装 講師認証の実装 生徒認証の実装 モデルの統一されたカスタム認証 Teacher モデル Student モデル ApplicationHelper の統一設計 認証チェッ [&#8230;]]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1000" height="1000" src="https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-17-10.29.35-A-conceptual-illustration-of-an-authentication-system.-The-image-features-a-digital-interface-with-a-secure-login-screen-showing-a-username-and-passw.webp" alt="" class="wp-image-735" srcset="https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-17-10.29.35-A-conceptual-illustration-of-an-authentication-system.-The-image-features-a-digital-interface-with-a-secure-login-screen-showing-a-username-and-passw.webp 1000w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-17-10.29.35-A-conceptual-illustration-of-an-authentication-system.-The-image-features-a-digital-interface-with-a-secure-login-screen-showing-a-username-and-passw-300x300.webp 300w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-17-10.29.35-A-conceptual-illustration-of-an-authentication-system.-The-image-features-a-digital-interface-with-a-secure-login-screen-showing-a-username-and-passw-150x150.webp 150w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-17-10.29.35-A-conceptual-illustration-of-an-authentication-system.-The-image-features-a-digital-interface-with-a-secure-login-screen-showing-a-username-and-passw-768x768.webp 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">プロ太先生、Quick Mendanの認証システムが完成しました！講師も生徒も同じパターンで実装されていて、すごくスッキリしています！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">素晴らしいね！どんな設計になっているのか、詳しく見てみようか。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">はい！まず全体像から説明します。</p>
</div></div>



<h3 class="wp-block-heading">統一された認証フロー</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># 講師認証（AuthController）
GET  /staff/login     → staff_login（ログイン画面表示）
POST /staff/login     → staff_authenticate（認証処理）
DELETE /staff/logout  → staff_logout（ログアウト処理）

# 生徒認証（StudentsController）
GET  /student/login   → login（ログイン画面表示）
POST /student/login   → authenticate（認証処理）
DELETE /student/logout → logout（ログアウト処理）</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">おお、完全に同じパターンだね！URLの構造も統一されている。</p>
</div></div>



<h2 class="wp-block-heading">セッションベース認証の実装</h2>



<h3 class="wp-block-heading">講師認証の実装</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># app/controllers/auth_controller.rb
class AuthController &lt; ApplicationController
  def staff_authenticate
    username = params[:username]
    password = params[:password]
    
    # カスタム認証メソッドで検索
    teacher = Teacher.find_for_database_authentication(email: username)
    
    if teacher && teacher.valid_password?(password)
      # セッションに講師IDを保存
      session[:teacher_id] = teacher.id
      redirect_to staff_dashboard_path, notice: &#39;ログインしました&#39;
    else
      flash.now[:alert] = &#39;ユーザー名またはパスワードが正しくありません&#39;
      render :staff_login
    end
  end

  def staff_logout
    # セッションをクリア
    session[:teacher_id] = nil
    redirect_to root_path, notice: &#39;ログアウトしました&#39;
  end

  private

  def current_staff_user
    @current_staff_user ||= session[:teacher_id] && Teacher.find_by(id: session[:teacher_id])
  end
end</code></pre></div>



<h3 class="wp-block-heading">生徒認証の実装</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># app/controllers/students_controller.rb
class StudentsController &lt; ApplicationController
  def authenticate
    student_number = params[:student_number]
    password = params[:password]
    
    # カスタム認証メソッドで検索
    student = Student.find_for_database_authentication(email: student_number)
    
    if student && student.valid_password?(password)
      # セッションに生徒IDを保存
      session[:student_id] = student.id
      redirect_to student_dashboard_path, notice: &#39;ログインしました&#39;
    else
      flash.now[:alert] = &#39;生徒番号またはパスワードが正しくありません&#39;
      render :login
    end
  end

  def logout
    # セッションをクリア
    session[:student_id] = nil
    redirect_to root_path, notice: &#39;ログアウトしました&#39;
  end

  private

  def current_student
    @current_student ||= session[:student_id] && Student.find_by(id: session[:student_id])
  end
end</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">講師も生徒も全く同じパターンですね！セッションに保存して、ログアウト時にクリアする。シンプルです！</p>
</div></div>



<h2 class="wp-block-heading">モデルの統一されたカスタム認証</h2>



<h3 class="wp-block-heading">Teacher モデル</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># app/models/teacher.rb
class Teacher &lt; ApplicationRecord
  # ユーザー名でログインするための設定
  def self.find_for_database_authentication(warden_conditions)
    # warden_conditions = {email: &quot;shibaguti&quot;}
    conditions = warden_conditions.dup
    if (email = conditions.delete(:email))
      # emailキーで渡された値をuser_login_nameで検索
      where(user_login_name: email).first
    else
      # emailキー以外の場合はnilを返す
      nil
    end
  end
end</code></pre></div>



<h3 class="wp-block-heading">Student モデル</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># app/models/student.rb
class Student &lt; ApplicationRecord
  # 生徒番号でログインするための設定
  def self.find_for_database_authentication(login_conditions)
    # login_conditions = {email: &quot;2024001&quot;}
    search_conditions = login_conditions.dup
    if (student_number_input = search_conditions.delete(:email))
      # emailキーで渡された値をstudent_numberで検索
      where([&quot;student_number = :student_number&quot;, { student_number: student_number_input }]).first
    else
      # emailキー以外の場合はnilを返す
      nil
    end
  end
end</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！両方とも :email キーを受け取って、それぞれの認証フィールドで検索している。Deviseとの互換性を保ちながら、カスタム認証を実現している設計だね。</p>
</div></div>



<h2 class="wp-block-heading">ApplicationHelper の統一設計</h2>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># app/helpers/application_helper.rb
module ApplicationHelper
  # 現在ログインしている講師を取得
  def current_teacher
    @current_teacher ||= session[:teacher_id] && Teacher.find_by(id: session[:teacher_id])
  end

  # 現在ログインしている生徒を取得（講師方式と統一）
  def current_student
    @current_student ||= session[:student_id] && Student.find_by(id: session[:student_id])
  end

  # 講師がログインしているかチェック
  def teacher_signed_in?
    current_teacher.present?
  end

  # 生徒がログインしているかチェック（講師方式と統一）
  def student_signed_in?
    current_student.present?
  end

  # 管理者がログインしているかチェック
  def admin_signed_in?
    current_teacher&.admin?
  end

  # 現在のユーザーが管理者かどうか
  def current_user_is_admin?
    current_teacher&.admin?
  end
end</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">ヘルパーメソッドも完全に対応しています。講師用も生徒用も同じパターンで実装されています！</p>
</div></div>



<h2 class="wp-block-heading">認証チェックの統一</h2>



<h3 class="wp-block-heading">講師用認証チェック</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># AuthController
before_action :require_staff, only: [:staff_dashboard]

private

def require_staff
  unless current_staff_user
    redirect_to staff_login_path, alert: &#39;ログインが必要です&#39;
  end
end</code></pre></div>



<h3 class="wp-block-heading">生徒用認証チェック</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># StudentsController
before_action :require_student_login, only: [:dashboard]

private

def require_student_login
  unless current_student
    redirect_to student_login_path, alert: &#39;ログインが必要です&#39;
  end
end</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">認証チェックも同じパターンだね。必要なアクションにのみ before_action を設定して、ログインが必要な場合は適切なログインページにリダイレクトする。</p>
</div></div>



<h2 class="wp-block-heading">フォームの統一設計</h2>



<h3 class="wp-block-heading">講師ログインフォーム</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;!-- app/views/auth/staff_login.html.erb --&gt;
&lt;%= form_with url: staff_login_path, method: :post, local: true do |f| %&gt;
  &lt;%= f.text_field :username, placeholder: &quot;ユーザー名&quot; %&gt;
  &lt;%= f.password_field :password, placeholder: &quot;パスワード&quot; %&gt;
  &lt;%= f.submit &quot;ログイン&quot; %&gt;
&lt;% end %&gt;</code></pre></div>



<h3 class="wp-block-heading">生徒ログインフォーム</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;!-- app/views/students/login.html.erb --&gt;
&lt;%= form_with url: student_login_path, method: :post, local: true do |f| %&gt;
  &lt;%= f.text_field :student_number, placeholder: &quot;生徒番号&quot; %&gt;
  &lt;%= f.password_field :password, placeholder: &quot;パスワード（9999）&quot; %&gt;
  &lt;%= f.submit &quot;ログイン&quot; %&gt;
&lt;% end %&gt;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">フォームの構造も同じです！フィールド名だけが違って、送信先のURLも統一されたパターンです！</p>
</div></div>



<h2 class="wp-block-heading">この設計のメリット</h2>



<h3 class="wp-block-heading">保守性の向上</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># 同じパターンなので、理解しやすく修正しやすい
# 講師用
session[:teacher_id] = teacher.id

# 生徒用  
session[:student_id] = student.id</code></pre></div>



<h3 class="wp-block-heading">拡張性の高さ</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># 将来、管理者認証を追加する場合も同じパターン
session[:admin_id] = admin.id

def current_admin
  @current_admin ||= session[:admin_id] && Admin.find_by(id: session[:admin_id])
end</code></pre></div>



<h3 class="wp-block-heading">Deviseへの依存排除</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">複雑なDevise設定に依存せず、シンプルなRailsの基本機能だけで実装している。</p>
</div></div>



<h3 class="wp-block-heading">パフォーマンスの向上</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># シンプルなセッション管理 = 高速
@current_student ||= session[:student_id] && Student.find_by(id: session[:student_id])</code></pre></div>



<h2 class="wp-block-heading">実際の動作フロー</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">実際にユーザーがログインする時の流れを確認してみましょう！</p>
</div></div>



<h3 class="wp-block-heading">生徒ログインの場合</h3>



<ol class="wp-block-list">
<li>ログインページアクセス: GET /student/login</li>



<li>フォーム送信: POST /student/login</li>



<li>StudentsController#authenticate 実行</li>
</ol>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>   student_number = params[:student_number]  # &quot;2024001&quot;
   student = Student.find_for_database_authentication(email: student_number)
   if student && student.valid_password?(password)
     session[:student_id] = student.id  # セッションに保存</code></pre></div>



<p class="wp-block-paragraph">  4. ダッシュボードにリダイレクト: GET /student/dashboard<br>  5. 認証チェック</p>



<ol class="wp-block-list"></ol>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>   def current_student
     @current_student ||= session[:student_id] && Student.find_by(id: session[:student_id])
   end</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">講師ログインも全く同じ流れで、フィールド名とセッションキーが違うだけです！！</p>
</div></div>



<h2 class="wp-block-heading">まとめ</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">この統一認証システムで学んだことをまとめてみます！</p>
</div></div>



<h3 class="wp-block-heading">設計の原則</h3>



<ol class="wp-block-list">
<li>統一性: 同じパターンを使い回す</li>



<li>シンプルさ: 複雑な機能に依存しない</li>



<li>可読性: コードが理解しやすい</li>



<li>拡張性: 新しい認証タイプを追加しやすい</li>



<li>保守性: メンテナンスが容易</li>
</ol>



<h3 class="wp-block-heading">技術のポイント</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># 1. セッションベース認証
session[:user_id] = user.id

# 2. カスタム認証メソッド
Model.find_for_database_authentication(email: identifier)

# 3. 統一されたヘルパーメソッド
def current_user
  @current_user ||= session[:user_id] && User.find_by(id: session[:user_id])
end

# 4. 一貫した認証チェック
before_action :require_authentication, only: [:protected_action]</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">素晴らしいまとめだね！この認証システムは、シンプルで美しく、実用的だ。Railsの基本を深く理解できる、とても良い学習材料になったね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">はい！Deviseの便利さも分かりましたが、基本から作ることでRailsの認証の仕組みがよく理解できました。ありがとうございました！</p>
</div></div>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://oz006.com/rails-quick-mendan-login-function/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Rails認証機能入門</title>
		<link>https://oz006.com/rails-authentication/</link>
					<comments>https://oz006.com/rails-authentication/#respond</comments>
		
		<dc:creator><![CDATA[oz]]></dc:creator>
		<pubDate>Wed, 11 Jun 2025 08:45:21 +0000</pubDate>
				<category><![CDATA[プログラミング]]></category>
		<guid isPermaLink="false">https://oz006.com/?p=720</guid>

					<description><![CDATA[認証機能って何？ Step1: 認証機能の土台を作ろう Step2: 最初のユーザーを作成しよう ここでのPoint!! ここで、サーバーを再起動しよう！ Step3: 認証機能を試してみよう Step4: ログアウト機 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1000" height="1000" src="https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-11-17.44.31-A-conceptual-illustration-of-Ruby-on-Rails-authentication-functionality.-The-image-shows-a-secure-login-form-on-a-web-page-displayed-on-a-laptop-scree.webp" alt="" class="wp-image-724" srcset="https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-11-17.44.31-A-conceptual-illustration-of-Ruby-on-Rails-authentication-functionality.-The-image-shows-a-secure-login-form-on-a-web-page-displayed-on-a-laptop-scree.webp 1000w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-11-17.44.31-A-conceptual-illustration-of-Ruby-on-Rails-authentication-functionality.-The-image-shows-a-secure-login-form-on-a-web-page-displayed-on-a-laptop-scree-300x300.webp 300w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-11-17.44.31-A-conceptual-illustration-of-Ruby-on-Rails-authentication-functionality.-The-image-shows-a-secure-login-form-on-a-web-page-displayed-on-a-laptop-scree-150x150.webp 150w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-11-17.44.31-A-conceptual-illustration-of-Ruby-on-Rails-authentication-functionality.-The-image-shows-a-secure-login-form-on-a-web-page-displayed-on-a-laptop-scree-768x768.webp 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure>



<h2 class="wp-block-heading">認証機能って何？</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-12 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ02.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">プロ太先生、今まで作ってきた製品管理アプリなんですが、<span class="marker-under">誰でも編集・削除できちゃう</span>んですよね…</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">それは大問題だよね。例えば、君の日記が誰でも読めて、勝手に書き換えられたら嫌ですよね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-12 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ02.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">はい、、。LaravelではAuth::user()みたいな認証機能がありましたが、Railsでも似たような機能があるんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">もちろんあるよ！RailsにはLaravelのBreeze（ブリーズ）みたいに、認証機能を自動で作ってくれる便利なジェネレータがあるんだ。今日はそれを使って、「ログイン・ログアウト機能」を追加してみよう！</p>
</div></div>



<h2 class="wp-block-heading">Step1: 認証機能の土台を作ろう</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">まずは、Rails付属の認証ジェネレータを使って基本機能を作るよ。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code># 認証機能に必要なファイルを一括生成
$ bin/rails generate authentication</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">おお、これだけでいいんですか！Laravelだと <code>composer require laravel/breeze</code> してから <code>php artisan breeze:install</code> って感じでしたよね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうそう！Railsの場合は最初から入ってるから、追加インストールは不要なんだ。このコマンドで以下が自動生成されるよ。</p>
</div></div>



<ul class="wp-block-list">
<li><strong>Userモデル</strong>: ユーザー情報を管理（Laravelと同じ）</li>



<li><strong>Sessionモデル</strong>: ログイン状態を管理</li>



<li><strong>コントローラ群</strong>: ログイン・ログアウト処理</li>



<li><strong>ビュー群</strong>: ログイン画面など</li>
</ul>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">次に、データベースにテーブルを作ろう。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code># データベースにusersテーブルとsessionsテーブルを作成
$ bin/rails db:migrate</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">これもLaravelの <code>php artisan migrate</code> と同じ感覚ですね！</p>
</div></div>



<h2 class="wp-block-heading">Step2: 最初のユーザーを作成しよう</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">テーブルができたら、実際にユーザーを作ってみよう。Railsコンソールを使うよ。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code># Railsコンソール（対話モード）を起動
$ bin/rails console</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">LaravelでいうTinkerですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">その通り！コンソールが開いたら、ユーザーを作成しよう。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># 新しいユーザーを作成（エラーが出たら例外を投げる）
store(dev)&gt; User.create! email_address: &quot;you@example.org&quot;, password: &quot;s3cr3t&quot;, password_confirmation: &quot;s3cr3t&quot;</code></pre></div>



<p class="wp-block-paragraph"><strong>ここでのPoint</strong>!!</p>



<ul class="wp-block-list">
<li><code>create!</code> の「!」= 「絶対に作る！失敗したらエラーを出して教えて！」なくても動くが実務ではつけるべき！！</li>



<li><code>password_confirmation</code> = パスワードの確認入力（タイプミス防止）</li>
</ul>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">LaravelのUser::create()と似てますが、パスワード確認が必要なんですね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">セキュリティを重視してるんだ。パスワードは自動でハッシュ化されるから、データベースには暗号化された状態で保存されるよ。</p>
</div></div>



<p class="wp-block-paragraph">ここで、サーバーを再起動しよう！</p>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code># bcrypt gem（パスワード暗号化ライブラリ）を有効にするため再起動
$ bin/rails server</code></pre></div>



<h2 class="wp-block-heading">Step3: 認証機能を試してみよう</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">認証機能を設定したら、どうやって動作確認するんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">まずは、普通にアプリのトップページを開いてみよう。ブラウザで <code>http://localhost:3000/</code> にアクセスしてみて。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">あ！いきなりログイン画面が出てきました！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そう！認証ジェネレータは、デフォルトで「全てのページ」を認証必須にするんだ。つまり：</p>



<ul class="wp-block-list">
<li>トップページ（<code>/</code>）</li>



<li>商品一覧（<code>/products</code>）</li>



<li>商品詳細（<code>/products/1</code>）</li>



<li>商品作成（<code>/products/new</code>）</li>
</ul>



<p class="wp-block-paragraph">全部ログインしないと見られない状態になってるんだよ。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！だから、どのページにアクセスしてもログイン画面になるんですね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">その通り！試しに <code>http://localhost:3000/products/new</code>（商品作成ページ）にアクセスしても、同じログイン画面が出るはずだよ。さっき作ったメールアドレスとパスワードを入力してみよう。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">ログインできました！これで製品の作成・編集ページにアクセスできるようになったんですね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">その通り！ブラウザがcookie（クッキー）という仕組みで認証情報を覚えているから、他のページに移動してもログイン状態が保持されるんだ。</p>
</div></div>



<h2 class="wp-block-heading">Step4: ログアウト機能を追加しよう</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">次は、ログアウトボタンを追加しよう。<code>app/views/layouts/application.html.erb</code>を編集するよ。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;!-- 省略 --&gt;
  &lt;body&gt;
    &lt;!-- ナビゲーションバー（全ページ共通のメニュー） --&gt;
    &lt;nav&gt;
      &lt;!-- ホームページへのリンク --&gt;
      &lt;%= link_to &quot;Home&quot;, root_path %&gt;
      
      &lt;!-- ログイン済みの場合のみログアウトボタンを表示 --&gt;
      &lt;%= button_to &quot;Log out&quot;, session_path, method: :delete if authenticated? %&gt;
    &lt;/nav&gt;

    &lt;!-- メインコンテンツエリア --&gt;
    &lt;main&gt;
      &lt;%= yield %&gt;  &lt;!-- 各ページの内容がここに入る --&gt;
    &lt;/main&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre></div>



<p class="wp-block-paragraph"><strong>ここでのポイント</strong>:</p>



<ul class="wp-block-list">
<li><code>link_to</code> = 「〇〇へのリンクを作って」</li>



<li><code>button_to</code> = 「〇〇用のボタンを作って」</li>



<li><code>if authenticated?</code> = 「もしログイン済みなら」</li>



<li><code>method: :delete</code> = 「DELETEリクエストで送信」（ログアウト=セッション削除）</li>
</ul>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">LaravelのBladeテンプレートの <code>@auth</code> ディレクティブと似てますね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうそう！<code>authenticated?</code> がLaravelの <code>Auth::check()</code> と同じ役割だよ。</p>
</div></div>



<h2 class="wp-block-heading">Step5: 一部のページは認証なしでもOKにしよう</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">ストアの商品一覧や詳細ページは、お客さんが見られるようにしておきたいよね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">確かに！ネットショップで商品を見るのにログインが必要だったら、誰も買い物しませんね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">ということで、<code>app/controllers/products_controller.rb</code>を編集しよう。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>class ProductsController &lt; ApplicationController
  # index（一覧）とshow（詳細）は認証なしでもアクセス可能
  allow_unauthenticated_access only: %i[ index show ]
  
  # 以下省略...
end</code></pre></div>



<p class="wp-block-paragraph"><strong>ここでのPoint</strong>!!</p>



<ul class="wp-block-list">
<li><code>allow_unauthenticated_access</code> = 「認証なしアクセスを許可する」</li>



<li><code>only: %i[ index show ]</code> = 「indexとshowアクションのみ」</li>



<li><code>%i[ ]</code> = シンボルの配列を作る簡単な書き方（<code>[:index, :show]</code>と同じ）</li>
</ul>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">LaravelのMiddlewareで <code>auth</code> を特定のルートから除外するのと似てますね！</p>
</div></div>



<h2 class="wp-block-heading">Step6: 認証状態に応じてリンクを出し分けよう</h2>



<h3 class="wp-block-heading">商品一覧ページ</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><code>app/views/products/index.html.erb</code>で、ログイン済みの人だけに「新商品作成」リンクを表示しよう</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;!-- ログイン済み の場合のみ新商品作成リンクを表示 --&gt;
&lt;%= link_to &quot;New product&quot;, new_product_path if authenticated? %&gt;</code></pre></div>



<h3 class="wp-block-heading">レイアウトファイル</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">さらに、<code>app/views/layouts/application.html.erb</code>にログインリンクも追加しよう。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;nav&gt;
  &lt;!-- ホームへのリンク --&gt;
  &lt;%= link_to &quot;Home&quot;, root_path %&gt;
  
  &lt;!-- ログイン状態によってリンクを出し分け --&gt;
  &lt;%= link_to &quot;Login&quot;, new_session_path unless authenticated? %&gt;  &lt;!-- 未ログインの場合 --&gt;
  &lt;%= button_to &quot;Log out&quot;, session_path, method: :delete if authenticated? %&gt;  &lt;!-- ログイン済みの場合 --&gt;
&lt;/nav&gt;</code></pre></div>



<p class="wp-block-paragraph"><strong>ここがポイント！！</strong></p>



<ul class="wp-block-list">
<li><code>if authenticated?</code> = 「ログイン済みなら表示」</li>



<li><code>unless authenticated?</code> = 「ログインしていなければ表示」</li>
</ul>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">app/views/products/show.html.erbも更新しよう！</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;h1&gt;&lt;%= @product.name %&gt;&lt;/h1&gt;  &lt;!-- 商品名を表示 --&gt;

&lt;!-- 一覧ページに戻るリンク（誰でも表示） --&gt;
&lt;%= link_to &quot;Back&quot;, products_path %&gt;

&lt;!-- ログイン済みの場合のみ編集・削除機能を表示 --&gt;
&lt;% if authenticated? %&gt;
  &lt;!-- 編集ページへのリンク --&gt;
  &lt;%= link_to &quot;Edit&quot;, edit_product_path(@product) %&gt;
  
  &lt;!-- 削除ボタン（確認ダイアログ付き） --&gt;
  &lt;%= button_to &quot;Destroy&quot;, @product, method: :delete, data: { turbo_confirm: &quot;Are you sure?&quot; } %&gt;
&lt;% end %&gt;</code></pre></div>



<p class="wp-block-paragraph"><strong>ここがポイント！！</strong><br><code>data: { turbo_confirm: "Are you sure?" }</code> = 削除前に確認ダイアログを表示</p>



<h2 class="wp-block-heading">Laravel vs Rails の認証機能比較</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">最後に、LaravelとRailsの認証機能を比較してみたいです！</p>
</div></div>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="724" src="https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-11-173955-1024x724.png" alt="" class="wp-image-723" srcset="https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-11-173955-1024x724.png 1024w, https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-11-173955-300x212.png 300w, https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-11-173955-768x543.png 768w, https://oz006.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-11-173955.png 1111w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">どちらも似たような機能があるんですね！でもアプローチが少し違う感じがします。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そう！Laravelは「Middleware」でフィルタリング、Railsは「Controller」で直接指定という違いがあるね。どちらも覚えやすいよ。</p>
</div></div>



<h2 class="wp-block-heading">まとめ：今日学んだこと</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">今日の学習内容をまとめよう！</p>
</div></div>



<ol class="wp-block-list">
<li><strong>認証機能の基本設定</strong>
<ul class="wp-block-list">
<li><code>bin/rails generate authentication</code>で一括生成</li>



<li><code>bin/rails db:migrate</code>でテーブル作成</li>
</ul>
</li>



<li><strong>ユーザー作成</strong>
<ul class="wp-block-list">
<li><code>bin/rails console</code>でRailsコンソール起動</li>



<li><code>User.create!</code>でユーザー作成</li>
</ul>
</li>



<li><strong>ログイン・ログアウト機能</strong>
<ul class="wp-block-list">
<li><code>authenticated?</code>でログイン状態を判定</li>



<li><code>button_to</code>でログアウト機能実装</li>
</ul>
</li>



<li><strong>アクセス制御</strong>
<ul class="wp-block-list">
<li><code>allow_unauthenticated_access</code>で一部ページを認証なしで許可</li>



<li>ビューで<code>if authenticated?</code>を使って表示制御</li>
</ul>
</li>
</ol>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">ありがとうございました！これで安全な製品管理アプリができました。LaravelとRailsの違いも理解できて、とても勉強になりました！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">セキュリティは開発の基本だから、しっかりマスターしておこうね。</p>
</div></div>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://oz006.com/rails-authentication/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Rails CRUD操作を学ぼう！初心者向け完全ガイド</title>
		<link>https://oz006.com/rails-crud/</link>
					<comments>https://oz006.com/rails-crud/#respond</comments>
		
		<dc:creator><![CDATA[oz]]></dc:creator>
		<pubDate>Wed, 11 Jun 2025 05:12:30 +0000</pubDate>
				<category><![CDATA[未分類]]></category>
		<guid isPermaLink="false">https://oz006.com/?p=716</guid>

					<description><![CDATA[第1章：CRUDって何？ 第2章：Railsでの準備 &#8211; コントローラーの基本 覚え方：@マーク = アット（at）= そこにある つまり、画面でも使えるようにそこに置いておく変数だと思えばいいよ！ 第3章： [&#8230;]]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1000" height="1000" src="https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-11-14.11.41-A-conceptual-illustration-of-Ruby-CRUD-operations-Create-Read-Update-Delete-in-a-web-development-context.-The-image-shows-a-laptop-with-Ruby-code.webp" alt="" class="wp-image-718" srcset="https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-11-14.11.41-A-conceptual-illustration-of-Ruby-CRUD-operations-Create-Read-Update-Delete-in-a-web-development-context.-The-image-shows-a-laptop-with-Ruby-code.webp 1000w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-11-14.11.41-A-conceptual-illustration-of-Ruby-CRUD-operations-Create-Read-Update-Delete-in-a-web-development-context.-The-image-shows-a-laptop-with-Ruby-code-300x300.webp 300w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-11-14.11.41-A-conceptual-illustration-of-Ruby-CRUD-operations-Create-Read-Update-Delete-in-a-web-development-context.-The-image-shows-a-laptop-with-Ruby-code-150x150.webp 150w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-11-14.11.41-A-conceptual-illustration-of-Ruby-CRUD-operations-Create-Read-Update-Delete-in-a-web-development-context.-The-image-shows-a-laptop-with-Ruby-code-768x768.webp 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure>



<h2 class="wp-block-heading">第1章：CRUDって何？</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">プロ太先生、CRUDって何ですか？クラッド？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">CRUDは、4つの英単語の頭文字を取ったものなんだよ。</p>
</div></div>



<ul class="wp-block-list">
<li><strong>C</strong>reate（作成）- 新しいデータを作る</li>



<li><strong>R</strong>ead（読み取り）- データを見る・表示する</li>



<li><strong>U</strong>pdate（更新）- 既存のデータを変更する</li>



<li><strong>D</strong>elete（削除）- データを消す</li>
</ul>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！つまり、データの基本的な操作ってことですね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">その通り！例えば、君がSNSに投稿するとき…<br>・新しい投稿を書く（Create）<br>・投稿を見る（Read）<br>・投稿を編集する（Update）<br>・投稿を削除する（Delete）<br>これ全部CRUDなんだ！</p>
</div></div>



<h2 class="wp-block-heading">第2章：Railsでの準備 &#8211; コントローラーの基本</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">じゃあ、実際にRailsで商品（Product）を管理するシステムを作ってみよう。まずは基本のコントローラーから見てみよう。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>class ProductsController &lt; ApplicationController
  # 商品一覧を表示するアクション
  def index
    @products = Product.all  # 全ての商品をデータベースから取得
  end

  # 個別の商品を表示するアクション
  def show
    @product = Product.find(params[:id])  # IDを使って特定の商品を取得
  end
end</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><code>@products</code>と<code>@product</code>って何で@マークが付いてるんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">いい質問だね！<strong><span class="marker-under">@マークが付いた変数は「インスタンス変数」と呼ばれて、コントローラーからビュー（画面）に値を渡すための特別な変数</span></strong>なんだ。</p>
</div></div>



<p class="wp-block-paragraph">覚え方：<strong>@マーク = アット（at）= そこにある</strong> つまり、画面でも使えるようにそこに置いておく変数だと思えばいいよ！</p>



<h2 class="wp-block-heading">第3章：Create（作成）- 新しい商品を作ろう</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">じゃあ、実際に新しい商品を作る機能を追加してみよう！</p>
</div></div>



<h3 class="wp-block-heading">3-1. newアクション（フォームを表示）</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>class ProductsController &lt; ApplicationController
  def index
    @products = Product.all  # 全商品を表示用に取得
  end

  def show
    @product = Product.find(params[:id])  # 指定された商品を取得
  end

  def new
    @product = Product.new  # 新しい空の商品オブジェクトを作成
  end
end</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><code>Product.new</code>って何ですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">これは「まっさらな商品の箱」を用意するイメージだよ。まだ中身は何も入っていないけど、これからユーザーが情報を入力するための準備をしているんだ。</p>
</div></div>



<h3 class="wp-block-heading">3-2. フォームを作る（new.html.erb）</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;h1&gt;New product&lt;/h1&gt;

&lt;%= form_with model: @product do |form| %&gt;
  &lt;div&gt;
    &lt;%= form.label :name %&gt;        &lt;!-- 「商品名」というラベルを表示 --&gt;
    &lt;%= form.text_field :name %&gt;   &lt;!-- 商品名を入力するテキストボックス --&gt;
  &lt;/div&gt;

  &lt;div&gt;
    &lt;%= form.submit %&gt;             &lt;!-- 「Create Product」ボタンを表示 --&gt;
  &lt;/div&gt;
&lt;% end %&gt;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><code>form_with</code>って何ですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">これはRailsの魔法の道具だよ！<code>form_with</code>は、</p>



<ol class="wp-block-list">
<li>自動的にセキュリティ対策をしてくれる</li>



<li>送信先のURLを自動で決めてくれる</li>



<li>ボタンの文字も自動で決めてくれる</li>
</ol>
</div></div>



<p class="wp-block-paragraph">覚え方：<strong>form_with = フォーム・ウィズ = フォームと一緒に全部やってくれる</strong></p>



<h3 class="wp-block-heading">3-3. createアクション（実際に保存）</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>def create
  # フォームから送られてきた安全なデータだけを使って新しい商品を作成
  @product = Product.new(product_params)
  
  if @product.save  # データベースに保存を試みる
    # 保存成功：商品詳細ページにリダイレクト
    redirect_to @product
  else
    # 保存失敗：エラーメッセージと一緒にフォームを再表示
    render :new, status: :unprocessable_entity
  end
end

private
  # セキュリティのため、許可されたパラメータのみを受け取る
  def product_params
    params.expect(product: [ :name ])  # 商品の名前のみ許可
  end</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><code><strong><span class="marker-under">product_params</span></strong></code>って何ですか？なんで必要なんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">これは「セキュリティガード」だよ！<br>例えば、悪い人が「商品の価格を0円にしちゃおう」とか「管理者権限をもらっちゃおう」みたいな不正なデータを送ってきても、<code>product_params</code>が「あ、それは許可されていません！」と止めてくれるんだ。</p>
</div></div>



<h2 class="wp-block-heading">第4章：Read（読み取り）- 商品を見よう</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">実は、Readはもうできているんだよ！</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>def index
  @products = Product.all  # 全商品を取得（一覧表示用）
end

def show
  @product = Product.find(params[:id])  # 特定の商品を取得（詳細表示用）
end</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">あ、本当ですね！indexとshowがReadなんですね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">その通り！</p>



<ul class="wp-block-list">
<li><strong>index</strong> = 図書館の本棚全体を見る</li>



<li><strong>show</strong> = 特定の1冊を手に取って読む</li>
</ul>



<p class="wp-block-paragraph">こんなイメージだよ！</p>
</div></div>



<h2 class="wp-block-heading">第5章：Update（更新）- 商品を編集しよう</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">更新は作成とよく似ているよ。<br>editとupdateの2つのアクションが必要なんだ。</p>
</div></div>



<h3 class="wp-block-heading">5-1. editアクション（編集フォームを表示）</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>def edit
  @product = Product.find(params[:id])  # 編集したい商品を取得
end</code></pre></div>



<h3 class="wp-block-heading">5-2. updateアクション（実際に更新）</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>def update
  @product = Product.find(params[:id])  # 更新したい商品を取得
  
  if @product.update(product_params)  # 新しいデータで更新を試みる
    # 更新成功：商品詳細ページにリダイレクト
    redirect_to @product
  else
    # 更新失敗：エラーメッセージと一緒に編集フォームを再表示
    render :edit, status: :unprocessable_entity
  end
end</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">createとupdateって似てますね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">違いはこれだけだよ。</p>



<ul class="wp-block-list">
<li><strong>create</strong>: <code>Product.new</code> → <code>save</code>（新しく作って保存）</li>



<li><strong>update</strong>: <code>Product.find</code> → <code>update</code>（既存を見つけて更新）</li>
</ul>
</div></div>



<h2 class="wp-block-heading">第6章：DRY原則で賢くコーディング</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">今のコードを見ると、同じことを何度も書いていることは分かるかな？。まず、改善前のコードを見てみよう！</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>class ProductsController &lt; ApplicationController
  def show
    @product = Product.find(params[:id])  # ←同じコード
  end

  def edit
    @product = Product.find(params[:id])  # ←同じコード
  end

  def update
    @product = Product.find(params[:id])  # ←同じコード
    # 更新処理...
  end

  def destroy
    @product = Product.find(params[:id])  # ←同じコード
    # 削除処理...
  end
end</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">あ、本当ですね！<code>@product = Product.find(params[:id])</code>が4回も書いてある！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうなんだ！これを「DRY原則」で改善しよう！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">DRY原則って何ですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">DRY = <strong>D</strong>on&#8217;t <strong>R</strong>epeat <strong>Y</strong>ourself（同じことを繰り返すな）という意味だよ。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">ということで、<code>before_action</code>を使って、重複するコードをまとめよう！</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>class ProductsController &lt; ApplicationController
  # show, edit, update, destroyアクションの前に自動実行
  before_action :set_product, only: %i[ show edit update destroy ]

  def index
    @products = Product.all  # 全商品を取得
  end

  def show
    # @productは既にset_productで設定済み！
    # Product.find(params[:id])を書く必要がない
  end

  def new
    @product = Product.new  # 新しい商品オブジェクトを作成
  end

  def create
    @product = Product.new(product_params)  # フォームデータから商品を作成
    
    if @product.save  # 保存を試みる
      redirect_to @product  # 成功時は詳細ページへ
    else
      render :new, status: :unprocessable_entity  # 失敗時はフォーム再表示
    end
  end

  def edit
    # @productは既にset_productで設定済み！
    # Product.find(params[:id])を書く必要がない
  end

  def update
    # @productは既にset_productで設定済み！
    if @product.update(product_params)  # 更新を試みる
      redirect_to @product  # 成功時は詳細ページへ
    else
      render :edit, status: :unprocessable_entity  # 失敗時は編集フォーム再表示
    end
  end

  def destroy
    # @productは既にset_productで設定済み！
    @product.destroy           # データベースから削除
    redirect_to products_path  # 商品一覧ページにリダイレクト
  end

  private
    def set_product
      @product = Product.find(params[:id])  # IDから商品を検索
    end

    def product_params
      params.expect(product: [ :name ])  # 許可されたパラメータのみ取得
    end
end</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">わあ、すっきりしました！<br>4回書いていたコードが1回だけになりましたね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうだね！これの何がいいかというと、</p>



<ol class="wp-block-list">
<li><strong>コードが短くなる</strong>: 同じことを何度も書かなくていい</li>



<li><strong>バグが減る</strong>: 修正は1箇所だけでOK</li>



<li><strong>読みやすい</strong>: 何をしているか一目瞭然</li>
</ol>



<p class="wp-block-paragraph">例えば、もし<code>Product.find(params[:id])</code>を<code>Product.find(params[:product_id])</code>に変更したくなったら、改善前は4箇所を修正する必要があったけど、今は1箇所だけでいいんだ！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！修正し忘れでバグが起きることもなくなりますね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">その通り！<code>before_action</code>は「アクションの前に自動で実行される準備係」だと思えばいいよ。</p>
</div></div>



<p class="wp-block-paragraph">覚え方：<strong>before_action = 前もって準備 = アクションの前にお膳立てしてくれる</strong></p>



<p class="wp-block-paragraph">実際の動作はこんな感じです。</p>



<ol class="wp-block-list">
<li>ユーザーが商品詳細ページにアクセス</li>



<li>Railsが「showアクションを実行するよ」と準備</li>



<li><strong>before_action</strong>が「ちょっと待って！まず商品を探してくるね」</li>



<li><code>set_product</code>が実行されて<code>@product</code>に商品が入る</li>



<li>やっと<code>show</code>アクションが実行される</li>
</ol>



<h2 class="wp-block-heading">第7章：パーシャルでビューもDRYに</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">コントローラーがすっきりしたら、今度はビューもDRYにしよう！<br>新規作成と編集で同じフォームを使っているから、パーシャル（部品）として切り出そう。</p>
</div></div>



<h3 class="wp-block-heading">7-1. パーシャルファイル（_form.html.erb）</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;%= form_with model: product do |form| %&gt;
  &lt;div&gt;
    &lt;%= form.label :name %&gt;        &lt;!-- 商品名のラベル --&gt;
    &lt;%= form.text_field :name %&gt;   &lt;!-- 商品名の入力欄 --&gt;
  &lt;/div&gt;

  &lt;div&gt;
    &lt;%= form.submit %&gt;             &lt;!-- 送信ボタン（自動でテキスト設定） --&gt;
  &lt;/div&gt;
&lt;% end %&gt;</code></pre></div>



<h3 class="wp-block-heading">7-2. newビューで使用</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;h1&gt;New product&lt;/h1&gt;

&lt;%= render &quot;form&quot;, product: @product %&gt;  &lt;!-- パーシャルを呼び出し --&gt;
&lt;%= link_to &quot;Cancel&quot;, products_path %&gt;   &lt;!-- キャンセルリンク --&gt;</code></pre></div>



<h3 class="wp-block-heading">7-3. editビューで使用</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;h1&gt;Edit product&lt;/h1&gt;

&lt;%= render &quot;form&quot;, product: @product %&gt;  &lt;!-- 同じパーシャルを使用 --&gt;
&lt;%= link_to &quot;Cancel&quot;, @product %&gt;        &lt;!-- キャンセルリンク --&gt;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">パーシャルって何ですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">パーシャルは「部品」だよ！</p>



<p class="wp-block-paragraph">例えば、LEGOブロックを想像してみて。同じパーツを色んな場所で使い回せるでしょ？パーシャルも同じで、同じビューの部品を色んなページで使い回せるんだ。</p>
</div></div>



<p class="wp-block-paragraph">Point：</p>



<ul class="wp-block-list">
<li><strong>パーシャル = 部品 = 使い回せる画面の部品</strong></li>



<li><strong>ファイル名は_（アンダースコア）で始まる</strong></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">第8章：Delete（削除）- 商品を削除しよう</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">最後は削除機能だ！これが一番シンプルだよ。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>def destroy
  @product.destroy           # 商品をデータベースから削除
  redirect_to products_path  # 商品一覧ページにリダイレクト
end</code></pre></div>



<h3 class="wp-block-heading">削除ボタンの作成（show.html.erb）</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;h1&gt;&lt;%= @product.name %&gt;&lt;/h1&gt;

&lt;%= link_to &quot;Back&quot;, products_path %&gt;           &lt;!-- 戻るリンク --&gt;
&lt;%= link_to &quot;Edit&quot;, edit_product_path(@product) %&gt;  &lt;!-- 編集リンク --&gt;
&lt;%= button_to &quot;Delete&quot;, @product, method: :delete, 
              data: { turbo_confirm: &quot;Are you sure?&quot; } %&gt;  &lt;!-- 削除ボタン --&gt;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><code>turbo_confirm</code>って何ですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">これは「本当に削除していいですか？」という確認ダイアログを表示してくれるんだ。間違って削除ボタンを押しちゃった時の「あー！」を防いでくれる優しい機能だよ。</p>
</div></div>



<p class="wp-block-paragraph">覚え方：<strong>turbo_confirm = ターボ確認 = 高速で確認してくれる</strong></p>



<h2 class="wp-block-heading">第9章：完成したコントローラー</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">さあ、完成したコントローラーを見てみよう！</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>class ProductsController &lt; ApplicationController
  # 指定されたアクションの前に自動実行される準備メソッド
  before_action :set_product, only: %i[ show edit update destroy ]

  # C-R-U-D の R: 全商品を読み取り（一覧表示）
  def index
    @products = Product.all  # 全ての商品をデータベースから取得
  end

  # C-R-U-D の R: 特定商品を読み取り（詳細表示）
  def show
    # @productは既にset_productで設定済み
  end

  # C-R-U-D の C: 新規作成フォームを表示
  def new
    @product = Product.new  # 空の商品オブジェクトを作成
  end

  # C-R-U-D の C: 新しい商品を実際に作成・保存
  def create
    @product = Product.new(product_params)  # 安全なパラメータで商品作成
    
    if @product.save  # データベースへの保存を試みる
      redirect_to @product  # 成功：詳細ページへリダイレクト
    else
      # 失敗：エラーメッセージと共にフォーム再表示
      render :new, status: :unprocessable_entity
    end
  end

  # C-R-U-D の U: 編集フォームを表示
  def edit
    # @productは既にset_productで設定済み
  end

  # C-R-U-D の U: 商品を実際に更新
  def update
    if @product.update(product_params)  # 更新を試みる
      redirect_to @product  # 成功：詳細ページへリダイレクト
    else
      # 失敗：エラーメッセージと共に編集フォーム再表示
      render :edit, status: :unprocessable_entity
    end
  end

  # C-R-U-D の D: 商品を削除
  def destroy
    @product.destroy           # データベースから商品を削除
    redirect_to products_path  # 商品一覧ページへリダイレクト
  end

  private
    # 共通処理：IDから商品を検索して@productに設定
    def set_product
      @product = Product.find(params[:id])
    end

    # セキュリティ：許可されたパラメータのみを取得
    def product_params
      params.expect(product: [ :name ])  # 商品名のみ許可
    end
end</code></pre></div>



<h2 class="wp-block-heading">第10章：まとめ &#8211; CRUDを覚えよう！</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">プロ太先生、ありがとうございました！CRUDがよく分かりました。これでブログシステムも、ECサイトも、SNSも作れそうですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">その通り！CRUDはWebアプリケーションの基本中の基本。これをマスターすれば、どんなアプリでも作れるようになるよ。頑張って練習してね！</p>
</div></div>



<h3 class="wp-block-heading">Railsのルール</h3>



<ol class="wp-block-list">
<li><strong>DRY原則</strong>: 同じコードは書かない → <code>before_action</code>やパーシャルを使う</li>



<li><strong>Strong Parameters</strong>: セキュリティのため、許可されたデータのみ受け取る</li>



<li><strong>エラーハンドリング</strong>: 成功時はリダイレクト、失敗時は再表示</li>
</ol>



<h2 class="wp-block-heading">付録：よく使うRailsのメソッド一覧</h2>



<h3 class="wp-block-heading">コントローラーでよく使うメソッド</h3>



<ul class="wp-block-list">
<li><code>find(id)</code>: IDで1件検索</li>



<li><code>all</code>: 全件取得</li>



<li><code>new</code>: 新しいオブジェクト作成</li>



<li><code>save</code>: データベースに保存</li>



<li><code>update</code>: データベースの更新</li>



<li><code>destroy</code>: データベースから削除</li>



<li><code>redirect_to</code>: 別のページにリダイレクト</li>



<li><code>render</code>: ビューを表示</li>
</ul>



<h3 class="wp-block-heading">ビューでよく使うヘルパー</h3>



<ul class="wp-block-list">
<li><code>link_to</code>: リンクを作成</li>



<li><code>button_to</code>: ボタンを作成</li>



<li><code>form_with</code>: フォームを作成</li>



<li><code>render</code>: パーシャルを呼び出し</li>
</ul>



<p class="wp-block-paragraph">覚えておくと便利だよ！</p>
]]></content:encoded>
					
					<wfw:commentRss>https://oz006.com/rails-crud/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Rails初心者必見！link_toヘルパーで簡単リンク作成</title>
		<link>https://oz006.com/rails-link_to/</link>
					<comments>https://oz006.com/rails-link_to/#respond</comments>
		
		<dc:creator><![CDATA[oz]]></dc:creator>
		<pubDate>Tue, 10 Jun 2025 06:47:24 +0000</pubDate>
				<category><![CDATA[プログラミング]]></category>
		<guid isPermaLink="false">https://oz006.com/?p=713</guid>

					<description><![CDATA[link_toヘルパーの魔法を教えよう！ 基本的な使い方 Railsの規約（Convention）を理解しよう！ Railsが自動で作ってくれるヘルパーメソッド 「オブジェクトを直接渡す魔法！」 Railsの規約を理解し [&#8230;]]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1000" height="1000" src="https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-10-15.46.19-A-clean-modern-image-symbolizing-Ruby-on-Rails-web-development-for-beginners.-The-image-features-a-simplified-Ruby-gemstone-logo-and-abstract-browser.webp" alt="" class="wp-image-714" srcset="https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-10-15.46.19-A-clean-modern-image-symbolizing-Ruby-on-Rails-web-development-for-beginners.-The-image-features-a-simplified-Ruby-gemstone-logo-and-abstract-browser.webp 1000w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-10-15.46.19-A-clean-modern-image-symbolizing-Ruby-on-Rails-web-development-for-beginners.-The-image-features-a-simplified-Ruby-gemstone-logo-and-abstract-browser-300x300.webp 300w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-10-15.46.19-A-clean-modern-image-symbolizing-Ruby-on-Rails-web-development-for-beginners.-The-image-features-a-simplified-Ruby-gemstone-logo-and-abstract-browser-150x150.webp 150w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-10-15.46.19-A-clean-modern-image-symbolizing-Ruby-on-Rails-web-development-for-beginners.-The-image-features-a-simplified-Ruby-gemstone-logo-and-abstract-browser-768x768.webp 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-12 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ02.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">プロ太先生、RailsでHTMLでリンクを作るのって面倒くさいです..</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;!-- 商品一覧ページのコード --&gt;
&lt;h1&gt;Products&lt;/h1&gt;

&lt;div id=&quot;products&quot;&gt;
  &lt;% @products.each do |product| %&gt;
    &lt;div&gt;
      &lt;!-- 手動でaタグを書いている --&gt;
      &lt;a href=&quot;/products/&lt;%= product.id %&gt;&quot;&gt;
        &lt;%= product.name %&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;% end %&gt;
&lt;/div&gt;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">確かにこの書き方だと、<code>&lt;a></code>タグを手動で書いて、さらに<code>product.id</code>を埋め込んで&#8230;と面倒ですよね。<br><span class="marker-under">実は、Railsには<strong>もっと簡単な方法</strong>があるんです</span>！</p>
</div></div>



<h2 class="wp-block-heading">link_toヘルパーの魔法を教えよう！</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">Railsには<code>link_to</code>という<strong>ヘルパーメソッド</strong>があります。これを使うと、リンクがとても簡単に作れるんです。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">ヘルパーメソッド？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">簡単に言うと、<strong>よく使う処理を簡単にしてくれる便利な関数</strong>のことです。<code>link_to</code>は<code>&lt;a></code>タグを自動で作ってくれます。</p>
</div></div>



<p class="wp-block-paragraph"><strong>基本的な使い方</strong></p>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># 基本の書き方
link_to &quot;表示する文字&quot;, &quot;リンク先のパス&quot;

# 例
link_to &quot;ホームページ&quot;, &quot;/home&quot;
# ↓ これが以下のHTMLに変換される
# &lt;a href=&quot;/home&quot;&gt;ホームページ&lt;/a&gt;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">おお！これは便利そうですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">でも、商品の詳細ページのリンクはどう書けばいいんですか？商品のIDを使わないといけないですよね？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">実は、Railsにはさらに<strong>すごい機能</strong>があるんです。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;!-- 従来の書き方 --&gt;
&lt;a href=&quot;/products/&lt;%= product.id %&gt;&quot;&gt;
  &lt;%= product.name %&gt;
&lt;/a&gt;

&lt;!-- link_toを使った新しい書き方 --&gt;
&lt;%= link_to product.name, product %&gt;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">え？<code>product</code>だけ？IDは？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そこがRailsの<strong>魔法</strong>なんです！<strong><span class="marker-under">Railsは賢いので、<code>product</code>オブジェクトを渡すだけで、自動的に適切なパスを作ってくれる</span></strong>んです。</p>
</div></div>



<h2 class="wp-block-heading">Railsの規約（Convention）を理解しよう！</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">まず、<code>bin/rails routes</code>というコマンドを実行してみてください。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>Prefix Verb   URI Pattern                     Controller#Action
products GET    /products(.:format)            products#index
product GET    /products/:id(.:format)         products#show</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">これは何ですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">これは<strong>ルーティング情報</strong>です。注目してほしいのは<strong>Prefix列</strong>の<code>products</code>と<code>product</code>です。</p>
</div></div>



<h3 class="wp-block-heading">Railsが自動で作ってくれるヘルパーメソッド</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># Prefix が &quot;products&quot; の場合
products_path  # =&gt; &quot;/products&quot; を生成
products_url   # =&gt; &quot;http://localhost:3000/products&quot; を生成

# Prefix が &quot;product&quot; の場合
product_path(1)  # =&gt; &quot;/products/1&quot; を生成
product_url(1)   # =&gt; &quot;http://localhost:3000/products/1&quot; を生成</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！<code>product_path</code>を使えばいいんですね！</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;%= link_to product.name, product_path(product.id) %&gt;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">その通り！でも、実はもっと簡単にできるんです。</p>
</div></div>



<h2 class="wp-block-heading">「オブジェクトを直接渡す魔法！」</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">Railsでは、オブジェクトを直接渡すことができます。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;!-- この書き方 --&gt;
&lt;%= link_to product.name, product %&gt;

&lt;!-- ↓ Railsが自動でこう変換してくれる --&gt;
&lt;%= link_to product.name, product_path(product.id) %&gt;

&lt;!-- ↓ さらに具体的には --&gt;
&lt;%= link_to product.name, &quot;/products/#{product.id}&quot; %&gt;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">すごい！なんで<code>product</code>だけでパスが分かるんですか？</p>
</div></div>



<h3 class="wp-block-heading">Railsの規約を理解しよう</h3>



<ol class="wp-block-list">
<li><code>Product</code>モデルのオブジェクトを渡すと</li>



<li>自動的に<code>product_path(product.id)</code>に変換される</li>



<li>つまり<code>/products/1</code>のようなパスが生成される</li>
</ol>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># 例：productのIDが5の場合
product = Product.find(5)
link_to product.name, product
# ↓ 自動的にこうなる
# &lt;a href=&quot;/products/5&quot;&gt;商品名&lt;/a&gt;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">規約って何ですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><strong>「決まったルール」</strong>のことです。<span class="marker-under"><strong>Railsでは「こう書いたら、こう動く」というルール</strong></span>がたくさんあります。このルールに従うことで、コードがとても短く、読みやすくなるんです。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">じゃあ、実際に書き換えてみますね！</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;!-- 【Before】従来の書き方 --&gt;
&lt;h1&gt;Products&lt;/h1&gt;

&lt;div id=&quot;products&quot;&gt;
  &lt;% @products.each do |product| %&gt;
    &lt;div&gt;
      &lt;!-- 手動でaタグとパスを書いている --&gt;
      &lt;a href=&quot;/products/&lt;%= product.id %&gt;&quot;&gt;
        &lt;%= product.name %&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;% end %&gt;
&lt;/div&gt;</code></pre></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;!-- 【After】link_toを使った書き方 --&gt;
&lt;h1&gt;Products&lt;/h1&gt;

&lt;div id=&quot;products&quot;&gt;
  &lt;% @products.each do |product| %&gt;
    &lt;div&gt;
      &lt;!-- link_toでスッキリ！ --&gt;
      &lt;%= link_to product.name, product %&gt;
    &lt;/div&gt;
  &lt;% end %&gt;
&lt;/div&gt;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">素晴らしい！コードがとてもスッキリしましたね！</p>
</div></div>



<h2 class="wp-block-heading">他の例も見てみよう！</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">他のモデルでも同じように使えますよ。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;!-- ユーザー詳細ページへのリンク --&gt;
&lt;%= link_to user.name, user %&gt;
&lt;!-- 生成される：&lt;a href=&quot;/users/5&quot;&gt;田中太郎&lt;/a&gt; --&gt;

&lt;!-- 記事詳細ページへのリンク --&gt;
&lt;%= link_to article.title, article %&gt;
&lt;!-- 生成される：&lt;a href=&quot;/articles/10&quot;&gt;記事のタイトル&lt;/a&gt; --&gt;

&lt;!-- カテゴリー詳細ページへのリンク --&gt;
&lt;%= link_to category.name, category %&gt;
&lt;!-- 生成される：&lt;a href=&quot;/categories/3&quot;&gt;技術&lt;/a&gt; --&gt;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">すごい！どのモデルでも同じように使えるんですね！</p>
</div></div>



<h2 class="wp-block-heading">_pathと_urlの違いは？</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">さっき、<code>product_path</code>と<code>product_url</code>って出てきましたが、何が違うんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">普通のWebページでは<code>_path</code>を使います。<code>_url</code>は<strong>メール</strong>や<strong>外部サイト</strong>に送るリンクで使います。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># _path：相対パス（ドメインなし）
product_path(1)  # =&gt; &quot;/products/1&quot;

# _url：絶対URL（ドメインあり）
product_url(1)   # =&gt; &quot;http://localhost:3000/products/1&quot;</code></pre></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># Webページ内のリンク（普通はこっち）
link_to &quot;商品詳細&quot;, product_path(product)

# メールで送るリンク（完全なURLが必要）
link_to &quot;商品詳細&quot;, product_url(product)</code></pre></div>



<h2 class="wp-block-heading">まとめ：link_toでRailsライフが快適に！</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">今日学んだことをまとめましょう！</p>
</div></div>



<h3 class="wp-block-heading">今日のポイント</h3>



<ol class="wp-block-list">
<li>**<code>link_to</code>**は<code>&lt;a></code>タグを自動で作ってくれる便利なヘルパー</li>



<li><strong>オブジェクトを直接渡す</strong>ことで、パスが自動生成される</li>



<li><strong>Railsの規約</strong>により、コードが短く、読みやすくなる</li>



<li>**<code>_path</code><strong>は相対パス、</strong><code>_url</code>**は絶対URL</li>
</ol>



<p class="wp-block-paragraph"><strong>Before → After比較</strong></p>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>&lt;!-- 【Before】面倒な書き方 --&gt;
&lt;a href=&quot;/products/&lt;%= product.id %&gt;&quot;&gt;
  &lt;%= product.name %&gt;
&lt;/a&gt;

&lt;!-- 【After】スッキリした書き方 --&gt;
&lt;%= link_to product.name, product %&gt;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">link_toを使うと、こんなに簡単になるんですね！Railsってすごいです！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">その通り！Railsは「Convention over Configuration（設定より規約）」という哲学があります。決まったルールに従うことで、少ないコードで多くのことができるようになるんです。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">今度から積極的に<code>link_to</code>を使ってみます！ありがとうございました！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">どういたしまして！Railsの世界はまだまだ奥が深いので、一緒に頑張って学んでいきましょう！</p>
</div></div>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://oz006.com/rails-link_to/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>LaravelとRailsのクエリ書き方比較 &#8211; データベース操作をマスターしよう！</title>
		<link>https://oz006.com/laravel-rails-querie/</link>
					<comments>https://oz006.com/laravel-rails-querie/#respond</comments>
		
		<dc:creator><![CDATA[oz]]></dc:creator>
		<pubDate>Tue, 10 Jun 2025 04:42:13 +0000</pubDate>
				<category><![CDATA[プログラミング]]></category>
		<guid isPermaLink="false">https://oz006.com/?p=708</guid>

					<description><![CDATA[1.基本的なデータ取得 全データを取得する場合 Laravel（PHP）の場合 Rails（Ruby）の場合 特定の条件でデータを取得する場合 Laravel Rails 2.よく使うクエリパターン 並び替え（ORDER [&#8230;]]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1000" height="1000" src="https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-10-13.40.39-An-infographic-style-image-comparing-Laravel-and-Ruby-on-Rails-query-syntax.-On-the-left-side-labeled-Laravel-PHP-show-code-snippets-using-Eloqu.webp" alt="" class="wp-image-711" srcset="https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-10-13.40.39-An-infographic-style-image-comparing-Laravel-and-Ruby-on-Rails-query-syntax.-On-the-left-side-labeled-Laravel-PHP-show-code-snippets-using-Eloqu.webp 1000w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-10-13.40.39-An-infographic-style-image-comparing-Laravel-and-Ruby-on-Rails-query-syntax.-On-the-left-side-labeled-Laravel-PHP-show-code-snippets-using-Eloqu-300x300.webp 300w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-10-13.40.39-An-infographic-style-image-comparing-Laravel-and-Ruby-on-Rails-query-syntax.-On-the-left-side-labeled-Laravel-PHP-show-code-snippets-using-Eloqu-150x150.webp 150w, https://oz006.com/wp-content/uploads/2025/06/DALL·E-2025-06-10-13.40.39-An-infographic-style-image-comparing-Laravel-and-Ruby-on-Rails-query-syntax.-On-the-left-side-labeled-Laravel-PHP-show-code-snippets-using-Eloqu-768x768.webp 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-12 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ02.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">プロ太先生、こんにちは！最近LaravelとRailsを両方勉強してるんですが、<strong><span class="marker-under">データベースからデータを取得する書き方が似てるようで違っていて混乱</span></strong>してます…</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">確かに両方ともWebフレームワークだから似てる部分もあるけど、書き方には特徴があるんだ。今日は具体例を使って比較してみよう！</p>
</div></div>



<h2 class="wp-block-heading">1.基本的なデータ取得</h2>



<h3 class="wp-block-heading">全データを取得する場合</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">まずは一番基本的な「全部のデータを取る」方法から教えてください！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">OK！では、例として「users」テーブルから全ユーザーを取得してみよう。</p>
</div></div>



<h4 class="wp-block-heading">Laravel（PHP）の場合</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-php" data-lang="PHP"><code>// Eloquent ORMを使用
$users = User::all();

// または Query Builder を使用
$users = DB::table(&#39;users&#39;)-&gt;get();</code></pre></div>



<h4 class="wp-block-heading">Rails（Ruby）の場合</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># Active Recordを使用
users = User.all</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">おぉ！！<span class="marker-under">Railsの方がすごくシンプル</span>ですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><strong><span class="marker-under">Railsは「設定より規約」という思想</span></strong>で、シンプルに書けるように設計されているからね。LaravelはPHPの文法に従うから、少し記号が多くなるんだ。</p>
</div></div>



<h3 class="wp-block-heading">特定の条件でデータを取得する場合</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">次は条件を指定してデータを取得してみよう。「年齢が20歳以上のユーザー」を探す場合はこうなるよ。</p>
</div></div>



<h4 class="wp-block-heading">Laravel</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-php" data-lang="PHP"><code>// Eloquent ORM
$users = User::where(&#39;age&#39;, &#39;&gt;=&#39;, 20)-&gt;get();

// Query Builder
$users = DB::table(&#39;users&#39;)
            -&gt;where(&#39;age&#39;, &#39;&gt;=&#39;, 20)
            -&gt;get();</code></pre></div>



<h4 class="wp-block-heading">Rails</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># Active Record
users = User.where(&#39;age &gt;= ?&#39;, 20)
# または
users = User.where(age: 20..)  # Ruby 2.7以降の書き方</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！<span class="marker-under"><strong>どちらも <code>where</code> を使う</strong></span>んですね。<br>でもちょっと書き方が違う&#8230;</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">Laravelは3つの引数（カラム名、演算子、値）を分けて書くのが基本。Railsは条件を文字列やハッシュで書くことが多いんだ。</p>
</div></div>



<h2 class="wp-block-heading">2.よく使うクエリパターン</h2>



<h3 class="wp-block-heading">並び替え（ORDER BY）</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">データを並び替えたい時はどう書くんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">OK！では、「作成日時が新しい順」で並べてみよう。</p>
</div></div>



<h4 class="wp-block-heading">Laravel</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-php" data-lang="PHP"><code>// 新しい順（降順）
$users = User::orderBy(&#39;created_at&#39;, &#39;desc&#39;)-&gt;get();

// 古い順（昇順）
$users = User::orderBy(&#39;created_at&#39;, &#39;asc&#39;)-&gt;get();
// または &#39;asc&#39; は省略可能
$users = User::orderBy(&#39;created_at&#39;)-&gt;get();</code></pre></div>



<h4 class="wp-block-heading">Rails</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># Active Record
users = User.where(&#39;age &gt;= ?&#39;, 20)
# または
users = User.where(age: 20..)  # Ruby 2.7以降の書き方</code></pre></div>



<p class="wp-block-paragraph">ちなみに、descが降順、ascが昇順の覚え方は、<br><br><strong>ascは「a」から始まって「c」で終わるので「a、b、c…」ということで昇順。 descは「d」から始まって「c」で終わるので「d、c、b、a…」ということで降順。　と覚えると覚えやすいぞ！</strong></p>



<h3 class="wp-block-heading">件数制限（LIMIT）</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">では、今度は「最新の注文を1件だけ取得」する場合を見てみよう！</p>
</div></div>



<h4 class="wp-block-heading">Laravel</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-php" data-lang="PHP"><code>// 最新の注文を1件取得
$latest_order = DB::table(&#39;orders&#39;)
                  -&gt;select(&#39;customer_id&#39;)           // customer_idカラムのみ選択
                  -&gt;orderBy(&#39;created_at&#39;, &#39;desc&#39;)   // 作成日時の新しい順に並び替え
                  -&gt;limit(1)                        // 1件だけ取得
                  -&gt;first();                        // 結果を1つのオブジェクトとして取得</code></pre></div>



<h4 class="wp-block-heading">Rails</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># 最新の注文を1件取得
latest_order = Order.select(:customer_id)    # customer_idカラムのみ選択
                   .order(created_at: :desc) # 作成日時の新しい順に並び替え
                   .limit(1)                 # 1件だけ取得
                   .first                    # 結果を1つのオブジェクトとして取得</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！両方とも似たような流れで書けるんですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><span class="marker-under">「メソッドチェーン」という方法で、処理を順番につなげて書けるから読みやすい</span>よね。</p>
</div></div>



<h2 class="wp-block-heading">3.複数条件の組み合わせ</h2>



<h3 class="wp-block-heading">AND条件</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">複数の条件を組み合わせたい時はどうするんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">じゃあ、例えば「年齢が20歳以上かつ性別が男性のユーザー」を探してみよう。</p>
</div></div>



<h4 class="wp-block-heading">Laravel</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-php" data-lang="PHP"><code>$users = User::where(&#39;age&#39;, &#39;&gt;=&#39;, 20)
             -&gt;where(&#39;gender&#39;, &#39;male&#39;)    // AND条件は where を続けて書く
             -&gt;get();</code></pre></div>



<h4 class="wp-block-heading">Rails</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>users = User.where(&#39;age &gt;= ? AND gender = ?&#39;, 20, &#39;male&#39;)
# または
users = User.where(age: 20.., gender: &#39;male&#39;)</code></pre></div>



<h3 class="wp-block-heading">OR条件</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">では、次は、OR条件（「または」の条件）も見てみよう。「東京または大阪に住んでいるユーザー」の場合だね。</p>
</div></div>



<h4 class="wp-block-heading">Laravel</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-php" data-lang="PHP"><code>$users = User::where(&#39;city&#39;, &#39;Tokyo&#39;)
             -&gt;orWhere(&#39;city&#39;, &#39;Osaka&#39;)   // OR条件は orWhere を使う
             -&gt;get();</code></pre></div>



<h4 class="wp-block-heading">Rails</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>users = User.where(&#39;city = ? OR city = ?&#39;, &#39;Tokyo&#39;, &#39;Osaka&#39;)
# または
users = User.where(city: [&#39;Tokyo&#39;, &#39;Osaka&#39;])  # 配列を使うとIN句になる</code></pre></div>



<h2 class="wp-block-heading">4.集計系の操作</h2>



<h3 class="wp-block-heading">COUNT（件数を数える）</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">データの件数だけ知りたい時はどうするんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">countメソッドを使うんだ！「20歳以上のユーザー数」を数えてみよう。</p>
</div></div>



<h4 class="wp-block-heading">Laravel</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-php" data-lang="PHP"><code>$count = User::where(&#39;age&#39;, &#39;&gt;=&#39;, 20)-&gt;count();
echo &quot;20歳以上のユーザーは{$count}人です&quot;;</code></pre></div>



<h4 class="wp-block-heading">Rails</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>count = User.where(&#39;age &gt;= ?&#39;, 20).count
puts &quot;20歳以上のユーザーは#{count}人です&quot;</code></pre></div>



<h3 class="wp-block-heading">その他の集計</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">他にも色々な集計ができるよ。</p>
</div></div>



<h4 class="wp-block-heading">Laravel</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-php" data-lang="PHP"><code>// 合計（SUM）
$total_age = User::sum(&#39;age&#39;);

// 平均（AVG）
$average_age = User::avg(&#39;age&#39;);

// 最大値（MAX）
$max_age = User::max(&#39;age&#39;);

// 最小値（MIN）
$min_age = User::min(&#39;age&#39;);</code></pre></div>



<h4 class="wp-block-heading">Rails</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># 合計（SUM）
total_age = User.sum(:age)

# 平均（AVG）
average_age = User.average(:age)

# 最大値（MAX）
max_age = User.maximum(:age)

# 最小値（MIN）
min_age = User.minimum(:age)</code></pre></div>



<h2 class="wp-block-heading">5.JOIN（テーブル結合）</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">複数のテーブルを組み合わせて使いたい時はどうするんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">JOINという機能を使うんだ！例えば「ユーザーとその注文履歴」を一緒に取得してみよう。</p>
</div></div>



<h4 class="wp-block-heading">Laravel</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-php" data-lang="PHP"><code>// INNER JOIN
$users_with_orders = User::join(&#39;orders&#39;, &#39;users.id&#39;, &#39;=&#39;, &#39;orders.user_id&#39;)
                         -&gt;select(&#39;users.name&#39;, &#39;orders.total_amount&#39;)
                         -&gt;get();

// LEFT JOIN
$all_users = User::leftJoin(&#39;orders&#39;, &#39;users.id&#39;, &#39;=&#39;, &#39;orders.user_id&#39;)
                 -&gt;select(&#39;users.name&#39;, &#39;orders.total_amount&#39;)
                 -&gt;get();</code></pre></div>



<h4 class="wp-block-heading">Rails</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code># INNER JOIN
users_with_orders = User.joins(:orders)
                        .select(&#39;users.name, orders.total_amount&#39;)

# LEFT JOIN
all_users = User.left_joins(:orders)
                .select(&#39;users.name, orders.total_amount&#39;)</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">Railsの方はシンボル（:orders）を使うんですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そう！Railsはモデル間の関連（association）を事前に定義しておけば、シンプルに書けるんだ。Laravelも同様の機能があるけど、今回は基本的なクエリビルダーの書き方を紹介したよ。</p>
</div></div>



<h2 class="wp-block-heading">6.グループ化（GROUP BY）</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">最後にグループ化を見てみよう。「各都市のユーザー数」を調べる場合だね。</p>
</div></div>



<h4 class="wp-block-heading">Laravel</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-php" data-lang="PHP"><code>$city_counts = User::select(&#39;city&#39;, DB::raw(&#39;COUNT(*) as user_count&#39;))
                   -&gt;groupBy(&#39;city&#39;)
                   -&gt;get();</code></pre></div>



<h4 class="wp-block-heading">Rails</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ruby" data-lang="Ruby"><code>city_counts = User.select(:city, &#39;COUNT(*) as user_count&#39;)
                  .group(:city)</code></pre></div>



<h2 class="wp-block-heading">まとめ</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">ありがとうございました！だいぶ整理できました。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">最後に重要な共通点のポイントをまとめておこう。</p>
</div></div>



<h3 class="wp-block-heading">共通点</h3>



<ul class="wp-block-list">
<li>どちらもメソッドチェーンでクエリを構築</li>



<li>基本的なCRUD操作は似たような書き方</li>



<li>ORMを使ってデータベース操作を簡単に</li>
</ul>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">これで両方使い分けられそうです！ありがとうございました！！</p>
</div></div>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://oz006.com/laravel-rails-querie/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>ユニオン型とインターセクション型を分かりやすく解説</title>
		<link>https://oz006.com/union-intersection-type/</link>
					<comments>https://oz006.com/union-intersection-type/#respond</comments>
		
		<dc:creator><![CDATA[oz]]></dc:creator>
		<pubDate>Sun, 08 Jun 2025 13:14:53 +0000</pubDate>
				<category><![CDATA[プログラミング]]></category>
		<guid isPermaLink="false">https://oz006.com/?p=704</guid>

					<description><![CDATA[1.ユニオン型（Union Types）とは？ 1.1 リテラル型とユニオン型の組み合わせ 1.2 オブジェクト型でのユニオン型 2.インターセクション型（Intersection Types）とは？ 2.1 プロパティ [&#8230;]]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1000" height="1000" src="https://oz006.com/wp-content/uploads/2025/06/image-2.jpg" alt="" class="wp-image-705" srcset="https://oz006.com/wp-content/uploads/2025/06/image-2.jpg 1000w, https://oz006.com/wp-content/uploads/2025/06/image-2-300x300.jpg 300w, https://oz006.com/wp-content/uploads/2025/06/image-2-150x150.jpg 150w, https://oz006.com/wp-content/uploads/2025/06/image-2-768x768.jpg 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">プロ太先生、TypeScriptって既存の型を組み合わせて新しい型を作れるって聞いたんですが、どういうことですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">TypeScriptでは型を組み合わせて、より柔軟で実用的な型を作ることができるんだ。今日は<strong><span class="marker-under">『ユニオン型』と『インターセクション型』という2つの重要な型合成方法</span></strong>を教えよう。</p>
</div></div>



<h2 class="wp-block-heading">1.ユニオン型（Union Types）とは？</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">まずはユニオン型から説明しよう。<strong><span class="marker-under">ユニオン型は『AまたはB』という意味</span></strong>で、<span class="marker-under"><strong>複数の型のうちどれか一つを受け入れる型</strong></span>なんだ。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">『または』ですか？具体例で教えてください！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">例えば、<strong>ユーザーIDが数値でも文字列でも受け入れたい場合</strong>を考えてみよう。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ts" data-lang="TypeScript"><code>// ユニオン型の基本例
let userId: number | string;  // number型 または string型を受け入れる

// 数値を代入
userId = 12345;
console.log(userId); // 12345

// 文字列を代入
userId = &quot;user-abc-123&quot;;
console.log(userId); // &quot;user-abc-123&quot;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！<code>|</code>（パイプ記号）で区切って複数の型を指定するんですね。</p>
</div></div>



<h3 class="wp-block-heading">1.1 リテラル型とユニオン型の組み合わせ</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうそう。特に便利なのが、<strong><span class="marker-under">リテラル型とユニオン型を組み合わせる</span></strong>ことなんだ。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ts" data-lang="TypeScript"><code>// 動物の種類を限定する型
type AnimalType = &#39;dog&#39; | &#39;cat&#39; | &#39;rabbit&#39; | &#39;hamster&#39;;

let myPet: AnimalType;

// 正しい値の代入
myPet = &#39;dog&#39;;     // OK
myPet = &#39;cat&#39;;     // OK

// 間違った値を代入しようとするとエラー
// myPet = &#39;elephant&#39;; // エラー: Type &#39;&quot;elephant&quot;&#39; is not assignable to type &#39;AnimalType&#39;

// 関数での活用例
function feedAnimal(animal: AnimalType): string {
    switch (animal) {
        case &#39;dog&#39;:
            return &#39;ドッグフードをあげました&#39;;
        case &#39;cat&#39;:
            return &#39;キャットフードをあげました&#39;;
        case &#39;rabbit&#39;:
            return &#39;にんじんをあげました&#39;;
        case &#39;hamster&#39;:
            return &#39;ひまわりの種をあげました&#39;;
        default:
            return &#39;不明な動物です&#39;;
    }
}

console.log(feedAnimal(&#39;dog&#39;)); // &#39;ドッグフードをあげました&#39;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">これは便利ですね！決まった選択肢の中からしか選べないようにできるんですね。</p>
</div></div>



<h3 class="wp-block-heading">1.2 オブジェクト型でのユニオン型</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">オブジェクト型でもユニオン型は使えるよ。<br>例えば、<strong>異なる形式のユーザー情報を扱う場合</strong>を見てみよう。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ts" data-lang="TypeScript"><code>// 一般ユーザーの型
interface RegularUser {
    type: &#39;regular&#39;;        // ユーザータイプを識別するフィールド
    name: string;           // ユーザー名
    email: string;          // メールアドレス
}

// 管理者ユーザーの型
interface AdminUser {
    type: &#39;admin&#39;;          // ユーザータイプを識別するフィールド
    name: string;           // ユーザー名
    permissions: string[];  // 権限のリスト
}

// ゲストユーザーの型
interface GuestUser {
    type: &#39;guest&#39;;          // ユーザータイプを識別するフィールド
    sessionId: string;      // セッションID
}

// ユニオン型でまとめる
type User = RegularUser | AdminUser | GuestUser;

// 使用例
function greetUser(user: User): string {
    switch (user.type) {
        case &#39;regular&#39;:
            return `こんにちは、${user.name}さん！新着メールは${user.email}に送信されます。`;
        case &#39;admin&#39;:
            return `管理者の${user.name}さん、ようこそ！権限: ${user.permissions.join(&#39;, &#39;)}`;
        case &#39;guest&#39;:
            return `ゲストユーザーさん、ようこそ！セッション: ${user.sessionId}`;
        default:
            return &#39;不明なユーザーです&#39;;
    }
}

// テスト用のデータ
const regularUser: RegularUser = {
    type: &#39;regular&#39;,
    name: &#39;田中太郎&#39;,
    email: &#39;tanaka@example.com&#39;
};

const adminUser: AdminUser = {
    type: &#39;admin&#39;,
    name: &#39;管理者&#39;,
    permissions: [&#39;read&#39;, &#39;write&#39;, &#39;delete&#39;]
};

console.log(greetUser(regularUser)); // こんにちは、田中太郎さん！新着メールは...
console.log(greetUser(adminUser));   // 管理者の管理者さん、ようこそ！権限: ...</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">すごい！同じような構造だけど、少し違うオブジェクトをまとめて扱えるんですね。</p>
</div></div>



<h2 class="wp-block-heading">2.インターセクション型（Intersection Types）とは？</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">次はインターセクション型だ。<strong><span class="marker-under">ユニオン型が『AまたはB』だったのに対して、インターセクション型は『AかつB』という意味</span></strong>なんだ。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">『かつ』ですか？どういう時に使うんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">主にオブジェクト型を組み合わせて、より複雑な型を作る時に使うんだ。例を見てみよう。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ts" data-lang="TypeScript"><code>// 基本情報の型
interface PersonalInfo {
    name: string;      // 名前
    age: number;       // 年齢
}

// 連絡先情報の型
interface ContactInfo {
    email: string;     // メールアドレス
    phone: string;     // 電話番号
}

// 住所情報の型
interface AddressInfo {
    address: string;   // 住所
    zipCode: string;   // 郵便番号
}

// インターセクション型で全ての情報を組み合わせ
type CompleteUserInfo = PersonalInfo & ContactInfo & AddressInfo;

// 使用例
const user: CompleteUserInfo = {
    // PersonalInfo のプロパティ
    name: &#39;山田花子&#39;,
    age: 25,
    // ContactInfo のプロパティ
    email: &#39;yamada@example.com&#39;,
    phone: &#39;090-1234-5678&#39;,
    // AddressInfo のプロパティ
    address: &#39;東京都渋谷区1-2-3&#39;,
    zipCode: &#39;150-0001&#39;
};

// 全ての情報を表示する関数
function displayUserInfo(user: CompleteUserInfo): void {
    console.log(`名前: ${user.name}`);
    console.log(`年齢: ${user.age}歳`);
    console.log(`メール: ${user.email}`);
    console.log(`電話: ${user.phone}`);
    console.log(`住所: ${user.address} (〒${user.zipCode})`);
}

displayUserInfo(user);</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！別々に定義した型を<code>&amp;</code>で繋げて、全部の条件を満たす型を作れるんですね。</p>
</div></div>



<h3 class="wp-block-heading">2.1 プロパティが重複した場合</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">いい理解だね。ただし、同じプロパティ名がある場合は少し複雑になるよ。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ts" data-lang="TypeScript"><code>// 型Aの定義
interface TypeA {
    id: number;        // 数値のID
    name: string;      // 名前
    optional?: string; // 省略可能なプロパティ
}

// 型Bの定義
interface TypeB {
    id: string;        // 文字列のID（TypeAと型が異なる）
    email: string;     // メールアドレス
}

// 型Cの定義
interface TypeC {
    name: string;      // 名前（TypeAと同じ型）
    optional: string;  // 必須プロパティ（TypeAでは省略可能）
    phone: string;     // 電話番号
}

// TypeAとTypeBのインターセクション
type AandB = TypeA & TypeB;
// この場合、idプロパティは number & string となり、
// 実際には never型になる（数値かつ文字列は存在しないため）

// TypeAとTypeCのインターセクション
type AandC = TypeA & TypeC;
// この場合は以下のような型になる：
// {
//   id: number;
//   name: string;        // 同じ型なので問題なし
//   optional: string;    // 必須側が優先される
//   email: string;
//   phone: string;
// }

// 実際に使える例
const validUser: AandC = {
    id: 123,
    name: &#39;佐藤次郎&#39;,
    optional: &#39;追加情報&#39;,  // 必須になる
    phone: &#39;080-9876-5432&#39;
};

console.log(validUser);</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">同じプロパティ名でも型が違うと<code>never</code>になっちゃうんですね。気をつけないと！</p>
</div></div>



<h3 class="wp-block-heading">2.2 プリミティブ型でのインターセクション</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうなんだ。実際、プリミティブ型でインターセクションを試すとどうなるか見てみよう。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ts" data-lang="TypeScript"><code>// プリミティブ型のインターセクション
type NumberAndString = number & string;  // これは never型になる
type StringAndBoolean = string & boolean; // これも never型になる

// never型の変数を作ってみる
let impossible: NumberAndString;

// どんな値も代入できない
// impossible = 123;      // エラー: Type &#39;number&#39; is not assignable to type &#39;never&#39;
// impossible = &quot;hello&quot;;  // エラー: Type &#39;string&#39; is not assignable to type &#39;never&#39;
// impossible = true;     // エラー: Type &#39;boolean&#39; is not assignable to type &#39;never&#39;

console.log(&#39;プリミティブ型のインターセクションは実用的ではありません&#39;);</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">プリミティブ型では意味がないんですね。オブジェクト型で使うのが基本ということですか。</p>
</div></div>



<h2 class="wp-block-heading">3.実践的な使い方の比較</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">最後に、インターフェースの継承とインターセクション型の違いも見てみよう。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-ts" data-lang="TypeScript"><code>// インターフェースの継承を使った場合
interface BaseUser {
    id: number;
    name: string;
}

interface ExtendedUser extends BaseUser {
    email: string;
    createdAt: Date;
}

// インターセクション型を使った場合
type BaseUserType = {
    id: number;
    name: string;
};

type ExtendedUserType = BaseUserType & {
    email: string;
    createdAt: Date;
};

// どちらも同じような結果になる
const user1: ExtendedUser = {
    id: 1,
    name: &#39;鈴木一郎&#39;,
    email: &#39;suzuki@example.com&#39;,
    createdAt: new Date()
};

const user2: ExtendedUserType = {
    id: 2,
    name: &#39;高橋二郎&#39;,
    email: &#39;takahashi@example.com&#39;,
    createdAt: new Date()
};

// 実用例：APIレスポンスの型を組み合わせる
type ApiResponse&lt;T&gt; = {
    success: boolean;
    message: string;
};

type UserData = {
    userId: number;
    username: string;
};

// ユニオン型とインターセクション型を組み合わせ
type UserApiResponse = ApiResponse&lt;UserData&gt; & {
    data: UserData | null;  // 成功時はUserData、失敗時はnull
};

const successResponse: UserApiResponse = {
    success: true,
    message: &#39;ユーザー情報を取得しました&#39;,
    data: {
        userId: 100,
        username: &#39;testuser&#39;
    }
};

const errorResponse: UserApiResponse = {
    success: false,
    message: &#39;ユーザーが見つかりません&#39;,
    data: null
};</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！継承でできることはインターセクション型でもできるんですね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうだね。ただし、エラーの出方に違いがある場合もあるから、プロジェクトの方針に合わせて選ぶといいよ。</p>
</div></div>



<h2 class="wp-block-heading">まとめ</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">今日学んだことをまとめてみよう！</p>
</div></div>



<h3 class="wp-block-heading">ユニオン型（<code>A | B</code>）</h3>



<ul class="wp-block-list">
<li>「AまたはB」の意味</li>



<li>複数の型のうちどれか一つを受け入れる</li>



<li>リテラル型と組み合わせると列挙型のように使える</li>



<li>異なる形式のデータを統一的に扱える</li>
</ul>



<h3 class="wp-block-heading">インターセクション型（<code>A &amp; B</code>）</h3>



<ul class="wp-block-list">
<li>「AかつB」の意味</li>



<li>複数の型を組み合わせて新しい型を作る</li>



<li>主にオブジェクト型の合成に使用</li>



<li>同じプロパティでは厳しい方の条件が適用される</li>
</ul>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">TypeScriptの型システムって本当に柔軟なんですね！<br>これで更に安全なコードが書けそうです。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">その通り！型を適切に組み合わせることで、コンパイル時により多くのエラーを捕捉できるようになるよ。実際のプロジェクトでどんどん使ってみてね！</p>
</div></div>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://oz006.com/union-intersection-type/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>実際にGraphQLサーバーを構築してみよう！</title>
		<link>https://oz006.com/graphql-2/</link>
					<comments>https://oz006.com/graphql-2/#respond</comments>
		
		<dc:creator><![CDATA[oz]]></dc:creator>
		<pubDate>Sun, 08 Jun 2025 07:27:42 +0000</pubDate>
				<category><![CDATA[プログラミング]]></category>
		<guid isPermaLink="false">https://oz006.com/?p=702</guid>

					<description><![CDATA[事前準備 最初のGraphQLサーバーを作成 1.必要なライブラリの読み込み ●ApolloServer：GraphQLサーバーを作るためのクラス ●gql：GraphQLスキーマを書くためのテンプレートリテラル関数 ● [&#8230;]]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1000" height="1000" src="https://oz006.com/wp-content/uploads/2025/06/image-1.jpg" alt="" class="wp-image-698" srcset="https://oz006.com/wp-content/uploads/2025/06/image-1.jpg 1000w, https://oz006.com/wp-content/uploads/2025/06/image-1-300x300.jpg 300w, https://oz006.com/wp-content/uploads/2025/06/image-1-150x150.jpg 150w, https://oz006.com/wp-content/uploads/2025/06/image-1-768x768.jpg 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">プロ太先生、前回GraphQLがすごく便利そうだって分かりました！<br>実際に作ってみたいです！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">よし！今日は実際にGraphQLサーバーを作ってみよう。Node.jsとApollo Serverを使うから、まずは環境を準備しよう。</p>
</div></div>



<h2 class="wp-block-heading">事前準備</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">まず、Node.jsがインストールされているか確認しよう。ターミナルで以下のコマンドを実行してみて。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>node --version
npm --version</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">Node.jsは入ってます！バージョンも新しいものでした。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">それじゃあ新しいプロジェクトを作成しよう。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code># 新しいディレクトリを作成
mkdir my-first-graphql
cd my-first-graphql

# package.jsonを作成
npm init -y

# 必要なパッケージをインストール
npm install apollo-server-express express graphql
npm install --save-dev nodemon</code></pre></div>



<h2 class="wp-block-heading">最初のGraphQLサーバーを作成</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">それでは、まず簡単なGraphQLサーバーを作ってみよう。<code>server.js</code>というファイルを作成して、以下のコードを書いてみて。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// server.js
const { ApolloServer, gql } = require(&#39;apollo-server-express&#39;);
const express = require(&#39;express&#39;);

// GraphQLのスキーマを定義（どんなデータがあるかを決める設計図）
const typeDefs = gql`
  # ユーザーという型を定義
  type User {
    id: ID!          # IDは必須項目（!マークで必須を表す）
    name: String!    # 名前は文字列で必須
    email: String!   # メールアドレスも文字列で必須
    age: Int         # 年齢は整数（必須ではない）
  }

  # クエリ（データを取得する処理）を定義
  type Query {
    # すべてのユーザーを取得する
    users: [User!]!  # User型の配列を返す、必須
    
    # 特定のIDのユーザーを取得する
    user(id: ID!): User  # IDを受け取って、Userを返す（見つからない場合はnull）
  }
`;

// サンプルデータ（本来はデータベースから取得）
const sampleUsers = [
  { id: &#39;1&#39;, name: &#39;山田太郎&#39;, email: &#39;yamada@example.com&#39;, age: 25 },
  { id: &#39;2&#39;, name: &#39;田中花子&#39;, email: &#39;tanaka@example.com&#39;, age: 30 },
  { id: &#39;3&#39;, name: &#39;佐藤次郎&#39;, email: &#39;sato@example.com&#39;, age: 22 }
];

// リゾルバー（実際にデータを取得する処理）
const resolvers = {
  Query: {
    // すべてのユーザーを返す関数
    users: () =&gt; {
      console.log(&#39;全ユーザーが要求されました&#39;);
      return sampleUsers;
    },
    
    // 特定のユーザーを返す関数
    user: (parent, args) =&gt; {
      console.log(`ID: ${args.id} のユーザーが要求されました`);
      // 配列から指定されたIDのユーザーを探す
      return sampleUsers.find(user =&gt; user.id === args.id);
    }
  }
};

// サーバーを起動する関数
async function startServer() {
  // Apollo Serverを作成
  const server = new ApolloServer({ 
    typeDefs,    // スキーマ定義
    resolvers    // データ取得処理
  });

  // Expressアプリを作成
  const app = express();
  
  // Apollo Serverを開始
  await server.start();
  
  // ExpressアプリにApollo Serverを統合
  server.applyMiddleware({ app });

  const PORT = 4000;
  
  // サーバーを起動
  app.listen(PORT, () =&gt; {
    console.log(`&#x1f680; GraphQLサーバーが起動しました！`);
    console.log(`&#x1f4cd; GraphQL Playground: http://localhost:${PORT}${server.graphqlPath}`);
  });
}

// サーバーを起動
startServer().catch(error =&gt; {
  console.error(&#39;サーバー起動エラー:&#39;, error);
});</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-12 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ02.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">うわー、結構長いコードですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうだね！実は構造はシンプルなんだ。大きく分けて3つの部分があるよ。</p>
</div></div>



<ol class="wp-block-list">
<li><strong>typeDefs</strong>：「こんなデータがありますよ」という設計図</li>



<li><strong>resolvers</strong>：「実際にデータを取得する処理」</li>



<li><strong>サーバー起動処理</strong>：「サーバーを立ち上げる」</li>
</ol>



<h3 class="wp-block-heading">1.必要なライブラリの読み込み</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// server.js
const { ApolloServer, gql } = require(&#39;apollo-server-express&#39;);
const express = require(&#39;express&#39;);</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">この最初の2行は何をしているんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">これは「分割代入」という書き方だね。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// これは以下と同じ意味
// const apolloServerExpress = require(&#39;apollo-server-express&#39;);
// const ApolloServer = apolloServerExpress.ApolloServer;
// const gql = apolloServerExpress.gql;

const { ApolloServer, gql } = require(&#39;apollo-server-express&#39;);</code></pre></div>



<p class="wp-block-paragraph">●<strong>ApolloServer</strong>：GraphQLサーバーを作るためのクラス <br>●<strong>gql</strong>：GraphQLスキーマを書くためのテンプレートリテラル関数 <br><strong>●express</strong>：WebサーバーのためのNode.jsフレームワーク</p>



<h3 class="wp-block-heading">2.GraphQLスキーマの定義</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// GraphQLのスキーマを定義（どんなデータがあるかを決める設計図）
const typeDefs = gql`
  # ユーザーという型を定義
  type User {
    id: ID!          # IDは必須項目（!マークで必須を表す）
    name: String!    # 名前は文字列で必須
    email: String!   # メールアドレスも文字列で必須
    age: Int         # 年齢は整数（必須ではない）
  }

  # クエリ（データを取得する処理）を定義
  type Query {
    # すべてのユーザーを取得する
    users: [User!]!  # User型の配列を返す、必須
    
    # 特定のIDのユーザーを取得する
    user(id: ID!): User  # IDを受け取って、Userを返す（見つからない場合はnull）
  }
`;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">この<code>gql</code>の部分、変わった書き方ですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">これは「テンプレートリテラル」という書き方だよ。<br>バッククォート（`）で囲むことで、複数行の文字列を書けるんだ。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// 普通の文字列だとこうなる（読みにくい！）
const typeDefs = &quot;type User { id: ID! name: String! }&quot;;

// テンプレートリテラルなら読みやすい
const typeDefs = gql`
  type User {
    id: ID!
    name: String!
  }
`;</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-12 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ02.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><code>[User!]!</code>の部分が分からないです&#8230;</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">GraphQLの型表記だね！詳しく見てみよう</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// 型の表記方法
String     // 文字列（nullの可能性あり）
String!    // 文字列（必須、nullは不可）
[String]   // 文字列の配列（配列自体がnullの可能性あり）
[String!]  // 文字列の配列（配列内の要素はnull不可、配列自体はnullの可能性あり）
[String!]! // 文字列の配列（配列内の要素もnull不可、配列自体もnull不可）

// 具体例
users: [User!]!
// ↑ これは「User型の配列で、配列内にnullは入らず、配列自体もnullではない」という意味</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-12 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ02.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">えぇ！？待ってください！<br>User型の中で<code>age: Int</code>って必須じゃないのに、<br><code>[User!]!</code>って書いて大丈夫なんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">これは多くの人が混乱するポイントなんだ。<br>実は全然問題ないよ。理由を説明するね。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// User型の定義
type User {
  id: ID!      // 必須
  name: String! // 必須
  email: String! // 必須
  age: Int     // オプショナル（nullの可能性あり）
}

// この場合、以下のデータは全て有効なUser型
const validUsers = [
  { id: &quot;1&quot;, name: &quot;山田&quot;, email: &quot;yamada@example.com&quot;, age: 25 },     // ageあり
  { id: &quot;2&quot;, name: &quot;田中&quot;, email: &quot;tanaka@example.com&quot;, age: null },   // ageがnull
  { id: &quot;3&quot;, name: &quot;佐藤&quot;, email: &quot;sato@example.com&quot; }                // ageがundefined
];

// でも、以下は無効（User型ではない）
const invalidData = [
  null,        // これはUser型ではない
  undefined,   // これもUser型ではない
  &quot;文字列&quot;      // これもUser型ではない
];</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">あー！つまり<code>User!</code>は「User型のオブジェクトであることは保証する」けど、「User型の中身のフィールドがnullかどうかは別問題」ってことですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">完璧な理解だ！もう少し具体的に見てみよう！</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// [User!]! の意味を分解すると...

// 1. User! → 「User型のオブジェクトで、nullではない」
//    &#x2705; { id: &quot;1&quot;, name: &quot;山田&quot;, email: &quot;yamada@example.com&quot;, age: 25 }
//    &#x2705; { id: &quot;2&quot;, name: &quot;田中&quot;, email: &quot;tanaka@example.com&quot;, age: null }
//    &#x274c; null
//    &#x274c; undefined

// 2. [User!] → 「User型のオブジェクトの配列で、配列内にnullは含まない」
//    &#x2705; [user1, user2, user3]
//    &#x274c; [user1, null, user3]  // 配列内にnullがある
//    &#x2705; []  // 空配列はOK

// 3. [User!]! → 「上記の配列で、配列自体もnullではない」
//    &#x2705; [user1, user2, user3]
//    &#x2705; []  // 空配列
//    &#x274c; null  // 配列自体がnull</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！「型の保証」と「フィールドの値の保証」は別次元の話なんですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そういうこと！GraphQLでは、こんな風に段階的に型安全性を設計できるんだ！</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// 様々なパターンの例
type Query {
  // パターン1: 配列もUser型も必須
  allUsers: [User!]!        // 必ず配列が返る、中身は必ずUser型
  
  // パターン2: 配列は必須だが、User型はnullの可能性あり
  someUsers: [User]!        // 必ず配列が返る、中身はUser型かnull
  
  // パターン3: 配列自体がnullの可能性あり
  maybeUsers: [User!]       // 配列かnull、配列の場合は中身は必ずUser型
  
  // パターン4: 全てがnullの可能性あり
  optionalUsers: [User]     // 配列かnull、配列の場合は中身もnullの可能性あり
}

// 実際のレスポンス例
{
  &quot;allUsers&quot;: [
    { &quot;id&quot;: &quot;1&quot;, &quot;name&quot;: &quot;山田&quot;, &quot;email&quot;: &quot;yamada@example.com&quot;, &quot;age&quot;: 25 },
    { &quot;id&quot;: &quot;2&quot;, &quot;name&quot;: &quot;田中&quot;, &quot;email&quot;: &quot;tanaka@example.com&quot;, &quot;age&quot;: null }
  ],
  &quot;someUsers&quot;: [
    { &quot;id&quot;: &quot;1&quot;, &quot;name&quot;: &quot;山田&quot;, &quot;email&quot;: &quot;yamada@example.com&quot;, &quot;age&quot;: 25 },
    null,  // これはOK
    { &quot;id&quot;: &quot;3&quot;, &quot;name&quot;: &quot;佐藤&quot;, &quot;email&quot;: &quot;sato@example.com&quot;, &quot;age&quot;: null }
  ],
  &quot;maybeUsers&quot;: null,  // 配列自体がnullでもOK
  &quot;optionalUsers&quot;: [
    { &quot;id&quot;: &quot;1&quot;, &quot;name&quot;: &quot;山田&quot;, &quot;email&quot;: &quot;yamada@example.com&quot;, &quot;age&quot;: 25 },
    null   // これもOK
  ]
}</code></pre></div>



<h3 class="wp-block-heading">3.サンプルデータの準備</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// サンプルデータ（本来はデータベースから取得）
const sampleUsers = [
  { id: &#39;1&#39;, name: &#39;山田太郎&#39;, email: &#39;yamada@example.com&#39;, age: 25 },
  { id: &#39;2&#39;, name: &#39;田中花子&#39;, email: &#39;tanaka@example.com&#39;, age: 30 },
  { id: &#39;3&#39;, name: &#39;佐藤次郎&#39;, email: &#39;sato@example.com&#39;, age: 22 }
];</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">今回は簡単にするために、メモリ上に配列でデータを用意したよ。本格的なアプリではデータベースを使うけどね。</p>
</div></div>



<h3 class="wp-block-heading">4.リゾルバーの実装</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// リゾルバー（実際にデータを取得する処理）
const resolvers = {
  Query: {
    // すべてのユーザーを返す関数
    users: () =&gt; {
      console.log(&#39;全ユーザーが要求されました&#39;);
      return sampleUsers;
    },
    
    // 特定のユーザーを返す関数
    user: (parent, args) =&gt; {
      console.log(`ID: ${args.id} のユーザーが要求されました`);
      // 配列から指定されたIDのユーザーを探す
      return sampleUsers.find(user =&gt; user.id === args.id);
    }
  }
};</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><code>(parent, args)</code>って何ですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><strong><span class="marker-under">GraphQLのリゾルバー関数は、4つの引数を受け取る</span></strong>んだ。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// リゾルバー関数の引数
function myResolver(parent, args, context, info) {
  // parent: 親のリゾルバーからの結果（今回は使わない）
  // args: クエリで渡された引数（user(id: &quot;1&quot;) の &quot;1&quot; など）
  // context: 全リゾルバーで共有するデータ（認証情報など）
  // info: クエリの詳細情報（高度な使い方で使用）
}

// 実際の使用例
user: (parent, args) =&gt; {
  console.log(&#39;受け取った引数:&#39;, args); // { id: &quot;1&quot; }
  return sampleUsers.find(user =&gt; user.id === args.id);
}</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">でも待ってください！スキーマでは<code>user(id: ID!): User</code>って書いてるけど、なんでリゾルバーでは<code>(parent, args)</code>って書くんですか？<code>user(id)</code>じゃダメなんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">これはGraphQLの仕組みを理解する上で重要なポイントなんだ。詳しく説明するね。</p>
</div></div>



<h4 class="wp-block-heading">スキーマ vs リゾルバーの関係</h4>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// 【スキーマ】= 「外部への約束・インターフェース」
type Query {
  user(id: ID!): User  // 「IDを受け取ってUserを返しますよ」という約束
}

// 【リゾルバー】= 「約束を実現する実際の処理」
const resolvers = {
  Query: {
    user: (parent, args) =&gt; {
      // args.id でスキーマで定義した引数にアクセス
      return sampleUsers.find(user =&gt; user.id === args.id);
    }
  }
};</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">あー！スキーマは「約束」で、リゾルバーは「実装」って感じのイメージですね！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">その通り！もう少し具体的に見てみよう！</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// スキーマで色々な引数パターンを定義できる
type Query {
  # 引数なし
  users: [User!]!
  
  # 引数1つ
  user(id: ID!): User
  
  # 引数2つ
  userByEmail(email: String!, domain: String!): User
  
  # オプショナル引数
  searchUsers(name: String, minAge: Int): [User!]!
}

// リゾルバーでは全部同じパターン
const resolvers = {
  Query: {
    // 引数なし → args は空オブジェクト {}
    users: (parent, args) =&gt; {
      console.log(args); // {}
      return sampleUsers;
    },
    
    // 引数1つ → args は { id: &quot;値&quot; }
    user: (parent, args) =&gt; {
      console.log(args); // { id: &quot;1&quot; }
      return sampleUsers.find(user =&gt; user.id === args.id);
    },
    
    // 引数2つ → args は { email: &quot;値&quot;, domain: &quot;値&quot; }
    userByEmail: (parent, args) =&gt; {
      console.log(args); // { email: &quot;test@example.com&quot;, domain: &quot;example.com&quot; }
      return sampleUsers.find(user =&gt; 
        user.email === args.email && user.email.endsWith(args.domain)
      );
    },
    
    // オプショナル引数 → 指定されなかった引数はundefined
    searchUsers: (parent, args) =&gt; {
      console.log(args); // { name: &quot;山田&quot;, minAge: undefined } など
      let result = sampleUsers;
      
      if (args.name) {
        result = result.filter(user =&gt; user.name.includes(args.name));
      }
      
      if (args.minAge !== undefined) {
        result = result.filter(user =&gt; user.age &gt;= args.minAge);
      }
      
      return result;
    }
  }
};</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">なるほど！引数の数に関係なく、リゾルバーは常に<code>(parent, args)</code>で受け取るんですね！</p>
</div></div>



<h4 class="wp-block-heading">どうしてこういった仕組みなの？</h4>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">GraphQLがこの仕組みを採用している理由は、<strong><span class="marker-under">統一性と柔軟性</span></strong>だよ。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// もしJavaScriptの関数のように直接引数を受け取る場合...
const badExample = {
  Query: {
    user: (id) =&gt; { /* ... */ },           // 引数1つ
    userByEmail: (email, domain) =&gt; { /* ... */ }, // 引数2つ
    searchUsers: (name, minAge) =&gt; { /* ... */ }   // オプショナル引数は？
  }
};

// 問題点：
// 1. 引数の数がバラバラで統一性がない
// 2. オプショナル引数の扱いが難しい
// 3. 将来的に引数を追加する時に既存コードが壊れる</code></pre></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// GraphQLの方式なら...
const goodExample = {
  Query: {
    // 全て同じパターン！統一性がある
    user: (parent, args) =&gt; { /* args.id */ },
    userByEmail: (parent, args) =&gt; { /* args.email, args.domain */ },
    searchUsers: (parent, args) =&gt; { /* args.name, args.minAge */ }
  }
};

// メリット：
// 1. 全てのリゾルバーが同じ形
// 2. 引数の追加/削除が簡単
// 3. ツールでの自動生成がしやすい</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><strong><span class="marker-under">統一性があることで、コードが書きやすくなる</span></strong>んですね！<br>でも<code>parent</code>って何に使うんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><code>parent</code>は、ネストしたクエリで威力を発揮するんだ。例えば、、</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// こんなクエリが来た場合
query {
  user(id: &quot;1&quot;) {
    name
    posts {      # ←ここでparentが活躍！
      title
    }
  }
}

// スキーマ定義
type User {
  id: ID!
  name: String!
  posts: [Post!]!  # ←このpostsリゾルバーでparentを使う
}

// リゾルバー
const resolvers = {
  Query: {
    user: (parent, args) =&gt; {
      return sampleUsers.find(user =&gt; user.id === args.id);
    }
  },
  User: {
    // User型のpostsフィールドのリゾルバー
    posts: (parent, args) =&gt; {
      // parent は上のuserリゾルバーが返したUserオブジェクト
      console.log(parent); // { id: &quot;1&quot;, name: &quot;山田太郎&quot;, email: &quot;...&quot; }
      
      // そのユーザーの投稿を取得
      return samplePosts.filter(post =&gt; post.authorId === parent.id);
    }
  }
};</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">あー！<code>parent</code>があることで、関連するデータを芋づる式に取得できるんですね！</p>
</div></div>



<h3 class="wp-block-heading">5.サーバー起動処理</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// サーバーを起動する関数
async function startServer() {
  // Apollo Serverを作成
  const server = new ApolloServer({ 
    typeDefs,    // スキーマ定義
    resolvers    // データ取得処理
  });

  // Expressアプリを作成
  const app = express();
  
  // Apollo Serverを開始
  await server.start();
  
  // ExpressアプリにApollo Serverを統合
  server.applyMiddleware({ app });

  const PORT = 4000;
  
  // サーバーを起動
  app.listen(PORT, () =&gt; {
    console.log(`&#x1f680; GraphQLサーバーが起動しました！`);
    console.log(`&#x1f4cd; GraphQL Playground: http://localhost:${PORT}${server.graphqlPath}`);
  });
}</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-11 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ03.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><code>server.applyMiddleware({ app })</code>は何をしているんですか？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">Apollo ServerをExpressアプリに組み込む処理だよ。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// applyMiddleware を実行すると...
server.applyMiddleware({ app });

// 以下のようなルートが自動的に作られる
// GET /graphql  → GraphQL Playground画面
// POST /graphql → GraphQLクエリの実行</code></pre></div>



<h3 class="wp-block-heading">6.エラーハンドリング</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>// サーバーを起動
startServer().catch(error =&gt; {
  console.error(&#39;サーバー起動エラー:&#39;, error);
});</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph"><code>async</code>関数はPromiseを返すから、エラーが起きた時のために<code>.catch()</code>でキャッチしてるんだ。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">うわー、一つ一つ説明してもらうと、すごく分かりやすいです！全体的にはシンプルな構造なんですね。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうだね！実は構造はシンプルなんだ。もう一度言うけど、大きく分けて3つの部分があるのでしっかりと頭に入れておこう！！</p>
</div></div>



<ol class="wp-block-list">
<li><strong>typeDefs</strong>：「こんなデータがありますよ」という設計図</li>



<li><strong>resolvers</strong>：「実際にデータを取得する処理」</li>



<li><strong>サーバー起動処理</strong>：「サーバーを立ち上げる」</li>
</ol>



<h3 class="wp-block-heading">package.jsonを更新</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">開発を楽にするために、<code>package.json</code>にスクリプトを追加しよう。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>{
  &quot;name&quot;: &quot;my-first-graphql&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;main&quot;: &quot;server.js&quot;,
  &quot;scripts&quot;: {
    &quot;start&quot;: &quot;node server.js&quot;,
    &quot;dev&quot;: &quot;nodemon server.js&quot;
  },
  &quot;dependencies&quot;: {
    &quot;apollo-server-express&quot;: &quot;^latest&quot;,
    &quot;express&quot;: &quot;^latest&quot;,
    &quot;graphql&quot;: &quot;^latest&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;nodemon&quot;: &quot;^latest&quot;
  }
}</code></pre></div>



<h3 class="wp-block-heading">サーバーを起動してみよう！</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">それでは、サーバーを起動してみよう！</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>npm run dev</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">おお！ターミナルに「GraphQLサーバーが起動しました！」って表示されました！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">OK！じゃあ、ブラウザで <code>http://localhost:4000/graphql</code> を開いてみて。</p>
</div></div>



<h2 class="wp-block-heading">GraphQL Playgroundで実際にクエリを実行</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">すごい！なんか格好いい画面が開きました！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">これが「GraphQL Playground」だよ。<br>ここで実際にクエリを書いて、データを取得してみよう。</p>
</div></div>



<h3 class="wp-block-heading">クエリその1：全ユーザーを取得</h3>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code># 左側のエディタに以下を入力
query {
  users {
    id
    name
    email
  }
}</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">このクエリを入力して、真ん中の再生ボタン（&#x25b6;）をクリックしてみて。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">うわー！右側にデータが表示されました！</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>{
  &quot;data&quot;: {
    &quot;users&quot;: [
      {
        &quot;id&quot;: &quot;1&quot;,
        &quot;name&quot;: &quot;山田太郎&quot;,
        &quot;email&quot;: &quot;yamada@example.com&quot;
      },
      {
        &quot;id&quot;: &quot;2&quot;,
        &quot;name&quot;: &quot;田中花子&quot;,
        &quot;email&quot;: &quot;tanaka@example.com&quot;
      },
      {
        &quot;id&quot;: &quot;3&quot;,
        &quot;name&quot;: &quot;佐藤次郎&quot;,
        &quot;email&quot;: &quot;sato@example.com&quot;
      }
    ]
  }
}</code></pre></div>



<h3 class="wp-block-heading">クエリその２：特定のユーザーを取得</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">今度は特定のユーザーだけを取得してみよう。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>query {
  user(id: &quot;1&quot;) {
    name
    email
    age
  }
}</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">今度は山田太郎さんの情報だけが返ってきました！</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>{
  &quot;data&quot;: {
    &quot;user&quot;: {
      &quot;name&quot;: &quot;山田太郎&quot;,
      &quot;email&quot;: &quot;yamada@example.com&quot;,
      &quot;age&quot;: 25
    }
  }
}</code></pre></div>



<h3 class="wp-block-heading">クエリその３：欲しいフィールドだけ取得</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">じゃあ、<strong><span class="marker-under">GraphQLの醍醐味を味わってみよう</span></strong>。名前だけが欲しい場合は？</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>query {
  users {
    name
    # emailやageは取得しない
  }
}</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">本当に名前だけが返ってきました！<br>これが<span class="marker-under"><strong>オーバーフェッチングを防ぐ</strong></span>ってことですね！</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>{
  &quot;data&quot;: {
    &quot;users&quot;: [
      { &quot;name&quot;: &quot;山田太郎&quot; },
      { &quot;name&quot;: &quot;田中花子&quot; },
      { &quot;name&quot;: &quot;佐藤次郎&quot; }
    ]
  }
}</code></pre></div>



<h3 class="wp-block-heading">エラーハンドリングも確認</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">じゃあ、存在しないIDを指定するとどうなるか試してみよう。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>query {
  user(id: &quot;999&quot;) {
    name
    email
  }
}</code></pre></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">結果がnullになりました！エラーにならずに、きちんと「見つからない」ことが分かりますね。</p>
</div></div>



<div class="hcb_wrap"><pre class="prism off-numbers lang-plain"><code>{
  &quot;data&quot;: {
    &quot;user&quot;: null
  }
}</code></pre></div>



<h3 class="wp-block-heading">スキーマの自動補完機能</h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">GraphQL Playgroundの右側にある「DOCS」タブをクリックしてみて。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">おお！自動的にAPIの仕様書が作られてる！どんなクエリが使えるか、どんなデータが返ってくるかが全部書いてあります！</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">そうなんだ！<strong><span class="marker-under">これもGraphQLの大きな利点の一つ</span></strong>。APIの仕様が自動的に生成されるから、フロントエンドの開発者も迷わずに済むんだ。</p>
</div></div>



<h2 class="wp-block-heading">今日のまとめ</h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">今日学んだことをまとめてみよう！</p>
</div></div>



<h3 class="wp-block-heading">作ったもの</h3>



<ul class="wp-block-list">
<li>Node.js + Apollo Serverを使ったGraphQLサーバー</li>



<li>User型のスキーマ定義</li>



<li>全ユーザー取得と特定ユーザー取得のクエリ</li>
</ul>



<h3 class="wp-block-heading">学んだ概念</h3>



<ul class="wp-block-list">
<li><strong>typeDefs</strong>：データの型を定義する設計図</li>



<li><strong>resolvers</strong>：実際にデータを取得する処理</li>



<li><strong>GraphQL Playground</strong>：クエリをテストできるツール</li>
</ul>



<h3 class="wp-block-heading">GraphQLの利点を実感</h3>



<ul class="wp-block-list">
<li>必要なフィールドだけ取得できる</li>



<li>自動的にAPIドキュメントが生成される</li>



<li>型安全でエラーが分かりやすい</li>
</ul>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-7 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/OZ01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">実際に動くものが作れて、すごく楽しかったです！<br>でも、<span class="marker-under"><strong>実際のアプリではデータベースを使いますよね</strong></span>？</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-8 sbs-stn sbp-l sbis-sb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://oz006.com/wp-content/uploads/2024/10/プロ太01.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p class="wp-block-paragraph">その通り！<br><span class="marker-under">次回はデータベースと連携して、もっと実践的なGraphQLサーバーを作ってみよう</span>。</p>
</div></div>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://oz006.com/graphql-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
