とんちむ日記

RubyとJavaScriptと猫が好きです

javascriptのvalidationをchainする

きっかけ

  • いちいちバリデーションする時にif() ~とかするのがめんどくさい。
  • chainでバリデーションを実行したい
  • Railsのvalidationみたいにerrors.full_messagesみたいにまとめてエラーメッセージ取れたら嬉しい

・・と思ってまたライブラリでも作ろうかと思ってたけど調べていたらvalidator.jsのissueにこんなのがあった

var validator = require('validator');

function ValidatorChain(str) {
    this.str = str;
}

Object.keys(validator).forEach(function (fn) {
    ValidatorChain.prototype[fn] = function () {
        var args = Array.prototype.slice.call(arguments);
        args.unshift(this.str);
        if (!validator[fn].apply(validator, args))
            throw Error(fn + ' failed with ' + this.str);
        return this;
    };
});

exports.check = function (str) {
    return new ValidatorChain(str);
};

check('foo@bar.com').isEmail().isLength(5, 64);

引用元: https://github.com/chriso/validator.js/issues/407#issuecomment-118561692

「様々なユースケースに対応するためにあえて標準ではchainできるようにしてない」 みたいなニュアンスの事が書いてあって、上のコードでchainできるようになる。

とはいえこれだとエラーメッセージはカスタマイズしにくいし、chainを全部通してから全部のエラーメッセージを表示するとかってのもできない。あとクライアントサイドなら別にthrowしなくてメッセージだけでいいって事もあるかもしれない。

と思って上に手を入れてこんな感じにしてみた。

import validator from 'validator'
import messages from './messages.js'

function ValidatorChain(str, messages) {
  this.str = str;
  this.errors = [];
  this.messages = messages;
}

Object.keys(validator).forEach(function (fn) {
  ValidatorChain.prototype[fn] = function (...args) {
    args.unshift(this.str);
    if (!validator[fn].apply(validator, args)) {
      const message = this.messages(fn, args)
      this.errors.push(message)
    }
    return this;
  };
});

function check(str, messages) {
  return new ValidatorChain(str, messages);
}

console.log(check('foo', messages).isEmail().isLength(5, 64).errors);

こうすればmessages.jsをこちらで用意すればメッセージをカスタマイズできるし、全てのバリデーションを通した結果の全エラーメッセージを取得できる。

messages.jsは以下のように作る。args[this.str, ...呼び出したvalidatorの引数]という感じになる。

export default function(fn, args){
  const messages = {
    isEmail: `${args[0]}は正しいEmailの形式ではありません`,
    isLength: `${args[1]}文字から${args[2]}文字以下で入力してください`
  }
  return messages[fn]
}

babelでトランスパイルして実行してみた。

$ node build/index.js
=> [ 'fooは正しいEmailの形式ではありません', '5文字から64文字以下で入力してください' ]

errorメッセージの有無でバリデーションの成否を判断するとか、もしくはValidatorChainのプロパティにエラーがあったかの状態を追加すればいいんじゃないかなと思う。

Google Chromeがimportに対応した

対応するって話は知ってはいましたがとうとう対応したんですね。ちょっと興奮して久しぶりにブログを更新してます。

ES2017も正式勧告されたこのご時世にimportを知らないwebエンジニアは少数だと思いますが、使い方はこちら

Safariも最新版はiOSを含めて対応してると小耳に挟んだので他のブラウザ実装状況はどうだろうかとcan i useで調べて見ました。

今のところこんな感じみたいでEdgeやFirefoxもデフォルトでは対応していないもののNot supported by default, but can be enabled. とあるので設定変更するとかで有効にできるようです。

というわけでやってみた。

// hello.js
const Hello = "hello"
export default Hello
// sample.js
import Hello from './hello.js'
console.log(Hello)
<!-- index.html -->
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <script type="module" src="./sample.js"></script>
</body>
</html>

chromeはローカルのファイルだと制限があるのでpythonのサーバーを立ち上げます。

$ python3 -m http.server

http://localhost:8000/index.htmlchromeで開くと・・ コンソールにhelloと表示されました。やったね!

ちなみにnode_modulesには対応してないのでそういうの使いたければ適当な場所に置いといて読み込むとか、これまで通りWebpackなどのモジュールバンドラーを使う必要があるそうです。

とは言ってもグローバル汚染しなくてもライブラリを扱えるのは素晴らしいです。

他のブラウザも早く対応して欲しいですね。

モック用のJSONやCSVなどのデータを大量にかつ簡単に作成できるMockarooを試してみた

どうも、フロントエンジニアになりたい人です。

js側から叩くAPIがまだサーバーサイドで実装されてないけど、js側の処理も先にやっとかないといけないって状況ありますよね・・多分。僕は今のところ経験したことないけどきっとある。

あと、テスト用のデータ欲しいとか。簡単なjsのデモ作りたいけどそのためにAPIを実装するのも面倒だとか、そもそもサーバーサイド作れないとか。

そこでAPIの仕様さえ決まってれば1000件のデータまで無料でJSONCSVや TSVとかなんならSQLもいけるらしい)ファイルを作ってくれるサービスMockarooを見つけました。

こちらが初期状態です。 f:id:tonchix:20170509161216p:plain

Field NameはDBでいうカラム名ですね。Typeはどういうデータを入れたいかを指定します。ランダムでそれっぽいデータを作って入れてくれます。Fakerっぽいやつだと思って貰えば良いかと。

Optionにあるblankは空(DBでいうとNULL)が入る割合を指定できます。50%だったら1000件作れば500件ほどのデータは指定したフィールドに値がないものになります。

fxは生成されるデータを加工したい場合にここで指定できるようです。用意されている関数を使うこともできますし、Rubyが書けるならRubyを使って加工することもできます。例えばthis.upcaseとやれば全部大文字にするとか。

こんな感じで英語わかんなくてもぱっと見た感じ簡単に作れそうですよね。 でもちょっとだけ悩んだのが、こういうデータが欲しい時。

{
  "friends": [
    { "first_name": "foo", "last_name": "bar" },
    { "first_name": "hoge", "last_name": "huga" }
  ]
{

以下のようにすれば良いみたいです。

f:id:tonchix:20170509155905p:plain

↓こういうのが欲しい場合は 上の例からJSON Arrayのフィールドを無くせば良いです。

{
  "friends": {
    "first_name": "foo",
    "last_name": "bar"
  }
}

また、単純な配列が欲しいだけならば、フィールド名[2]とかやると[]の中で指定した大きさの配列になります。

あとはダウンロードして適当なところに置いてjsから呼び出せばOK!やったー。しかも無料の範囲なら登録不要みたいですよ、楽ですねー。

他にも公式のnpm packageもあってこちらはAPIkeyが必要なので登録する必要がありますが、無料プランだと1日200リクエストまで使えます。詳細はリンク先をみてもらえればなんとなく雰囲気掴めると思います。

実際に試してみました。下のようにclient.generateとすればPromiseを返してくれるようです。generateに渡すcountの値が1の場合はPromiseから取り出す値は配列ではないので注意してください。

const Mockaroo = require('mockaroo');

const client = new Mockaroo.Client({
  apiKey: '******' //自分のAPIKeyを入れてね
});

client.generate({
  count: 10,
  fields: [{
    name: 'id',
    type: 'Row Number'
  },{
    name: 'friends.first_name',
    type: 'First Name'
  },{
    name: 'friends.last_name',
    type: 'Last Name'
  }]
}).then(records => {
  for(let record of records){
    console.log(record.id, record.friends.first_name, record.friends.last_name);
  }
    console.log(records[0]);
});

結果は以下のようになります。(最後のはちょっと整形してます)

1 'Susy' 'Ingarfill'
2 'Jakob' 'Duligal'
3 'Lanie' 'Jamieson'
4 'Joanna' 'Betham'
5 'Magdalena' 'Castledine'
6 'Roxine' 'Cogdon'
7 'Bea' 'Trevaskis'
8 'Gertruda' 'Bannard'
9 'Dorelle' 'Moors'
10 'Bruno' 'Dorot'
{ 
  id: 1,
  friends: { 
    first_name: 'Ermin',
    last_name: 'Rosenfarb'
  }
}

簡単だし便利ですねー。

ただ日本語対応してないっぽいので日本語のデータ欲しいならばfxのとこで無理やり日本語データ作るか、これじゃなくてFakerとか使うかする必要がありますね。

サイトではSQLも作れるのでDBにテストデータを作るのにも便利だなーと思いました。僕はRailsを主に使うのでその辺の必要性はないですが、データを作るのが面倒な開発環境ならそこそこ使えるかも知れませんね。

もっといい方法あるよーって場合はぜひ教えてください。

初心者が質問サイトで安易に質問すべきではない理由

はじめに言うと自分自身、stack over flowの情報には助けられているので質問サイトをディスっているとかではないです。

質問サイトって便利ですよね、ググったら同じ悩みを抱えている人がすでにいて、それに対して詳しい人がすでに素晴らしい回答をしてくれている。無償で!そういうエンジニアって素晴らしいなぁと思います。

で、今まで助けられているぶん、僕も貢献できたらと思ってteratailに登録して答えられそうなものには回答してみているんですが。

質問の内容がひどい

まぁ・・ひどいです。ひどいと言ってもいくつかあるのでまずその特徴をあげてみますね。

まず日本語を勉強したほうがいい

コミュ障っていうのは何話していいかわからないとか、極度に緊張しちゃうとか、まぁそういうやつだと思うんですけど。そういうタイプではなくて、プログラミングよりも日本語の勉強をした方が良さそうな人もいます。

「てにをは」がおかしいとか(自分もたまに長文書くとやらかしますが)言いたいことがさっぱりわからない人たちがたくさんいます。

コミュ障というか、日本語できない人ですね。(母国語が日本語でないなら仕方ないですが・・それなら母国語で質問できるサービスあるのでは・・?)よくこんな説明で仕事できてんなってくらいに酷いものがあります・・。

回答者は質問のコードの前に質問者の意図を理解しないと行けなくなります。質問サイトの回答はボランティアなんであえて日本語もどきの暗号を解読しようとする人は少ないでしょう。

ググればわかる内容

「これ聞かなくてもググればすぐに出てくるよ?」と思うようなことを質問されている場合があります。でも優しい回答者の皆さんは「ググれカス」とは言わずに教えてくれます。(リンク貼り付けるだけの場合もあるけど)正直この場合はググれと言ってやった方が本人のためかもしれないですね・・。

デバッガー使えばすぐにわかる内容

デバッガー使うのは基本中の基本ですよね。ブレークポイント置いてコード実行して変数の中身や処理の流れを追って行けば自ずとわかるはずです。ツールの使い方を学べばすぐに解決するはずなのになぁ。

つーかエラーメッセージに書いてある

これはびっくりしますよ。「え、書いてるじゃん?」と思うんですが・・おそらくエラーメッセージを読む習慣がないのでしょう、英語に対して拒否反応を示してるんでしょうね。エラーメッセージをコピペしてググるか翻訳するだけでも違うのになぜそれをやらないかなぁと思います。

回答者をエスパーかなんかと勘違いしている

このパターンがすごく多いです。すごいエンジニアの皆さんはある程度の経験と勘で質問の意図を汲み取ってくれるんですが・・(すごく優しいですよね)情報が少なすぎる!

ベタベタとソースコードを貼り付けて、「うまく動きません。よろしくお願いします」

わかるかーっ! f:id:tonchix:20170505172319j:plain

↑酷い質問を見たときの僕の心境

teratail側が初心者にもわかりやすいようなテンプレートを用意してくれているにも関わらずどうしてこうなるんだろう・・。

エスパーじゃないんでからあなたの思考がわかるわけではないんです。まず、何がどう動かないのか明示してください。(5W1Hって聞いたことあるでしょ?ないならググって)

そしてあなたはどういう手法を試したのかとかもできるだけ書かないと回答者の時間を奪うだけです。(くどいですがボランティアなんですよ?善意でわざわざあなたのために貴重な時間を割いてくれてるんですよ?)

ソースコードも、できれば手元で動かせるだけのものがあればいいです。(かといって余計なものまで貼り付けられても困る)もちろん公開できるように加工した上でです。めんどくさいとか言うな、答える方もめんどくさいんだ。

的確な回答を早く欲しいのなら、回答者の身になってこちらもできる限りの情報を提供しましょう。それができないのなら自分で解決しないといけませんよ。

なぜ初心者は安易に質問すべきでないか

ここでやっとタイトルに戻ります。

僕は上記の質問を見てきて、安易に質問することで自分の問題解決能力を磨く機会を失っているのではないかと考えています。

「わからない」 => 「質問サイトで聞けばいいや」

こういう安易な発想になってしまっているのではないかと思います。

もちろん、質問しつつ自分で調査しているのなら良いと思いますが。そうでなければ効率的なデバッグ手法やググるためのキーワードのセンス(結構大事ですよこれ)、英語のサイトを頑張って読む経験などが得られないのでとっても勿体無いです。

一度はわかるまで自分でとことん調べてみると苦労しただけあって身につきますし、その過程で試した手法などは次回の調査で役にたちます。ベテランのエンジニアの方々がすぐに回答できるのはたくさんの知識とこのような苦労した経験をたくさんしているからに他なりません。

質問サイトを使うなとは言いません。どうしようもないときだってあります。諦めてしまうよりはずっといいでしょうし。周りに聞ける人がいないかもしれません。

ただ、ハマった時はチャンスなんです。自分でデバッグする、調査する、仮説を立てるなどの貴重な機会なんです。特に経験のないことならば新しい知見を得られる可能性があります。なんならそれがQiitaとかブログのネタになります(笑)

そういった折角の機会を無駄にしないためにもまずは自分で解決する努力をしましょう。

JavaScriptは学ぶべきか

・・という質問が某tのつく質問サイトでされていました。質問者は内容から察するにRailsエンジニアっぽかったです。(どうでもいいけどwebで口頭よりも具体的に質問しやすいのに質問下手くそな人多いですよね。そして回答する人みんな優しいなぁ)

だとすれば逆に聞くがなぜいらないと思うのか・・。CoffeeScriptはオワコンだぞ。

結論からいうとwebエンジニアならば必須です。

話は変わりますが、自分の会社はJavaの言語をメインにやっています。web系です。

しかし、みんなwebエンジニアなのにJavaScriptの知識が浅い。

このReactやVueなどが主流のご時世に「jQueryだけちょろっと書ければいい」と思っている人が大半で(印象だけど)、JavaScriptのESnextどころか基本文法も怪しい。関数スコープを理解している人間がどれだけいるんだろうってレベル。

なまじjQueryでちょっとしたことは実現できるから危機感がない。人間どうしても自分の経験の範囲でしか世界を認識できませんから、世の中のwebアプリケーションのjsは全てjQueryで書かれていると思ってる人もいるのかもしれませんね(冗談でなく稀にこんな人いるからびっくりします)。これから転職したり、新プロジェクトが立ち上がってjQueryを使ってなかったらどうするんでしょうね。

js一行も書かないでやっていくんですか?

webエンジニアなのに??

濁流のごとく流れの早いフロントエンドの最先端攻めろとは言いません。ただ、基本文法とかややこしいところたくさんあって絶対一度はハマるんだからちゃんと勉強しといて損はないはずです。というか仕事で使う言語のことですよ??なぜ学ばないんです?

PHPJavaの知識がほぼないのにライブラリの知識だけでサーバーサイドの実装しようと思わないでしょう?

目の前の仕事でいっぱいいっぱいなのでしょうか?まぁそういう人もいるかもしれません・・。

けれどその仕事を効率よく進めるためにもJavaScriptもっ勉強しようぜ、みんな少しはjs書くでしょ?

JavaScriptには関数スコープ、XHRやPromise、ホイスティング、strictモード、ESnextとか他の言語と比べてややこしくてハマり易いところが盛りだくさんです。あらかじめ学習しておけば事前に回避できますし、問題を発見しやすくなります。

昨日書いた記事に入門書籍とかまとめてあるので、みんな頑張りましょう。

これからJavaScrirptを学ぶ人におすすめしたい書籍

f:id:tonchix:20170504001032j:plain プロジェクトがReactだとかAngularだとかVueだとか、最近流行りのフレームワークやライブラリを使ってれば別なんですが、例えばjQueryでDOM操作とXHRするくらいだったりするとプロジェクトに参加しているエンジニアはあんまりJavaScriptをしっかり勉強しない傾向にある気がしてます。

ですが、フロントエンドが専門でなくともWebエンジニアたるもの最低限のJavaScriptは書けるようになっておくべきです。

4月からWeb業界でエンジニアとして働き始めたという人もたくさんいると思うんで、そういう方々はjQueryさえできれば大丈夫とか言う先輩には気の毒な人を見る目で愛想笑いだけしておいて、ぜひJavaScriptをしっかり学んで欲しいと思います。(注:決してjQueryが不要とは思いません。長期的にはなくなって欲しいと個人的には思いますし、いずれはそうなっていくと思いますが、少なくとも「レガシーな環境」や「UIがそこまでリッチである必要はないプロジェクト」で今後も使われ続けていくでしょう)

なぜJavaScriptをしっかり学ぶべきか、理由は「JavaScriptは難しいから」この一言に尽きます。

特にサーバーサイドのメインの言語がJavaのような静的型付け(それも型宣言がわざわざ必要な)言語だと動的型付けのJavaScriptはややこしく、どのように動作するかわからず不安に感じると思います。

ではその「しっかり学ぶ」にはどういう指針で学習を進めていけばいいのか。

よく初心者はjQueryから入りがちなんですが、jQueryはあくまでJavaScriptのライブラリの一つなのでJavaScriptの基本的な知識がないと思わぬところで苦労します。まぁDOM操作は初めてやると見た目の変化が楽しくて面白いのでとっかかりとしては悪くないと思いますが、以下の書籍などで入門から応用まで体系的に学んでいきましょう。

オススメの書籍

JavaScript本格入門 山田 祥寛 (著)

持ってる人は大正解ですね、この本の著者である山田氏はその他の書籍でもわかりやすさに定評があります。リンク先のアマゾンレビューでも高い評価を受けていますし、僕自身、この本で学習しましたが非常にわかりやすいです。

体系的に基本的なところから学べるので隙間なくJavaScriptの基礎を学べるはずです。最近、新版になって以前あったjQueryの項目が消え、ESnextについての言及が増えました。時代に合わせた素晴らしい改定だと思います。初心者はまずこの本で入門することをおすすめします。(プログラミング初心者ではなくJavaScript初心者はです)


開眼!JavaScript Cody Lindley(著)、和田祐一郎(訳)

これも以前から評判が良くて王道と言える本で持っている人も多いのではないでしょうか。山田氏の本でしっかり基礎を学んでればこの本は必要ないとも言えそうですが、本の厚さは半分ほどでJavaScriptのつまづきやすい、ややこしい言語仕様についてよくまとまっています。

復習用に買っておくという手もありますし、JavaScript中級者はこちらだけやるのもありでしょう。初心者というか初心者が基礎を学んだ上での次のステップとしてこの本はオススメです。


JavaScript:The Good Parts 「良いパーツ」によるベストプラクティス Douglas Crockford(著)、水野貴明(訳)

少し古い本にはなりますが、こちらも良い本です。これも中級者向けの書籍ですね、JavaScriptをより深く学びたい方向けです。

JavaScriptには歴史的な要因(ブレンダン・アイクによって短期間で作られたとか、ブラウザベンダー各社が独自拡張したとか・・etc)によって言語仕様として様々な問題点があります。そういった悪いパーツを使わずに良いパーツを使った手法が書かれているので是非読んで見ることをおすすめします。


JavaScript Promiseの本 azu(著)※無料

JSer.infoを運営してるazu氏が書いた本。ES2015のPromiseについて詳しく説明されています。jQueryしかやらない人でもDeferredの仕様を理解するのに役にたつはずです。非同期処理を行うならばPromiseは必要不可欠になりつつあります。この本でしっかり学習しておきましょう。なんといっても無料で読めるのが素晴らしいですね。web版はコードを実行したり、編集したりできます。pdfでダウンロードして隙間時間にスマホで読んでもよし。

おしまい

さて、4つほど紹介させていただきました。JavaScriptの世界は広大なのでもっと知るべきことがある!という意見もあるかもしれませんが、フレームワークなどを考慮せずに初心者から〜中級までと考えるとこんなところだと思います。その後で必要な知識を積み重ねていくのが良いと思いますよ。

プライベートを大事にしたい人ほど学習するべき3つの理由

僕は転職してエンジニアになったので始めっからエンジニアの人と比べて自分は年齢の割にスキルがありません。

ですから危機意識を持って普段からほぼ毎日のように学習をしているわけなんですが、全く学習をしない・・どころか技術的なことに対して全く興味がない人がいます(エンジニアなのにっ!)

まぁ人それぞれなんで別に仕事できてればいいんじゃないかと思います。ただ、エンジニアに限らず「できる人」は必ず何かしら努力してますね。

「学習しない人は、なぜしないんだろう」とまぁ・・お節介なことを考えてみて、一番はじめに思いついた理由は「面倒だから」、それからプライベートな時間を大事にしたい。勉強する暇があるならアニメみたり、ゲームをしたり、なんやかんやしたいってわけでしょう。

ただね。

そういうプライベートを優先したい人ほど学習すべきだと思うんですよ。特にエンジニアならば。

なぜって、よりプライベートな時間を確保できる可能性があるからです。

どういうことかわからない?ではいくつか理由をあげてみますね。

バグの原因がわからなくて帰れないということが減る

スキルの高いエンジニアはデバッグ手法や調査方法、便利なコマンドやツールをいくつも駆使して仕事を行います。めんどくさいことがあれば、こういうことができるツールがないだろうかと調べたり、場合によっては自分で開発してしまったり。

なので問題発生から解決までがとっても早いんですね。「今日中に終わらせないといけないのにバグの原因がわからない」、「機能を実装するための技術がわからない」ということも普段から学習しておけばゼロにならなくともゼロに近づけることはできます。結果的に仕事を早く切り上げることができますね。

給与(報酬)が上がりやすい

ま、これは一概に言えたことではないですが。ただIT業界というものは人の移動が激しいもので、エンジニアは割と簡単に転職する人が多いです。

転職を機にフリーランスとなって収入をぐんっとあげる人はたくさんいますね。(フリーランスの平均報酬は月に60万だそうです。100万とか稼ぐ人もいますね)

良いスキルセットを持っていればフリーランスになりやすいですし、フリーになって契約するときもスキルに応じた高い報酬の案件を選ぶことができます。

趣味にお金を使いたい人にはお金はいくらあっても足りないですよね。

時間を確保しやすくなる

フリーランスの案件は時間に融通が効くので(水土日休みとか金土日休みとか週3勤務とか)趣味に使う時間をたっぷり確保することができます。

フリーランスではなくとも、リモートワークで働ける会社に勤めれば正社員でありながら、通勤から解放されてそのぶん時間に余裕ができますよ。ただ、リモートワークで働く会社はエンジニアのスキルも高い(これは僕の主観ですが・・)気がしてます。

フリーランスになったり、良い環境の会社に転職したりするためにも日々の学習は欠かせません。

・・

と、こんなところです。

僕の主観で書いている部分もありますが、概ね間違ってはいないでしょう。学習を日頃からやっておけば「今の会社が嫌な会社だったらすぐにやめて他に移り易くなる」というメリットもありますね。

みなさん気づいてると思うんですが、学習するのは最終的には全部自分のためなんですよ。

高い報酬、良い環境、少ない勤務時間、そういう「自分に都合の良い待遇」を選ぶためには優位な立場に立つための武器が必要です。

学習するということは来たる未来のためにその武器を鍛えることに他なりません。

それでも今のプライベートを大事にしたいというのはわかります、ですからほんの少しからでも学習を始めてみようじゃないですか。 一日30分でもいい、1年続ければ結構な時間になります。

いつのまにか学習することが楽しくなってくるはずです。より良い自分の未来のためにも今を少しだけ頑張ってみませんか?f:id:tonchix:20170502000234j:plain