Next.jsでSequelizeを使ってMySQLにアクセスするAPIを作る

すっかり夏を感じる季節になってきましたりっくんです。
BlogだったりはてなBlogだったり、Noteだったり色々書くところがあるんですが、ガッツリ技術っぽいのはここに書こうかな。

ふと、Next.jsを使ったWebアプリを書いてたんだけど、その時少しSequelizeが吐き出すファイルで詰まったので、メモがてら書いていきます。
Next.jsはAPI部分が簡単に便利に作れるように準備があるのですが、その中でSequelizeで作ったORMにアクセスしてデータを取得するイメージです。

構成

  • 開発環境:WSL2 Ubuntu
  • フロントエンド:React.js(Next.js)
  • バックエンド:Next.js(API部分をバックエンドにする)
  • DB:MySQL(Dockerで構築)

まだフロント部分ほとんど書いていないけど、Next.jsで言うところの、pages/api の部分を使ってAPIを作りそこを叩く予定。

Sequelizeについて

Node.jsで使えるORMapper、いろいろなDBに使えるようだけど今回はMySQLで使う感じ。
コマンドラインツールも用意されていて、便利にconfigファイルを生成したり、Migrationが可能になる。

参考: Node.jsのSequelizeでDBのmigrationを実行する - Qiita

ということでこんな感じにインストール

npm install sequelize --save

初期設定はnode_modulesから直接叩くとコマンドを実行できる。

node_modules/.bin/sequelize init

config.js が吐き出されるので、そこにDBの設定を書く。
今回はDocker上にMySQL8のContainerを立てているので、そこに向ける。

{
  "development": {
    "username": "root",
    "password": "docker",
    "database": "sampledb",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  // 略
}

migration用のファイルを生成するにも、コマンドを直接叩けば良いので以下のように叩く

node_modules/.bin/sequelize model:create --name user --underscored --attributes name:string,birth:date,country_code:integer
node_modules/.bin/sequelize db:migrate --env development

2行目のコマンドで実際にmigrationを実行できる。
この時、ちゃんと生成できるかはDBを直接叩いて確認済み。

Next.jsにSequelizeをつなぎこむ。

今回はAPIとして使いたいという気持ちがあったので、初期から用意されていた pages/api/hello.js をそのまま編集して使ってみる。
この時アクセスするURLは http://localhost/api/hello になるので、そこを叩きながらログを確認してチェックする。

// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
const db = require('../../models/')

export default async (req, res) => {
  // findAll
  db.user.findAll({}).then((instances) => {
    console.log(instances);
    res.status(200).json({ message: instances });
  });
};

db として、プロジェクト直下の models フォルダを読み込んでいるけども、これはSequelizeをinitしたときに生成される便利なやつです。
こいつを読み込んでおけば、 db.user のような形で user モデルを簡単に操作することができるようになる。

Next.jsの場合、自動生成された状態だとrequireを行ったときにエラーが出て正常に読み込めなかった。

解決策は、 models/index.js 内のファイルパスを書き換えてあげることで、以下のように変更する

'use strict';

const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/database.json')[env];
const db = {};

/* Custom handler for reading current working directory */
const models = process.cwd() + "/models/" || __dirname;

let sequelize;
if (config.use_env_variable) {
  sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
  sequelize = new Sequelize(config.database, config.username, config.password, config);
}

fs
  // .readdirSync(__dirname)
  .readdirSync(models)
  .filter(file => {
    return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
  })
  .forEach(file => {
    // const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
    const model = require(`./${file}`)(sequelize, Sequelize.DataTypes);
    db[model.name] = model;
  });

Object.keys(db).forEach(modelName => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

今回クリティカルに影響したのは、

// const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
const model = require(`./${file}`)(sequelize, Sequelize.DataTypes);

この部分。
Node.jsでは path.join を使うと簡単にPathを生成できるんだけど、状況によって求めていないPathが生成される可能性があるとのことで、ここを直接書き換えた。
参考: npm path.joinの罠 - Qiita

今回は ./ をつけてPathを記述したかったのにも関わらず、 / となっていて、Ubuntuの直下のディレクトリを参照していたため、正常にModelを定義したjsファイルを読むことができていなかったというのが原因。

ここからは開発進むと思うので頑張っていくー。

開発物の話

もともとはFirebaseで作ろうと思って色々考えてたんだけど、どう考えてもRDBのほうが作りやすいようなシンプルなものだったのでNode.jsのORMを探したところがスタート。
Firebase、ログイン周りとかすごく楽で良いと思ってるんだけど、多分Next.jsでも簡単にできるっしょみたいな思い込みがあるので、多分なんとかなる?笑

NoSQL周りの知見があまりないからなんともなんだけど、今回作ろうとしてるやつはかなり正規化できそうだし、しないとめんどくさそうなので・・・。

Next.js自体もあまり触らないけど多分Nuxt.jsっぽいと思っていればいいんだろうか。
とりあえず水曜日に代休を取っているので、奥さんを免許センターに送りつつ、空いた時間で開発する予定。

続報を出せるかは不明!

上司のHONDA CIVICと我が家のMazda Axelaを乗り比べて

Project Winterを購入して身内8人とかでちょいちょいプレイしてるんですがなかなかおもしろいと思っていますりっくんですこんにちわ。 すごい良いんだけど、いかんせん慣れてなさすぎててんやわんやで面白い、迷惑かけない程度にはできるようになりたい。

あまりこのBlogでは(というか別のものでもだけど)車の記事を書かないのですが、Twitterのプロフィールを見てもらえば分かる通り、我が家ではマツダアクセラセダンに乗っています。 で、5月くらいに上司がホンダシビックのセダンをオプション盛々で購入したので、ずっと運転してみる機会を伺っていたのですが、この土曜日にその機会がありましたので乗り比べた感じをざっくり書いておこうと思います。

TL;DR

  • 同じ1.5Lガソリンだけど、ターボとNAで大分トルク感が違う
  • そもそも、ホンダの1.5Lガソリンのほうが振動感とか少なくてじゃっかんラグジュアリーな気がする(CVTなのも影響あるかも)
  • 横幅はほぼ同じだけど、全然シビックのほうが感覚つかみやすい
  • あと後席の居住空間は圧倒的にシビック
  • 内装はマツダのほうが高級感があると思ってる。というかシビック古くないかなぁ・・・
  • Mazda Connectの設置位置はまじで考えられてて、シビックのナビの位置だと手元過ぎて視線が外れるのが怖い
  • あと、ヘッドアップディスプレイは最高
  • シビックのハンドルのボタン類のナビゲーションが微妙、あまり直感的じゃない

割と長くなった、TL;DRなのに・・

行き先

今回は千葉の西の方から、ひたちなか漁港で寿司を食って、一応ガルパンの聖地っぽい大洗マリンタワーに登り、適当に帰ってきました。 行きでは例のあおり運転の実況見分をながら観運転した車両のせいで玉突き事故が発生して、守谷付近で混んでいたのはほんとにひどいなぁと。

f:id:remicck:20190902003138j:plain

エンジン・走り

圧倒的にシビックのほうがいい・・・。 CVTだけど最近乗って全然感じさせないんですね。ただ、パドルでギアを落としたときの挙動(ギアが落ちるというのがよくわからんけど)は、6速ギアのアクセラのほうが使ってて楽しいです。

で、NAとターボでそもそも違うとはいえ、同じ排気量でトルク感もそうだし、スムーズさもそうだし、なんかボロ負け感があって大分辛いです。乗り出し価格はシビックのほうが高いんだけど、いやー、マツダ頼むもうちょっとガソリンエンジン頑張って。 そういう意味だとそもそもディーゼル買いましょうみたいなところもあるかもしれないし、1.5Dにすればよかったって今でもたまに思う。必要十分ではあるけど。

あと、ホイールハウス周りが若干盛り上がるデザインをしているからか、車幅感覚はシビックの方が掴みやすかった気がする。 ハンドルは少し重めだけど許容範囲だし、乗りやすい車だなぁと思った。

内装関係

f:id:remicck:20190902003143j:plain
シビック内装
悪くないんだけど、マツダに乗り慣れてるとちょっと古いなぁと思う。 やっぱしナビが一体型って、昔は好きな2DINナビ突っ込めないの辛いと思ってたけど、なんか統一感ある方がいいかもしれないと思うようになってきた。

ナビから話すと、やっぱしマツコネのおいてある位置が比較的前方かつ上部にある為、視線移動が少なくて良いなぁと再確認。 自分は割とシートを前に出す方なんだけども、そうなると画像にある位置にナビがあると、走行中の視線とナビの角度が付きすぎて前方が疎かになりすぎる感じがあって結構怖かった。

あとセットで、マツダのヘッドアップディスプレイに慣れていると、自然に車速を確認する自分を認知できた。 というのも、頻繁に速度が気になるからシビックではハンドルの隙間から速度を見るわけなんだけど、これがまた視線が外れるから怖い(笑) あれ、安全系の装置としてついてるって認識だったけど、たしかにそれはあると思う。

あと不満なのがクルコンの車速。これがメーター類のところに小さく出るくせに、1km/hごとの指定だから結構指定しづらい。 長押しすると5km/hずつ上がるけど、これも音とかのフィードバックがないから何キロ上がったかわからない。ACCが付いてるからほっといてデカ目に設定してもいいんだけど、とりあえず1km/hごとに指定する需要がどこにあるかわからないので、特にACC搭載車では5km/hごとでいいんじゃないかなぁ。

で、後席の居住空間だけども、あまり後席乗らないからわからないけど見た感じ全然シビックのせいで広い。 あれは長距離後ろで乗ってても楽だろうなー・・・。

まとめ

いや、内装周りとかかなり思いを込めて書いてるけどほんと走りは良かった。 自分が車を購入するときは「言うてエンジンはある程度の所まで来てるでしょ、大事なのはデザインだよね」って気持ちで選んだけど、まだまだメーカーで違いがあるっぽいので次買い換えるときはもうちょっと乗り比べとかしてみたい。 でも、最終的には「好きだから」っていう理由でマツダになりそうw

今回はありがとうございました、また寿司食いましょう!

f:id:remicck:20190902004123j:plain
市場寿し ひたちなか漁港にありますのでぜひ!

おもむろに最近聞いている曲について

90日だかBlogを更新していない忙しめのりっくんですこんにちわ。 なんか広告出ちゃってダサいので、最近聞いている音楽周りを貼っていきます。

主にGoogle Play MusicのTHUMBS UPに突っ込んでるモノを列挙する感じです!

www.youtube.com この間入ったAviciiのNew Albumのラストの曲。
Noonie BaoはAviciiの他の曲でも参加してるんだけど、この曲はすごく好きで出た瞬間からハードループしてる。 しかし亡くなってからもこうやって未発表曲をまとめてくれるのは嬉しい。 ロスすごかったけどなんとか保ててる気がする。

www.youtube.com これもAviciiだけど、亡くなった後に出てくる「Heaven」って曲なだけでもうなんか泣きそうになったよね。

www.youtube.com 確かアイアンマン3?見てるときに流れて、ちょいちょい使われてて知ってるなぁと思い発掘。
知らなかったけど有名な曲だったんだねこれ。

www.youtube.com Beat Saverの曲で発見して、それから譜面もやりつつ、曲も死ぬほど聞いてる。すっごい好き。

www.youtube.com JVNA、どこで知ったんだっけなぁ、確かTwitchでDJしてて、それでYoutube周りを漁り始めた気がする。

www.youtube.com 同じくJVNA。良い。 DJしてる動画から知ったけども、すごく盛り上がる流れで流れてきたのが印象に残ってそのままThumbs up

www.youtube.com 最近アニメ系イベントとかキズナアイ関係とかでわりかし名前を聞くようになったYunomiさんの曲。以上に頭に残る。

www.youtube.com 最近ではないんだけど、ログ追ってたら一番最初にThumbs Upした曲はこの曲だった。
昔、同じルートの深夜の高速走るときに、毎回出発時にTrueを流し始めてたんだけど、ほぼほぼ同じタイミングで同じ曲が流れるから「曲と場所」が完全にリンクしてて、この曲のときすっごいいい感じの場所だったんだよねぇ・・・。

以上!!!!!!!!

Google Play MusicYoutubeの謎なプレイリストのおかげで、知らない曲がガンガン仕入れることができるようになってて非常に良いですね!

Pixel3を買った

約150日前に書いた記事がこちら。 remicck.hatenablog.com

これは事情があるんだ・・・!

  • たまたま妹が携帯を割った
  • 2年以上使っているからそろそろ格安SIMあたりで買い替えたいとのことだった
  • 個人的にはiPhone XRをおすすめしたかったけど格安SIMで運用する場合SIMフリーAppleとかから買う必要があった
  • なんかすごいめんどくさそうだった
  • 俺がiPhone XS売って、その代金でPixel3(セール中)買えばバッチシじゃん

これです。

ということで、iPhoneXSを買った翌日だか、翌週だかに触って最高だなぁと感じたPixel3になりました。
うちの嫁さんが使っていて、ちょいちょい触ってましたので操作感などは把握済みで、やはり最高でした。

Felicaが搭載されたので、本当はPixel3で良かったんですよねぇ、自分がiPhoneXSを買ったときにPixel3の国内情報がなかっただけで。 後やっぱし文字入力は辛かった。戻るボタンが無いのはすぐ慣れるんだけど、キーボードだけは全く慣れない。英語だけならまだしもなぁと・・・。

ということでPixel3、最高です。皆さんも買いましょう。

iPhone Xs 256GB Silver 雑なレビュー

2010年からメインではずーーーっとAndroidを使い続けて、特にXperiaのデザインが好きで大変良い7年間だった。
最近は端末の巨大化から、XperiaのCompactシリーズが非常によくて、XZ1 Compactを使っていたんだけど、XZ2 Compactが(スペックは良いにしても)ダサくて、XZ3も非常にダサいので、カメラ機能がとても強化されたiPhone Xsを購入して使ってる。

ということで、iOS端末を使ったことがないわけではないけど、初メイン端末としてのiPhone Xsレビューを書いていく!!

f:id:remicck:20181021184048j:plain

外観

まずサイズ感について。
これは今までXperiaのCompactシリーズを使っていたことも「でかっ!!!」ってのが最初の印象だったけど、1日で慣れる。

確かに、手から少しこぼれる感じではあるけど、左端からのスワイプ(戻る動作)があるのでそこまで困らないなぁと。

iPhoneは全面に画面が無くなったこともあってすごくシンプルな端末だから、評価も何もシンプルで良いという感じに落ち着いた。

画面

f:id:remicck:20181021184338j:plain

iPhone Xsについて語る上で、OLED Display(有機EL)とノッチの話はしなくてはいけない気がする。

OLED

まずOLEDについてだけど、今まで液晶、それもXZ1 CompactはFull HDですらないモニターから写ってきたので画面の綺麗さには感動している。

焼付きだけは気になってるんだけど、普通に使っているiPhone Xユーザーから何も話を聞かないから、多分多少気をつけておけば問題ないんだと思う。
ビックカメラとかの店頭に置いてあるiPhone Xは本当にひどいなぁと思うんだけどw

ノッチ

これ、まじで賛否両論だし、僕自身あまり良いとは思ってなかったんだけどNetflixをフル画面(ノッチも含めたほう)でみたときに評価が変わった。
映画とかだと多少上下が切れても問題ないと思ってやってみたら、この画面の広さは確かに売れる要素なんだろうなぁと思わざるを得なくなった。
さようなら小型端末。

まず日常使いではノッチの有無はほとんど問題ないと言うか影響なかった。情報が左右に分かれていて、カテゴライズされてるって意味では有りかもしれない。
ダサいかどうかの話になると、うーん、なんかもう市民権を得たというかこれも慣れちゃった感がある。

今はPixel3 XLのノッチはでかいなぁとか言ってるけど、多分使えば気にならなくなるんだろうな。

カメラ

iPhone Xsを買おうと思った理由としてはもうほぼこのカメラだった。
だって後から被写界深度を変えられるってなんだよ!!楽しすぎるだろ!!!

ということでかなりいい写真をいくつか撮ったんだけどとてもプライベートな写真なのでその他の写真を載せる。
カメラは良いけど、どっちにするかで悩んでたPixel3もかなりいい感じのカメラで、今端末を選んでる人は、今iPhoneならXs、AndroidならPixel3でいいんじゃないかな・・・。

f:id:remicck:20181021185315j:plainf:id:remicck:20181021185329j:plainf:id:remicck:20181021185341j:plain

たまたま、ひたち海浜公園にコキアとコスモスを見に行ったのでその写真を。

HEICの画像をどう扱うかだけがまだ課題で、非常にめんどくさい。全体的に対応してほしい。

ゲーム

今の所FGOがダメ、これUnity系なんですかね問題。
ドラガリアロストは快適。
ポケモンGoとかもローディングが早くて最高ですね。

文字入力

これはホントつらい、Androidは良かった。

同じGboardがあるから使ってみたけど、入力中がどこからどこまでかわからないのが辛いのと、やっぱし左に一文字戻るとかのボタンがないとちょっとミスったときに直しにくい。
あと、画面のデカさで唯一すぐに慣れなかったのが文字入力で、少しミスタイプが目立ってるかなぁ・・・。多分慣れる系だと思う。

バッテリー

そこまで酷使してないけどとりあえず困らない。

通知

Androidのほうが良かったかなぁ・・・?これも慣れかな。

ケース

Spigenのものを買った。

https://www.amazon.co.jp/gp/product/B074CN96GL/ref=oh_aui_detailpage_o00_s00

iPhone XsとXではすっごい微妙にカメラの位置が違うみたいだけどこれだとわからない。対応してるのかな・・・?

保護フィルム

Ankerのものを買った。

https://www.amazon.co.jp/gp/product/B07GRX5JLG/ref=oh_aui_detailpage_o00_s00

ガイドがあるから特に問題なく貼れる。滑り具合とかも良いのでおすすめ。2枚入り

まとめ

Pixel3を買った後に店頭で触ったんだけど、これがすごい良いww
いやー、まじでこれ、Pixel3と同時に悩んでたらそっちでよかったかもなぁ・・・。

そんなわけでiPhone触っていきます、これからよろしく!!

DetonatioN FocusMe vs Cloud9のゲームなんかこう・・・書かずにはいられないアレ

最っ高っだった!!!!!!!!!!!!

DNFのTweetを見ていても負けたことがすごく悔しいし自分もめっちゃ悔しかった。 けど、Cloud9が勝ったこともすごく良くて、もう何が何だか分からないからひたすらに打ち込みまくってこの良すぎたゲームを見ていて思ったことをひたすらに書いていく。 多分長くはならない。

何の話?

League of Legendsという世界最高のゲームの世界大会が今日から始まりました。 現在はPlay in Groupという、各国の代表が集まって予選をしている段階。 北米EUや、韓国中国など、ある程度強い地域はシードも持っているので、強い北米チームと言えど、日本などの1段落ちるグループで戦ってから本戦に出なくてはいけない。

そんな中、抽選で日本と北米のチーム、Cloud9が同じグループになって、そのCloud9はかれこれ4年程応援しているチームだったから「Cloud9に負けてほしくないけどDNFに勝ってほしい」みたいなやばい心理状況でゲームを見始めることになる。

f:id:remicck:20181001222844p:plain

LoL Esports

試合

DNFの1戦目、ブラジルのKabun戦は見てないんだけど、これは逆転でDNFが勝ったらしい。

そして本日、Play in Groupが決まってからめちゃくちゃ楽しみにしていた、NAチーム且つ自分が応援するCloud9との直接対決。 世界戦であまりいいところを見せられていない日本代表からは考えられないほど完璧な立ち上がりをしていて、Cloud9を負けている姿を見るのがすごく辛い。

ああこれがCloud9だよ、ナメプかよ!とか思いながらも、決定打にならない感じでちょっと時間が空いた。

Cloud9が好きな理由は、最後の最後まで何をやるかわからなくて、負けまくっていて自分でプレイしてたらサレンダーしてるレベルなゲームでも、最後の最後で最高のエンゲージを決めてゲームに勝ったりする、そういうところがすごく夢を見せてくれてこれはどのチームより優れてると思っている。

もう負けるかもわからんという所まで来たのに、すごく良い当たりを決めてCloud9が優位に立ったんだけど、もっかいヘマするんだよ!!!!!!!!! なんだよ!!!DNFやるじゃん!最高じゃん!!!!!!! Cloud9!!!!!!!!!!!!!!!!!!!!!!!!!!!

ってめちゃくちゃな気持ちになってたんだけど、そっからまた勝っちゃうんだよ、C9・・・。

もうね、疲れすぎた。 最高のゲームだった。

日本勢がここまで戦えたことがとてつもなく嬉しいし、Cloud9がメンバーは変われど、相変わらずの粘り強さで最後まで勝ちを狙いに行く姿勢もすごく好きだ。

終わって

Twitterを見た。 とりあえず英語アカウントでLoLのアナリストの発言とか、選手のコメントなどを見ていった。 どう考えてもCrazyなゲームで、C9のアナリストとかこんなこと言ってる。

ほんとだよ、なんてゲームだよ。

で、日本人選手のコメント。 そりゃ悔しかったと思うんだけど、私はすっごい嬉しかった。最高のゲームだった。

次こそは勝ってほしいし、Cloud9に勝ってほしい、すごいぐちゃぐちゃな気持ちで応援している!!!!!!!!!

明後日、そしてその次のステージでも最高のゲームを見せてほしい。 とにかく良かった、eSportsの未来は明るい!!!!!!!

・・・まじで疲れた。

Google SpreadSheetのGoogle App Scriptから、Microsoft Teamsに投稿する

忘れないように書いておきます。
やりたいこととしては、Google SpreadSheet上に定期的に流したいメッセージを入れておき、ランダムに流すというだけの簡単なことです。

少しつまづきポイントはあったんですけど、多分このコード見ればいけると思うのでぜひ使ってください。

function postMicrosoftTeams(){
  // WebhookのURL
  var url = 'コネクトから追加したWebhook Incomingに指定されているURL';
  // 投稿タイトル
  var title = 'タイトルはこちら!!!!!!!!!!';
    // 投稿メッセージ
  var text = "本文が入ります" ;
  
  // 送信する
  var method = 'POST'; 
  var payload = {
    'title'    : title,
    'text'       : text,
  };
  var params = {
    'method' : method,
    'contentType': 'application/json',
    'payload' : JSON.stringify(payload) // この辺大事っぽい?
  };
  var response = UrlFetchApp.fetch(url, params);
}

以上です。
contentTypeを指定しないとうまく行かなかったような気がします。

payload 部分で指定しているのがMicrosoft Teamsに渡されるjsonになるので、仕様に合わせて変更すると色々いじれるんじゃないでしょうか!!!

f:id:remicck:20180928123601p:plain