rubyのmoduleについて
今回はrubyのmodule
について説明していこうと思います。
この記事を書こうと思った経緯としては、業務においてソースコードを読んでいる時に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導入編)
今回は前回の記事↓の続きとして、pug、sass、typescriptを導入しようと思います。
それでは早速必要なパッケージをインストールします。
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 モジュールをエクスポートするので記述は不要になります。
以下のページを一度読んでみてください。
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を設定すると以下のようにローカルスコープができます。便利ですね。
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で試してみたいと思います。
以下参考記事になります。
次回はtodoアプリを作成するなどして、理解を深めていきたいと思います。
今回のコードもgithubにあげたので参考にしてみてください。
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のミニマムの単一ファイルコンポーネントの環境構築を行いました。
コードの詳細を見たい方はこちらを参考にしてみてください。
次回はtypescript、sass、pugなどを導入してみようと思います。
SQLの内部結合の結果をexpressを使ってブラウザに表示してみた
今回は内部結合について紹介したいと思います。
そもそも内部結合とは、2つのテーブルを結合してデータを取得する手法のうち、指定したテーブルのカラムの値が一致するデータだけを取得する方法です。
内部結合をした結果を実際にブラウザに表示するところまでを今回のゴールにします。
使用するツールとしては
- express
- mysql
- pug
になります。
手順としては
- mysqlの設定
- expressの環境を構築
- 実際にブラウザに表示
まず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テーブルの構造
belongテーブルの構造
ダミーデータは予め用意しておきました。 見てわかる通り、シンプルな構造です。 これらのテーブルを使っていきます。
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の説明は割愛させていただきます。 詳細を知りたい方はこちらの記事を参考にしてください。
注目をする箇所はsql文の箇所になります。
let sql = 'select * from user INNER JOIN belong ON user.belong_id = belong.id';
こちらが内部結合をしている部分です。
- userテーブルから全件データを取得
- userテーブルのbelong_idがbelongテーブルのidと合致するものをbelongテーブルから取得して、1で取得したuserテーブルに結合
ということをしています。 出力結果はこのようになります。
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}
このように表示されれば完成です。
今回は内部結合の紹介だけでしたが、今度は外部結合についても紹介できればと思います。
初めてのKotlin
Kotlinを触ってみようと思います。
今までフロントネタが多くを占めていたのですが、実際の業務でKotlinを使用することが増えることが予想されるので。
この記事では実際にKotlinの開発環境を準備して
お馴染みのHello World
を出力するところまでやっていこうと思います。
Kotlinの統合開発環に「InteliJ IDEA」というものがあります。 まずはInteliJ IDEAをインストールしてみましょう。 (JDKはインストールされていることは前提としています。)
公式サイトへアクセスします。
UltimateとCommunityと二つありますがUltimateは有償版でCommunityは無償版になります。 Community版をダウンロードしましょう。
ダウンロード完了後、早速InteliJ IDEAを起動してみましょう。 最初の起動時には設定の質問を色々と聞かれるかもしれませんが、一旦スルーでOKです。
まずは、JDKの設定を行います。 右下にある「Configure」→「Project Defaults」→「Project Structure」をクリックしてください。
下記の画面が表示されると思います。
「New」をクリック後、「JDK」を選択します。 その後、JDKのホームディレクトリを選択し、Openをクリックします。
次にKotlinプラグインを最新版にアップデートします。 その後ホーム画面に戻り、「Configure」→「Plugins」を選択します。 Updateが表示されなければ、そのまま「OK」をクリックして終了です。
準備が整いました。 ホーム画面から「Create New Project」をクリックします。
左に色々と項目が並んでいますが、「Kotlin」を選択してください。
その後、ファイル名は任意で良いので保存後ファイルに以下のコードを記述します。
fun main(args: Array<String>) {
println("Hello, World!")
}
画面右のファイル名からコンテキストメニュ−を表示させます。
表示後、「Run ファイル名」を選んでクリックします。
そうするとコンパイルがはじまり、以下のようにHello, World!
、Process finished with exit code 0
と表示されればOKです。
今度は、Kotlinで何か簡単なアプリケーションを作成しようと思います。
JavaScriptのimportとrequireの違いって?
JavaScriptで開発をしている時に、自分で作成したファイルやnodeモジュールなどを読み込む時にimport
やrequire
を使う時があると思います。
そういえばこの二つの違いってなんだろうと疑問に思ったのでその違いを探っていきたいと思います。
結論を先に述べると、require
がnodeの書き方でimport
がES2015の記述方法です。
因みに前者がCommonJSと呼ばれるモジュールシステム、後者がES Modulesです。
import
は全ブラウザでサポートしているわけではないので、babelなどで変換する必要があります。
require
は当たり前のことですが、nodeがない環境では使用することができません。
ここで疑問が生まれます。
フロントエンドで開発をしていくとなるとnodeを使った開発が主流になると思います。node
側でどのようにES Modulesを解釈しているのでしょうか?
この両者を区別するアルゴリズムが存在します。
CommonJS
とES Modules
によって処理内容を切り替えているようです。
こちらが参考にさせていただいた記事になります。
yosuke-furukawa.hatenablog.com
ではES Modules
の記述方法を見ていきましょう。
ES Modules
default exports
default exportsはexport default (渡したい変数や関数)
の形式で記述します。以下のコードを見てください。
export default function(name) { console.log(`My name is, ${name}!`); }
default imports
import getName from './greet.js'; getName('Tom');
このとき、greet.jsから渡された関数は、import先の変数getNameに代入されています。 export文では文字列や数値などの値、class、オブジェクトや配列などのリテラルも指定して公開できます。
named exports
こちらは上記のdefault exports
と違って1つのモジュールから個別にexportしたいものに変数名をつける必要があります。
export const name = "tanaka"; export const fruits = ["Apple", "Orange", "Banana"]; exports const num = 40;
それぞれ変数名をつけてexportします。
named imports
上で定義したモジュールを読み込む際にはimport先でimport { (変数名) } from (パス名)
の形式で、分割代入を記述するときのよう変数名を単一あるいは複数列挙します。
import { name, fruits } from './sub.js';
もしimport先から公開されている値のすべてを読み込みたいのであれば、任意の名前空間内に配置できます。
import * as module from './sub.js'; console.log(module.name); // "tanaka"
また変数名を読み込み側で変更することもできます。
import { name as myName } from './sub.js';
sub.js
で定義されている変数name
をMyname
と変更しています。
import元と同一ディレクトリのモジュールを読み込む場合には、./
と記述しなくてはいけません。
それ以外の読み込みについては、HTMLからほかのリソースを指定する場合のパス指定のルールと一緒です。/
から書き始めることで、ルートパスでの指定もできます。
// 同一階層のmenu.js を取得 import menu from './menu.js'; // 上の階層のscroll.js を取得 import scroll from '../scroll.js'; // ルートパスのroot.js を取得 import root from '/root.js';
また拡張子についても気をつける点があります。 webpackやBrowserifyを使っていると、.jsの拡張子を省いていてもモジュールを取得してくれることに慣れてしまっているかもしれませんね。
次回は、CommonJSについての書き方やルールについて解説していきたいと思います。
Reactとaxiosを使ってgithubのAPIからデータを取得してみる
今回はReactとaxiosを使ってgithubのAPIからデータを取得しようと思います。
まず、初めにプロジェクトフォルダを作ってください。
作成後、プロジェクトフォルダに移動して以下のコマンドを実行してください。
create-react-app プロジェクト名
create-react-appはreactの環境を簡単に作成することができる超便利ツールです。
その後、yarn start
自動でブラウザが立ち上がります。
編集するファイルはApp.jsとApp.cssファイルだけになります。 今回はgithub APIのデータをaxiosを使って取得することに集中したいのでコンポーネント化などはしません。
まず、必要なパッケージをインストールします。
yarn install -D axios
App.jsの全体のコードになります。 順を追って説明していきたいと思います。
import React, { Component, Fragment } from 'react'; import axios from 'axios'; import User from './App.css' class App extends Component { constructor(){ super(); this.state = { userDatas:[] }; } componentWillMount(){ const request = axios.create({ baseURL: 'https://api.github.com' }) request.get('/users/ユーザー名') .then(res => { this.setState({ userDatas: res.data }); }) } render() { return ( <Fragment> <header className="header"></header> <div className="user"> <p className="user_img"><img src={this.state.userDatas.avatar_url}/ ></p> <div className="user_name">{this.state.userDatas.name}</div> <div className="user_id">{this.state.userDatas.login}</div> <div className="user_followArea"> <div className="user_followers">followers:{this.state.userDatas.followers}</div> <div className="user_following">following:{this.state.userDatas.following}</div> </div> </div> </Fragment> ); } } export default App;
まずは1行目から見てみましょう。
import React, { Component, Fragment } from 'react'; import axios from 'axios';
FragmentとはReact v16から追加された機能になります。 簡単に言うとrender関数の中で余計なDOMノードを追加することが不要になります。 そのことの記事を書いたのでよかったら参考にしてください。
constructor(){ super(); this.state = { userDatas:[] }; }
constructorの中身についてですが、まずはstateにuserDatasを登録します。
次のコードが今回のコードのキーポイントになります。 componentWillMountというのはReactのコンポーネントのライフサイクルになります。 文字通り、コンポーネントがマウントされる前になんらかの処理を施すことができます。
componentWillMount(){ const request = axios.create({ baseURL: 'https://api.github.com' }) request.get('/users/ユーザー名') .then(res => { this.setState({ userDatas: res.data }); }) }
baseURLでgithubのAPIにアクセスします。 request.getでgithubの自分のデータをjson形式で取得しています。 その後、データを取得した後にsetStateでuserDatesにデータを入れています。
render() { return ( <Fragment> <header className="header"></header> <div className="user"> <p className="user_img"><img src={this.state.userDatas.avatar_url}/ ></p> <div className="user_name">{this.state.userDatas.name}</div> <div className="user_id">{this.state.userDatas.login}</div> <div className="user_followArea"> <div className="user_followers">followers:{this.state.userDatas.followers}</div> <div className="user_following">following:{this.state.userDatas.following}</div> </div> </div> </Fragment> ); }
ここではstateのデータを整形し表示しているだけになります。
ブラウザで見るとこのよう表示になります。(Cssは別途設定しています。)
とっても手軽で簡単ですね。是非試してみてください!今回は初めからjson形式データを取得できていましたが、サーバーから取得するデータの形式がjsonではないときなどあります。どのような形式でデータが渡ってきているかなど意識することは大切です。
簡単ではありますが、以上になります。