Learn English

with movies

MOViE UP

映画|翻訳

自身の英語学習のために翻訳した映画のワンシーンを記事として載せています
たくさんの人に楽しく英語学習が出来る材料となれば幸いです

MOViE UPでの使用技術

当サイトは管理人がエンジニアとしての学習も兼ねて作成しております。
当サイトを構成する技術についていくつかご紹介させていただきます。

サーバサイド

使用技術
- go言語
- gin( go言語用のWebアプリ用フレームワーク
- gorm ( go言語用のORマッパー )
- docker(開発中)
- mysql
go言語 x gin x gormでサーバサイドを実装しました。
いくつかサンプルを載せておきますので、同じ構成で実装する方のサンプルとなれば幸いです。

まずはginを使ったルーティングです。
テンプレートはgo言語の標準テンプレートを使います。


【main.go】
    router.GET("/", func(context *gin.Context) {
        // HTMLを返却するリクエストなので使用するテンプレートを設定
        // base.templ.html ⇨ 全てのテンプレートの親となるベースのテンプレート
        // index.templ.html ⇨ 表示対象画面のテンプレート
        html := template.Must(template.ParseFiles("docker/golang/templates/base.tmpl.html", "docker/golang/templates/index.tmpl.html"))
        router.SetHTMLTemplate(html)

        // ごにょごにょ処理する
        content := "こんてんつ"

        // HTMLを返却
        // gin.H{}内にtemplateで使用する変数を設定
        context.HTML(http.StatusOK, "base.tmpl.html", gin.H{ "content": content })
    })

【base.tmpl.html】
    <!-- 親のテンプレートにはtemplateタグで子への埋め込み設定を指定 -->
    <body>
        {{template "body" .}}
    </body>

【index.tmpl.html】
    <!-- 子のテンプレートで埋め込みタグに実値を注入(指定しないとgo起動時エラーとなるため注意) -->
    {{define "body"}}
        <p>
            {{ .content }}
        </p>
    {{end}}
                    

次にgormを使用したDB接続周りです。


【main.go】
    // USER、PASSWORD、PROTOCOL、DBNAMEを接続先のDBに合わせて指定
    CONNECT_STR := USER + ":" + PASSWORD + "@" + PROTOCOL + "/" + DBNAME
    // DB接続。parseTime=trueをつけることでstructで受ける時time.Timeを使用可能となる
    // errを使ってエラーハンドリングしたり
    db,err := gorm.Open(DBMS, CONNECT_STR + "?parseTime=true")

    // タグ一覧を取得(当サイト画面下に出しているカテゴリってやつです)
    tags := []Tag{}
    db.Find(&tags)
    // db.Find(&tags, "xxxx=?", hoge) とするとwhere句に'xxx = hoge'が指定される

【main.goやら別のファイルやら】
    // 実際のDB構成です。タグマスタはこうなってます。
    type Tag struct {
        TagId       int `gorm:"column:tag_id"`
        Name        string `gorm:"column:name"`
        OrderNumber int `gorm:"column:order_number"`
    }
    // TableName()を実装してあげるとdb.Find()時にこのテーブルをfrom句で指定してくれるようになる
    // 実装しないと自動でstructの複数形(tagsテーブル)が指定される
    func (m *Tag) TableName() string {
    	return "mst_tag"
    }
                    

フロントサイド

使用技術&学習内容
- vue.js
- Webサイトデザイン
- レスポンシブデザイン
- レスポンシブデザインコーディング ( CSSフレームワーク無しでの実装 )
- ロゴ作成

vue.jsは、細かい箇所含めて数カ所使っています。
例えばトップページの「もっと見る」ボタンを押すとajaxを使用して次の記事をサーバから読み込む箇所は、以下のような感じで実装しています。
( vue.jsのコンポーネントは、コンポーネント化された部分のHTML構成が別ファイルに分割されてデザインコーディングが不便なため使用していません )


【HTML側】
    // ajaxではaxiosを使用しているので、axios.jsを読み込み
    <cript src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

    // ここではaタグで実装してます
    // js側のロジック(getNextArticles)を呼び出し、aタグクリックのライフサイクルをonclick="return false;"で停止しています
    <a href="#" onclick="return false;" @click="getNextArticles">もっと見る</a>

    // v-forで取得した配列を表示
    // HTML構成は省略してます
    <div id="hoge">
        <div v-for="scene in scenes">
            <div class="article">
                <span>@{ scene.titleJp }</span>
                <span>@{ scene.titleEn }</span>
                <span>@{ scene.description }</span>
            </div>
        </div>
    </div>

【js側】
    var vueNews = new Vue({
        el: '#hoge',
        // go言語のテンプレートでは{{}}を使用するのでHTML側では@{}でデータをバインド出来るように指定しておく
        delimiters: ['@{', '}'],
        data: {
            currentArticlePage: 1,
            scenes: [],
        },
        methods: {
            getNextArticles: function() {
                axios
                    // クエリパラメータで読み込みページを指定
                    .get('/hoge/hoge/' + (vueNews.currentArticlePage + 1) + '/')
                        .then(function (response) {
                            // レスポンス値は記事(シーン)がjsonで配列になってくるので配列をループ処理でdata内のscenesに追加していく
                            // (いくつかの処理を簡略化してあります)
                            response.data.scenes.forEach(scene => {
                                vueNews.scenes.push({
                                    // タイトル(日本語)
                                    titleJp: scene.Movie.TitleJp,
                                    // タイトル(英語)
                                    titleEn: scene.Movie.TitleEn,
                                    // シーン説明
                                    description: scene.Description,
                                });
                            });
                            // ページ数をカウントアップ
                            vueNews.currentArticlePage++
                        });
            },
        },
    })

【go言語(サーバ)側】
    import (
        "strconv"
    )

    ...

    // 記事取得API
    router.GET("/hoge/hoge/:pageNo/", func(context *gin.Context) {
        // パラメータ(ページ数)取得
        pageNo, _ := strconv.Atoi(context.Param("pageNo"))

        scenes := []structs.Scene{}
        // ほにゃほにゃしてシーン一覧をDBより取得

        // jsonでレスポンス返却
        context.JSON(http.StatusOK, gin.H{ "scenes": scenes })
    })
                    

また、レスポンシブデザインはbootstrapでのデザインしか経験がなかったので、全てのデザインコーディングを自分でやってみたくて1から実装しました。
デザイン ( デザイン作成はcacoo ) 作成後の基本的な流れは
1. スマホ用のデザインコーディング
2. タブレット用のデザインコーディング ( 1からタブレット時の画面サイズの時に差分が出る箇所のみ )
3. PC用のデザインコーディング ( 2からPC時の画面サイズの時に差分が出る箇所のみ )
としたので、以下のようにメディアクエリを分けました。


【css】
    /* まずスマホ用のデザイン(共通デザイン)をメディアクエリ無しでコーディング */
    ...

    /* タブレット用のメディアクエリでコーディング */
    @media all and (min-width: 768px) {
        ...
    }

    /* 最後にPC用のメディアクエリでコーディング */
    @media all and (min-width: 1000px) {
        ...
    }
                    

色々省略しましたが簡単に使用技術を載せてみました。
少しでも技術者の方の助けとなれば幸いです。