railsのプロジェクトにおけるvueを使った開発手法

今回はrailsのプロジェクトにおいてフロントにvue.jsを導入してみたことを記事にしてみました。具体的には下記のやりたいことに書いてあります。

開発環境

  • vue:2.3.4
  • typescript:2.2.2
  • ruby2.4.2
  • rails5.2.0

やりたいこと

railsjavascriptフレームワークなどを使用せずに開発をする場合コントローラーで作ったインスタンス変数などをerb.htmlファイルに渡すことが多いと思います。

f:id:top_men:20180617155702p:plain

今回は冒頭にも書きましたがvueの単一ファイルコンポーネントを使用して開発することを前提としています。そこで.vueファイルにrails側で作成したデータを渡す必要があります。erb.htmlファイルなら直接rubyのコードを記述することができますが、.vueファイルはrubyのコードを書くことができません。 

そこでどうしたら上記の問題を解決できるのか悩んでいました。

結論を言いますとwindowオブジェクトにviewmodelを追加すれば良いということです。

ここでは実際にユーザー情報が書かれたユーザ一詳細ページを例に解説していきます。(※ディレクトリ構成については説明していないのでご了承ください。)

ユーザー詳細ページの例

windowオブジェクトにviewmodelを追加している部分

import { Vue, Component } from 'vue-property-decorator';
import User from "../../component/users/User.vue";

@Component({
  components: {
    "user-profile-component": User
  }
})

class UserProfile extends Vue {

}

(<any>window).UserProfile = UserProfile;

前提としてtypescriptを使用して開発をしています。今回はそのことについてはあまり触れないので詳細を知りたい方は以下のリンクを参考にしてみてください。

github.com

はじめに、表示する用のUserコンポーネントを登録しています。 その後、windowオブジェクトのプロパティとしてUserProfileクラスを登録しています。

// typescriptを使用した記述方法

(<any>window).UserProfile = UserProfile;

// typescriptを使用していない場合

window.UserProfile = UserProfile

viewModelをインスタンス化している部分

<div id="userProfile">
  <user-profile-component :user="user"></user-profile-component>
</div>
<%= javascript_include_tag "/javascripts/viewmodel/users/show" %>
<script>
  new UserProfile({
    el: "#userProfile",
    data: {
      user: <%= raw @user.to_json %>
    }
  })
</script>

ここでviewファイルである.erb.htmlファイルとvueインスタンスをバインドしています。 その中にユーザー詳細ページを表示するコンポーネントを配置してpropsrailsからのデータを渡しています。

<user-profile-component :user="user"></user-profile-component>
<script>
  new UserProfile({
    el: "#userProfile",
    data: {
      user: <%= raw @user.to_json %> // railsのデータをインスタンス変数のuserに代入
    }
  })
</script>
<%= raw @user.to_json %>

このto_jsonメソッドは、rubyのHashやArrayをjson形式に変換してくれています。こうすることでフロント側で受け取りやすいデータ構造になります。

to_jsonを使った簡単な例

f:id:top_men:20180617142202p:plain

to_jsonを使用すると

f:id:top_men:20180617142310p:plain

json形式に変換してくれましたね。

またrawメソッドも使う必要があります。 使った場合と使わない場合の出力結果を見てみましょう。 (ここではdebuggerを仕込んだ出力結果を見ています。)

  • rawメソッドを使わない場合

f:id:top_men:20180617144556p:plain

  • rawメソッドを使った場合

f:id:top_men:20180617144831p:plain

ダブルクォーテーション""&quot;と変換されているのがわかります。 つまりrawメソッドを使用しない場合は、自動的にエスケープされています。 エスケープされないためにrawメソッドを使用する必要があるのです。

railsから受け取ったデータを受け取って描画している部分

<template>
  <div class='user'>
    <div class='user_name'>{{user.name}}</div>
    <div class='user_email'>{{user.email}}</div>
  </div>
</template>

<script lang="ts">
import { Vue, Prop } from "vue-property-decorator";
import UserData from "../../data/user";

export default class User extends Vue {
  @Prop()
  public user: UserData;
}

</script>

.vueファイルでは親から値を取得するためにpropsを定義してあげます。 あとは目的に合わせて表示するだけです。

まとめ

vueの単一ファイルコンポーネントを使用ってrailsからvueファイルにデータ渡すことができました。今回はvueを例に紹介しましたがreactなど他のフレームワークでも上記で説明した手法で開発できると思います。 簡単ではありますが、以上になります。

vue.jsはじめました@超基礎編

最近業務でvueを触る機会が多いので備忘録として残します。

ここで記述しているvueのバージョンは2.5.16です。

v-onについて

v-onディレクティブはイベントリスナに加え、Vueインスタンスのメソッドを呼び出すことができます。

<button v-on:click="doSomething">Click</button>

<!--省略記法-->
<button @click="doSomething">Click</button>

v-onは省略できるのでコードを書く際には@イベントリスナ名としましょう。 慣れるまではv-onを書くことをすすめます。

v-modelについて

フォームの入力値をvue側のデータとバインドする「双方向データバインディング」を簡単に実現することができます。これがVue.jsの主要な機能とも言えます。

<div id="app">
  <input v-model="messgae">
  <p>{{messgae}}</p>
</div>
new Vue({
  el: "#app",
  data: {
    messgae: "Hello"
  }
})

上記のコードを載せたので試してみてください。

jsfiddle.net

inputタグの値が変更される度にバインドしたmessageが変更されていると思います。 v-modelがしていることは二つあります。

  1. inputタグにvue側のデータをバインドする
  2. イベントハンドリングをしてデータを更新している

1について下記のようにまずはHTML側とvueをバインドします。

<input v-bind:value="message">

2では下記のように値を更新しています。

まずinputイベントハンドラでユーザーが入力した値を取得します。

<input @input="message">

その後、vue側のデータ変数に実際にユーザーが入力した値を代入します。

this.message = e.target.value

v-onの仕組みは大事なのでここで何をしているかは言語化できるようにしましょう。

v-bindディレクティブについて

bindとは他動詞では〜を結びつけるという意味です。 Vue側のデータをDOMと結びつけることを意味します。 リアクティブにデータを更新したいときに使用します。

最も簡単な例はテキストとしてバインドする例です。

<div id="app">
  {{ message }}
</div>
new Vue({
  el: "#app",
  data: { message: "Hello Vue" }
})

二重のブランケットの場合はプレーンなテキストとして表示されます。 htmlタグとして認識させたい場合は、v-htmlというディレクティブを使用します。

<div id="app">
  <p v-html="message"></p>
</div>
new Vue({
  el: "#app",
  data: {
   message: "<h1 style='color:red;'>Hello, Vue!!!</h1>" 
  }
 
})

vueのバージョン1では、下記にように三重のブランケットにしてhtmlとして認識させるようにしていたみたいです。

<div id="app">
  {{{ message }}}
</div>

またHTML属性にバインドするケースも多いです。 例えばapiから受け取ったデータをテキストリンクとして表示させたいとき。

<a v-bind:href="itemLink">Google</a>
new Vue({
  el: '#app',
  data: {
    itemLink: "http://google.com"
  }
})

また省略記法としてv-bindの代わりに:属性名と書くことが多いので慣れておきましょう。

イベント修飾子

イベント修飾子は、クリックやキー操作などDOMイベントの変更をしたいときに使用します。 今回はその中でも.stop修飾子について説明したいと思います。

例えばモーダルがあるとします。

  • モーダルのコンテンツを覆っているDOM → modal
  • モーダルのコンテンツのDOM → modal_content
<div class="modal">
  <div class="modal_content"></div>
</div>

モーダルのコンテンツに何か入力フォームやクリックするものなどあったときに、同じイベントをハンドルした要素がネストしている場合、イベントの発生元であるe.target.valueから親要素へ向かって設定している要素のイベントが連鎖して行われます。 そのようなときにmodalにはクリックするとモーダルが非表示になるイベント、modal_contentにも入力フォームなどに入力するようなイベントを設定していると入力しようとしたときにモーダルが非表示になってしまいモーダルが閉じてしまいます。

このようなケースの場合など.stop修飾子を使用します。

まずは.stop修飾子をつけないで試してみます。

<div id="app">
  <div class="modal" @click="getClassinfo('modal')">
    modal
    <div class="modal_content" @click.stop="getClassinfo('modal_content')">
      modal_content
    </div>
  </div>
</div>
new Vue({
  el: '#app',
  methods: {
    getClassinfo: function(className) {
        console.log(className)
    }
  }
})

modal_contentをくりっくした出力結果が以下になります。

modal_content
modal

modal_contentがクリックされるたびにmodalのクリックイベントも発火しています。

今度は.stop修飾子をつけて、modal_contentをクリックしてみてください。

<div id="app">
  <div class="modal" @click="getClassinfo('modal')">
    modal
    <div class="modal_content" @click.stop="getClassinfo('modal_content')">
      modal_content
    </div>
  </div>
</div>

javascriptのコードは変わらないので省略します。

出力結果は以下のようになります。

modal_content

.stopをつけることでイベントの伝搬を止めたい箇所を指定できました。

親→子へ値を渡す方法

<div id="app">
   <child-component number="3"></child-component>
</div>

Vue.component('child-component', {
    template: `<div>{{number}}</div>`,
  props: ['number']
})
new Vue({
  el: '#app',
})

ここでは子コンポーネントである'child-componentpropsの値として1を渡しています。=の右辺の値が親が渡したい値であり左辺のnumberは子の方でpropsとして定義する必要があります。

子→親へ何かをするとき

子のコンポーネントの状態に応じて親コンポーネントに何かしてほしいとき、また子が持っているデータを親に渡したいときは$emitを使用します。

<div id="app">
    <div class="parents">
      <child-component @child-event="getData"></child-component>
    </div>
</div>
Vue.component('child-component', {
    template: `<div @click='giveData'>クリック</div>`,
  methods: {
    giveData(){
        this.$emit("child-event")
    }
  }
})
new Vue({
  el: '#app',
  methods: {
    getData(){
        console.log("受け取りました")
    }
  }
})

ここで大切になるのがカスタムイベントです。 $emitを使って任意のタイミング(ここではクリックをしたとき)でカスタムイベントであるchild-eventを発火させます。それを親側で受け取るためには親側でv-onを使って子のカスタムイベントをハンドリングします。

そしてchild-eventが発火したタイミング(クリックしたとき)で親で定義したgetDataが実行され下記のような出力結果になります。

受け取りました

上記では子のコンポーネントのイベントに応じて親のメソッドを実行してるだけでした。 では、子のコンポーネントから何かしらのデータを送ってみましょう。 htmlファイルは変更箇所がないので記述しません。

Vue.component('child-component', {
    template: `<div @click='giveData'>クリック</div>`,
  methods: {
    giveData(){
        this.$emit("child-event", "come from child-component")
    }
  }
})
new Vue({
  el: '#app',
  methods: {
    getData(message){
        console.log(message)
    }
  }
})

出力結果です。

come from child-component

$emitの第一引数にカスタムイベント名、第二引数に渡したいデータを追加してあげると子→親にデータを与えることができます。

今は決め打ちで値を渡してみましたが、子のコンポーネントで定義したdata属性のpersonsという中身がオブジェクトの集まりのデータを渡してみます。

Vue.component('child-component', {
    template: `<div @click='giveData'>クリック</div>`,
  data: function() {
    return {
    persons: [
        {name: "田中", age: 23},
        {name: "佐藤", age: 22},
        {name: "武田", age: 17}
      ]
    }
  },
  methods: {
    giveData(){
        this.$emit("child-event", this.persons)
    }
  }
})
new Vue({
  el: '#app',
  methods: {
    getData(persons){
        console.log(persons)
    }
  }
})

クリックするとconsole.log上にこのように子から親にデータが渡ってきていることがわかると思います。

(3) [{…}, {…}, {…}, __ob__: Observer]

上記のコードはこちらに書いたので試してみてください。

jsfiddle.net

今度はvue-class-componentsについて記事を書きたいと思います。

rubyのmoduleについて

今回はrubymoduleについて説明していこうと思います。 この記事を書こうと思った経緯としては、業務においてソースコードを読んでいる時にmoduleという単語が出てきたのでJavaScriptユーザーの自分としては何ぞや?となったからです。

moduleの役割としては以下になります。

  • 定数やメソッドを定義

  • mix-inを可能とする

  • 名前空間を提供

定数やメソッドを定義

module Ziro
  Garlic = "にんにく"
  Noodles = "ふとめん"
  BeanSprou = "もやし"
  PigBones = "豚骨"
end

class Ramen
 include Ziro
 puts Garlic
end

結果はにんにくと出力されます。 注意点としては、定数は大文字から始めなくてはなりません。

mix-inを可能とする

rubyはクラス一つにつき一つしかクラスを継承することができないようです。 しかしmoduleを使うことで別のクラスとは別にメソッドや変数を継承することができます。具体的にはコードをみていきましょう。

module Cat
  def bark
    puts "ニャンニャン"
  end
end

class Zoo
  include Cat
end

zoo = Zoo.new
zoo.bark

ここで注目するのはincludeです。クラスの中でincludeと書くことでそのmoduleのメソッドはインスタンスメソッドとなります。 では猫だけだと寂しいので犬も仲間に入れてあげましょうか。

module Cat 
  def bark
    puts "ニャンニャン"
  end 
end

module Dog 
  def bark
    puts "わんわん"
  end 
end

class Zoo 
  include Dog 
  include Cat 
end

zoo = Zoo.new
zoo.bark

この結果どうなると思いますか? 結果はにゃんにゃん出力されます! Zooクラスの方で後にincludeされたmoduleが優先されます!

一方でこちらのコードも見てみましょう。

module Cat
  def bark
    puts "ニャンニャン"
  end
end

class Zoo
  extend Cat
end

Zoo.bark

includeをextendと変更しました。こうすることでインスタンスを作らなくてもクラスメソッドとして扱うことができます。ここでインスタンスを作ってからbarkを呼び出そうとしてもエラーになります。

名前空間を提供

名前空間とは、名前の衝突を避けるための概念になります。複数人で開発をしていると他の人が作成したメソッドの名前と被ってしまう可能性があります。このmoduleの中の◯◯のメソッドのように名前空間をつくることで重複を防ぎます。実際にコードを見て見ましょう。

module Animal
  class Dog 
    def self.bark
      puts "わんわん"  
    end 
  end 
end

Animal::Dog.bark #=> わんわん

このようにモジュール名::クラス名.メソッド名名前空間を作成し、メソッドを実行できることができます。

もう一階層モジュールの名前空間を深くしてみましょう。

module Creature
  module Animal
    class Dog
      def self.bark
        puts "わんわん"
      end
    end
  end
end

Creature::Animal::Dog.bark #=> わんわん

結果わんわんと出力されます。 moduleを呼び出す際には::を忘れないようにしましょう!

簡単ではありますが以上になります。

Vue.jsの単一ファイルコンポーネント用の環境構築をしてみた(Pug+Sass+Typescript導入編)

今回は前回の記事↓の続きとして、pugsasstypescriptを導入しようと思います。

top-men.hatenablog.com

それでは早速必要なパッケージをインストールします。

pugをインストール

npm i -D pug

sass関連のパッケージをインストール

npm i -D node-sass sass-loader

typescript関連のパッケージをインストール

npm i -D typescript ts-loader vue-ts-loader

必要なパッケージはインストールできたので、設定ファイルを編集・追加していきます。

tsconfig.jsの作成

まずプロジェクトフォルダ直下にtsconfig.jsを作成し、以下のようにします。

{
  "compilerOptions": {
    "outDir": "./dist/",
    "sourceMap": true,
    "strict": true,
    "noImplicitReturns": true,
    "module": "es2015",
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "noImplicitThis": true,
    "target": "es5",
    "experimentalDecorators": true
  },
  "include": [
    "./src/**/*"
  ]
}

webpack.config.jsの作成

webpack.config.jsを編集していきます。

const path = require('path');
const webpack = require('webpack');

module.exports = {
  entry: './src/index.ts',
  output: {
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/dist/',
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        exclude: /node_modules/,
        loader: 'vue-loader',
        options: {
          esModule: true
        }
      },
      {
        test: /\.ts$/,
        loader: 'ts-loader',
        exclude: /node_modules/,
        options: {
          transpileOnly: true,
          appendTsSuffixTo: [/\.vue$/]
        }
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      },
    ]
  },
  resolve: {
    extensions: ['*', '.ts', '.vue', '.json', 'scss', '.js'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  },
  devServer: {
    contentBase: './',
    port: 3000,
    host: 'localhost',
    historyApiFallback: true,
  }
};

vue-loaderの部分なのですが、よく他の記事では、オプションでesModule: trueと記載するのですが、ver14以降.vue ファイルは常に ES モジュールをエクスポートするので記述は不要になります。 以下のページを一度読んでみてください。

オプションリファレンス · vue-loader

d.tsファイルの作成

次にsrcフォルダ直下にsfc.d.tsファイルを作成します。

declare module "*.vue" {
  import Vue from "vue";
  export default Vue;
}

d.tsより前の名前は任意で大丈夫です。 このファイルを配置する場所は、tsconfig.jsonで指定されているパスの中でしたらどこでも大丈夫です。

コンポーネントファイルの作成

今度はHello.vueファイルを編集します。

<template lang="pug">
  .list
    p.list_item Hello {{name}}
</template>

<style lang="scss" scoped>
  .list {
    color: #323232;
    font-weight: 700;
    &_item {
      display: flex;
    }
  }
</style>

<script lang="ts">
  import Vue from "vue";

  export default Vue.extend({
    data() {
      return {
        name: 'Vue.js!!!!'
      }
    }
  })
</script>

styleタグにscopedを設定すると以下のようにローカルスコープができます。便利ですね。

f:id:top_men:20180506232704p:plain

htmlファイルを作成

前回の記事ではdistフォルダの中にhtnlファイルを配置していましたが、便宜上プロジェクトフォルダ直下に配置します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Vue Component Tutorial</title>
</head>
<body>
  <div id="app"></div>
  <script src="./dist/bundle.js"></script>
</body>
</html>

これでnpm startとコマンドを実行してブラウザにHello Vue.js!!!!と表示されればOKです!

躓いた箇所

vue-laoderの部分で結構悩まされました。 ローカルサーバーを起動した時に以下のようなエラーがでました。

ERROR in ./src/components/Hello.vue?vue&type=script&lang=ts
vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config.

結論を言うと自分は今回のプロジェジェクトではvue-loaderのver15を使用していました。ver15は最近リリースされたばかりでver14と変更点が多く、新たにVueLoaderPluginなどを追加しなければいけないみたいです。自分はvue-loaderのバージョンを14に下げてこのエラーを回避しました。次vue-loaderを使う機会がある時はver15で試してみたいと思います。

以下参考記事になります。

github.com

vue-loader.vuejs.org

次回はtodoアプリを作成するなどして、理解を深めていきたいと思います。

今回のコードもgithubにあげたので参考にしてみてください。

github.com

Vue.jsの単一ファイルコンポーネント用の環境構築をしてみた

Vueでの開発には欠かせない単一ファイルコンポーネント用の環境構築をしていきます。本当に最小構成になりますのでご了承ください。

vue-cliを使用すれば爆速で構築できると思うのですが、初心者であるからこそ環境構築の部分は時間をかけて理解していきたいところです。

では早速プロジェクトフォルダを作成後、お馴染みのコマンドを実行しましょう。

npm init -y

package.jsonが作成されます。

次にwebpack関連のパッケージをインストール

npm i -D webpack webpack-cli webpack-dev-server

babelのインストール

#webpackでbabelを使用するためのパッケージ
npm i -D babel-loader babel-core

#ES6 をトランスパイルするためのパッケージ
npm i -D babel-preset-es2015

css関連のパッケーシをインストール

npm i -D css-loader style-loader

vue関連のパッケージをインストール

npm i -D vue vue-html-loader vue-loader vue-template-compiler

必要なパッケージをインストールできました。 package.jsonのscriptの部分を以下の変更します。

"scripts": {
    "start": "webpack-dev-server"
  },

このように設定することでローカルサーバーが立ち上がります。

package.json全体はこのようになっています。

{
  "name": "vue-component-tutorial",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.4",
    "babel-preset-es2015": "^6.24.1",
    "css-loader": "^0.28.11",
    "style-loader": "^0.21.0",
    "vue": "^2.5.16",
    "vue-html-loader": "^1.2.4",
    "vue-loader": "^14.2.2",
    "vue-template-compiler": "^2.5.16",
    "webpack": "^4.6.0",
    "webpack-cli": "^2.0.15",
    "webpack-dev-server": "^3.1.3"
  },
  "dependencies": {
    "vue": "^2.5.16"
  }
}

次にwebpack.config.jファイルをプロジェクトフォルダ直下に作成してください。

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        exclude: /node_modules/,
        loader: 'vue-loader',
      },
      {
        test: /\.css$/,
        exclude: /node_modules/,
        loader: ['style-loader', 'css-loader'],
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      },
    ]
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  },
  devServer: {
    contentBase: 'dist',
    port: 3000,
    host: 'localhost',
    historyApiFallback: true,
  }
};

.babelrcファイルを作成します。

{
  "presets": [ "es2015" ]
}

プロジェクトフォルダ直下にindex.jsファイルを作成します。

import Vue from 'vue'
import Hello from './components/Hello.vue'

new Vue({
  el: '#app',
  components: {
    Hello
  },
  template: '<Hello></Hello>'
})

ここではコンポーネントファイルであるHello.vueファイルを読み込んでいます。テンプレート名として<Hello>を設定します。

今度は、コンポーネントファイルを作成していきます。 componentsディレクトリの中にHello.vueファイルを作成してください。

<template>
  <p>Hello, {{ name }}</p>
</template>

<style scoped>
p {
   color: #323232;
   font-weight: 700;
 }
</style>

<script>
export default {
  data: function() {
    return {
      name: 'Vue.js!!!'
    }
  }
}
</script>

最後にdistフォルダを作成後、直下にindex.htmlを配置してください。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Vue Component Tutorial</title>
</head>
<body>
  <div id="app">
    <hello></hello>
  </div>
  <script src="./bundle.js"></script>
</body>
</html>

ここではwebpackでビルドされたbundle.jsファイルを読み込み、定義したコンポーネントを配置しています。

これで一通り必要なファイルができました。

npm run start

上記のコマンドを実行後localhost:3000にアクセスし、Hello, Vue.js!!!と表示されれば完成です。 今回はVue.jsのミニマムの単一ファイルコンポーネントの環境構築を行いました。

コードの詳細を見たい方はこちらを参考にしてみてください。

github.com

次回はtypescript、sass、pugなどを導入してみようと思います。

SQLの内部結合の結果をexpressを使ってブラウザに表示してみた

今回は内部結合について紹介したいと思います。

そもそも内部結合とは、2つのテーブルを結合してデータを取得する手法のうち、指定したテーブルのカラムの値が一致するデータだけを取得する方法です。

内部結合をした結果を実際にブラウザに表示するところまでを今回のゴールにします。

使用するツールとしては

になります。

手順としては

  1. mysqlの設定
  2. expressの環境を構築
  3. 実際にブラウザに表示

まずmysqlの設定をしていきます。

1 mysqlの設定

最初にデータベースを作成します。データベース名は名簿という意味でRosterにします。 テーブルはUserの情報が入っているuserテーブル、そのユーザーの職種情報が書かれたgroupテーブルにしました。

早速ですが、テーブルにデータを追加しようとしたときに泥沼にハマってしまいました。 userテーブルにはすんなりとデータを入れることができたのですが、groupテーブルにはデータをうまくいれることができませんでした。下記のようなエラーが表示されます。

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group' at line 1

結論を言うと、このgroupというのがMysql予約語でした。 いやーほんとデータベースに無知な自分にとっては全く気がつかない大きな落とし穴でした。良い経験になりました。

その後、テーブル名をbelongに変更しました。

userテーブルの構造

f:id:top_men:20180425004949p:plain

belongテーブルの構造

f:id:top_men:20180425005223p:plain

ダミーデータは予め用意しておきました。 見てわかる通り、シンプルな構造です。 これらのテーブルを使っていきます。

2 expressの環境を構築

はじめにプロジェクトフォルダを作成し、移動してください。

プロジェクトフォルダ直下でpackage.jsonを作成します。

npm init -y

その後必要なパッケージをインストールします。

npm i -D express pug mysql

プロジェクトフォルダ直下にindex.jsファイルを作成します。

const express = require('express');
const app = express();
const mysql = require('mysql');

const connection = mysql.createConnection({
  host     : 'localhost',
  user     : 'ユーザー名',
  database : 'Roster'
});

//viewファイルとしてpugを設定
app.set('view engine', 'pug');

//viewsフォルダの中のファイルを参照するようにする
app.use(express.static('views'));

const recordLog = function (req, res, next) {
  console.log('localhost:3000にアクセスしました');
  next();
};

app.use(recordLog);

app.get('/', function (req, res) {
  let sql = 'select * from user INNER JOIN belong ON user.belong_id = belong.id';
  connection.query(sql, (err, rows, fields) => {
    console.log(rows, "rows")
    if (err) throw err;
      res.render('index', { title: '内部結合の練習', PesoralDatas: rows});
  });
});

app.listen(3000);

expressの説明は割愛させていただきます。 詳細を知りたい方はこちらの記事を参考にしてください。

top-men.hatenablog.com

注目をする箇所はsql文の箇所になります。

let sql = 'select * from user INNER JOIN belong ON user.belong_id = belong.id';

こちらが内部結合をしている部分です。

  1. userテーブルから全件データを取得
  2. userテーブルのbelong_idがbelongテーブルのidと合致するものをbelongテーブルから取得して、1で取得したuserテーブルに結合

ということをしています。 出力結果はこのようになります。

f:id:top_men:20180425012334p:plain

userテーブルにあるbelong_idが5のレコードが表示されていません。 belongテーブルのidが5のレコードは存在しないからです。

3. 実際にブラウザに表示

これらのデータをブラウザに表示させるためにまずプロジェクトフォルダ直下にviewsフォルダを作成し、index.pugファイルを配置します。

html
  head
    title #{title}
    link(rel="stylesheet" href="css/style.css")
  body
    h1 #{title}
    each person in PesoralDatas
      .person
        .person_name 名前:#{person.name}
        .person_type 職種:#{person.type}
        .person_age 年齢:#{person.age}
        .person_email メールアドレス:#{person.email}

このように表示されれば完成です。

f:id:top_men:20180425013254p:plain

今回は内部結合の紹介だけでしたが、今度は外部結合についても紹介できればと思います。

初めてのKotlin

Kotlinを触ってみようと思います。

今までフロントネタが多くを占めていたのですが、実際の業務でKotlinを使用することが増えることが予想されるので。

この記事では実際にKotlinの開発環境を準備して お馴染みのHello Worldを出力するところまでやっていこうと思います。

Kotlinの統合開発環に「InteliJ IDEA」というものがあります。 まずはInteliJ IDEAをインストールしてみましょう。 (JDKはインストールされていることは前提としています。)

公式サイトへアクセスします。

f:id:top_men:20180415232458p:plain

UltimateCommunityと二つありますがUltimateは有償版でCommunityは無償版になります。 Community版をダウンロードしましょう。

ダウンロード完了後、早速InteliJ IDEAを起動してみましょう。 最初の起動時には設定の質問を色々と聞かれるかもしれませんが、一旦スルーでOKです。

f:id:top_men:20180415235205p:plain

まずは、JDKの設定を行います。 右下にある「Configure」→「Project Defaults」→「Project Structure」をクリックしてください。

下記の画面が表示されると思います。

f:id:top_men:20180415235511p:plain

「New」をクリック後、「JDK」を選択します。 その後、JDKのホームディレクトリを選択し、Openをクリックします。

次にKotlinプラグインを最新版にアップデートします。 その後ホーム画面に戻り、「Configure」→「Plugins」を選択します。 Updateが表示されなければ、そのまま「OK」をクリックして終了です。

準備が整いました。 ホーム画面から「Create New Project」をクリックします。

f:id:top_men:20180416000615p:plain

左に色々と項目が並んでいますが、「Kotlin」を選択してください。

その後、ファイル名は任意で良いので保存後ファイルに以下のコードを記述します。

fun main(args: Array<String>) {
    println("Hello, World!")
}

画面右のファイル名からコンテキストメニュ−を表示させます。 表示後、「Run ファイル名」を選んでクリックします。 そうするとコンパイルがはじまり、以下のようにHello, World!Process finished with exit code 0と表示されればOKです。

f:id:top_men:20180416004029p:plain

今度は、Kotlinで何か簡単なアプリケーションを作成しようと思います。