Articles

直近で書いた記事をピックアップしています。
技術系の記事・アウトプットはブログとZennがメイン(Qiitaは過去記事が多め)です。
noteにはそれ以外で残しておきたい出来事などを気ままに書いています。

情報処理安全確保支援士になった

サムネはリスです。RISS(Registered Information Security Specialist)です。 なりました。 続きをみる
2022/10/03 from note

E2Eテスト実行を検知するTips

先日、とあるABテストを実施したところE2Eテスト上でABテストに当選すると、テストが落ちるという問題に直面した際に教えてもらったテクニック。 ブラウザが自動操作されているかどうかは、 windows.navigator.webdriver というプロパティに格納されているそう。 https://developer.mozilla.org/ja/docs/Web/API/Navigator/webdriver MDNによればexperimentalな機能であるようだが、主要なブラウザでは対応済みのためあまり気にせずに使うことができそうです。 if (!window.navigator.w...
2022/09/12 from zenn

Wake on LANの設定をしたのでメモ

めちゃくちゃ久しぶりにブログ書いている気がします。 ひょんなことから自作PCを組んだので、Wake on LANを使って起動できるようにしておきました。設定内容のメモ。 PCのスペック 設定と関係ありそうなところだけ マザーボード: ASRock B660M-ITX/ac OS: Windows 11 Pro 起動するPCの設定 UEFIを起動して以下の設定を実施 F6キーを押下しAdvanced Modeに切り替える Advancedタブに切り替え、ACPI Configurationを開く→ PCIE Devices Power Onの項目を有効(Enable)に変更 ここまでやったら設定を保存しUEFIを終了 Windowsを起動して、デバイスマネージャーからNICを見つけて開く。このマザーボードの場合のNICはInterl(R) Ethernet Connection I129-Vだった。 詳細設定タブを開き、Wake On Magic Packetの項目を有効にする(自分の場合は最初から有効になっていた) ここまでやれば設定は終了。 実際に起動する ひとまずMacからネットワーク越しの起動を試みることに。 Windows側のMACアドレスはWindows機のコマンドプロンプトなどを開いて ipconfig /all として、出てきたNICの物理アドレスのところから確認することができる。 i-think-it.net あとはこんな感じの手順で。 雑に要約するとbrewを使ってwakeonlanコマンドを入れて、 wakeonlan <MACアドレス> で実行してあげればよい。ちなみに前述の手段を使ってMACアドレスを取得するとハイフン区切りになっているが、wakeonlanコマンドが受け付けるのはコロン区切りなので適宜置き換えて実行すればOK。 無事に上記手順でシャットダウン状態およびスリープ状態からのLAN越しの電源投入ができることを確認した。VPNなどを経由すれば外出先からでも電源を入れられそうでよかった。 これがダメだったらSwitchbotの電源押すロボット買って本体に張り付けるか、と思っていたので無事に動いてよかった。
2022/08/23 from blog

食品衛生責任者の講習を受けてみた。

タイトルの通りですが、食品衛生責任者になるための資格を得る講習を受けました。 本業はITエンジニアです! 飲食店をやる予定も特にありません!! 続きをみる
2022/08/02 from note

静岡旅行の写真たち

先日、伊豆・伊東・下田あたりに旅行に行ってきたのでその写真たち。 カメラはいつものごとくSIGMA fp。 レンズは、以前から持っていた28 - 70mm F2.8 DG DN | Contemporaryに加えて、先日発売されたばかりの16 - 28mm F2.8 DG DN | Contemporaryを購入し持っていった。 続きをみる
2022/07/14 from note

身長186cmにありがちなこと31

中吊り広告頭打つ 吊り革持つ時根本持つ 「●cmでいいから分けてよ〜〜」 初対面の人との会話、初手「身長何cmあるんですか〜?」か「でかいですね!?」になりがち 羨ましがられる割に恩恵を受けてる感じはしていない はじめしゃちょーと同じ身長 ユニクロのジーンズ、裾直し不要 キッチンの流し台低い 換気扇低くて頭打つ 満員電車でも実はそんなに苦しくない シングルベット、まっすぐ寝るとちょうど身長と同じくらい 「背高くていいですね〜」って言われがち 「ご家族も高いんですか?」 そんなに高くない バスケとかやってました?とか聞かれる 足もでかい 背が高いだけでは別にモテない 人混みの中で割と目立つ カウンターチェアが好き 廊下の電球変えるのに踏み台いらない カーテンつける時も踏み台いらない 中学3年間でありえない成長をした過去がある スペースマウンテンは頭上が一番怖い 車の信号待ち、停止線に近づきすぎると信号機が見えない ハンドル膝に当たる ドリンクバーは覗きこまないとグラス見えない バイク、足つきが悪いという概念が存在しない 美容院めっちゃ椅子下げられる 自転車のサドル大体一番上 LCC乗ると膝が前のシートに接触する 誰も掃除しないような棚の上のほこり見えがち でもやっぱりなんだかんだ身長褒められると嬉しい 続きをみる
2022/07/03 from note

合格祝いしたら救急車で運ばれて入院して楽しみにしていたイベントに参加できなかった日記

突然ですが、ワタクシ25年の人生で初めて入院をしています。 続きをみる
2022/06/25 from note

親知らずを抜いた日記

2022/05/28、親知らずを抜いた。右側の上下2本。 年を重ねるごとに、未知の体験への恐怖心が増えていっていることを感じる。抜歯も例外ではない。(正確にいうと矯正をしていたことがあるので乳歯の抜歯は経験あるが) 続きをみる
2022/05/29 from note

ブロンプトンを買った。

最高の折り畳み自転車、ブロンプトン(BROMPTON)を買った。そんな話。 ブロンプトンって? 続きをみる
2022/05/22 from note

最近の出来事を写真つきで振り返る(2022年3月〜5月)

記録ついでに最近の出来事とか、撮った写真を載せていこうと思う。 ただの日記です。 続きをみる
2022/05/17 from note

SHARE LOUNGEがすごかった話

隔週くらいで大学時代の後輩たちとコワーキングスペースとかでもくもく会をしています。 いつもと違うコワーキングスペースに行ったら、めちゃくちゃよかったって話。 それがここ 続きをみる
2022/05/16 from note

パスタ作ったお前〜 #28

今日のごはんのコーナー。 続きをみる
2022/03/14 from note

お金をかけた手抜きの話 #27

ごはんのコーナー。 今日はこちら。 続きをみる
2022/03/13 from note

冷蔵庫を眺めて料理を作るイケメンになりたい #26

二日ぶり、今日のごはんのコーナー。 (作ってないとかじゃなくて普通に更新忘れてた) 続きをみる
2022/03/10 from note

シェフの気まぐれロコモコ 〜カーボンを添えて〜 #25

今日のごはんのコーナー。 続きをみる
2022/03/08 from note

一人暮らし3年目、ついにチャーハンを習得 #24

連続投稿が途切れて悲しみのあまり2日もサボってしまいましたが今日のごはんのコーナー。 続きをみる
2022/03/07 from note

確認不足 #23

今日のごはんのコーナー。 昼 続きをみる
2022/03/04 from note

レタス has gone #22

今日のごはんのコーナー。 晩御飯。 続きをみる
2022/03/03 from note

静岡ではおでんにうどんを入れるんですか? #21

昨日はナメた記事を書いてしまった。 続きをみる
2022/03/02 from note

ドォォン #20

丼。 続きをみる
2022/03/01 from note

スタッフが美味しくいただきました(フードファイト) #19

今日のごはんのコーナー。 今日は晩ごはんで事故が起こります。 続きをみる
2022/02/28 from note

アボガドじゃね〜し #18

今日のごはんのコーナー。 怠惰な時間に起きてしまったので今日は晩御飯だけ。 夜 続きをみる
2022/02/27 from note

皿が変わると料理のおいしさ2割増な気がする #17

きょうのごはんのコーナー 昼 続きをみる
2022/02/26 from note

餅は餅屋、牛丼は松屋 #16

だんだんとネタ切れ感が出てきたきょうのごはんのコーナー。 今日は一食分だけ。 続きをみる
2022/02/25 from note

人生最高のエビチリを叩き出した #15

きょうのごはんのコーナー。 今日は人生最高のエビチリを作りました。 続きをみる
2022/02/24 from note

2週間ごはんの写真を撮り続けた #14

きょうのごはんのコーナー。 今日はオマケが本編。 夜 続きをみる
2022/02/23 from note

🐟🍛 #13

きょうのごはんのコーナー。 今日は珍しく昼ごはんの方が気合い入ってたかも。どちらにしても割とやる気なしDayだったので雑ごはん。 続きをみる
2022/02/22 from note

転職から1ヶ月経ったので転職ドラフト体験談を投稿するぜ

こちらの記事は転職ドラフト体験談投稿キャンペーンに参加しています job-draft.jp 文章ばっかりなので無関係ですが最近のデスクの様子を添えておきます こちらのブログに書くのは転職後初なのですが、2021年8月9日より転職してnote株式会社で働いています。 入社直後の気持ちなどは下記noteに書いたのでもしよければご覧ください。 note.com この記事では冒頭にもあるように、今回の転職に利用した「転職ドラフト」というサービスについて、自分が転職にあたって考えていたことも交えつつ書いていきます。 0. お前誰 どれくらいのキャリアで、どんなことをやっていた人なのかということがわかった方が良いと思うので簡単に。 情報系の学部卒 2019年新卒 noteは2社目(= 今回の転職が初めて) 前職もWeb系のベンチャー。React Nativeによるアプリ開発→ElmによるWebフロントエンド開発みたいなことを主にやっていました。時々Golang使ったサーバーサイド開発のお手伝いもしてました。 趣味の延長で会社のサイドプロジェクトで使うWebアプリやSlack botを作りまくってた (将来的に他領域をやりたくなることもあるとは思っているが)フロントエンド領域を深く学んでいきたいという気持ち 1. 転職を考え出したきっかけ・転職ドラフトに登録したきっかけ 結論から先に述べると「転職が自分のキャリアを実現する近道だと感じたから」です。 新卒2年目終わり頃から3年目にかけて、キャリアのことについてなんとも言いがたいモヤモヤを抱えることが増えたことをキッカケにコーチングを受け始め、コーチと対話して自分のキャリアについて考えたタイミングがありました。 そこでたくさん時間を使って考えたのは「自分はやはり技術者としてスペシャリストになっていきたい」ということでした。 その理想状態と照らし合わせたとき、以下のような問題があるのではないかと考えました。 日々の業務がルーチンワークに近い状態・既にある知識の横展開になってしまっていることを感じた 技術者としてあるべき姿・やるべきことを外的要因によって実現できていない状態が続いてしまった 工数の問題や事業のフェーズとの不一致など。 特定の技術領域のエキスパートと働いてみたいと感じていた 技術的に難易度の高い仕事をしてみたいと感じていた フロントエンドでいうと、高いパフォーマンス要求/凝ったユーザーインタラクション/アクセシビリティなどWeb標準の深い理解や経験値を要求される仕事をやってみたかった 大きく4つを挙げましたが、最初の2点に関しては自分の立ち振る舞いを変えたり、上司と方向性を相談することで転職せずとも叶えられる余地はあったと思います。ただ、3点目4点目に関しては自分の努力によってすぐにどうにかなる問題ではなかったので、転職も視野に入れてみようと思いました。 ちなみに、数ある転職サイトから転職ドラフトを選んだ理由自体は割と単純で こういった体験記紹介記事を以前どこかで読んで知っていたこと レジュメを登録すればあとは受身で良い (この時点では転職するかもしれないというレベル感なので)「市場価値を知りたい」という目的OKと公言されている あたりです。Web系の転職というとぶっちゃけ転職ドラフトしかパッと思いつかなかったという感じです。 2. レジュメ審査 転職ドラフトにはレジュメ審査という制度があります。 ドラフト(=企業側が求職者に対してオファーを出す回)に参加するには、転職ドラフト運営にレジュメ(職務経歴やキャリアなどについて入力したもの)をみてもらい、審査に合格しておく必要があります。 ここに若干のハードルを当初感じていたのですが、自分はすんなりOKが出ました。内容を丸々見せるわけにはいかないので、どんなことを書いたか簡単に挙げると以下のような感じです。 将来どんなことをやりたいか これまでやってきたこと 業務で作っていたアプリケーションについて。特に、どういったプロセスでやっていたか・そのプロセスの中で何を担当していたか・どのような技術を使ってやっていたか・やっていた中で困ったこと・それらをどう解決したかをなるべく漏らさずに書いていくようにしました。Markdownが使えるので読み手がウッっとならないように構造化しつつ、書いていくとあっという間に推奨文字数は超える感じでした。 自分の場合は2年間かつ1社1プロダクトということでメインの業務の中でかけることの絶対的な量が少なかったので、サイドプロジェクトで自主的に作っていたプロダクトについても書きました。今思うと、こちらの話は既存の技術スタックに囚われず好き勝手やっていて、語れるポイントも多かったので書いて正解でした。実際面接の場でも、割とウケがよかったような気がします。 将来身につけたいこと フリーフォーマットで書くと大変ですが、ある程度入力フォームがあったり、入力中に「こういったことに触れて書くといいですよ」というサジェストを出してくれるのでそれほど大変だったなーという感じはしませんでした。1〜3を挙げましたが9割くらいは2でそのほかは長文を書いてる人は少ない印象です。 無論NDAに触れるような内容はNGですが、そうではないけど一般に公開はしづらいという内容でも、企業の採用担当者にだけしか見えないように設定することもできるので自分のやってきたことの棚卸し的な意味も込めて、概要をザクっと書いて、その上で各項目について具体的なところまで触れて書くようにしました。 3. ドラフト参加 レジュメの審査に通ると、その次に開催されるドラフトに自動参加扱いになるのであとは待つだけです。 ドラフト期間自体は何週間かあるのですが、どの企業も最終日2日前とかから指名を入れてくる感じです。実際、指名をもらえるとその指名に対して承諾か辞退が選べて、承諾の場合もいきなり採用面接に進むこともできれば、いったんカジュアル面談という形でざっくり話を聞くみたいなこともできます。 自分の場合はありがたいことに想像の3から4倍くらいの数の会社に指名をいただいたので、その中から自分の条件に合いそうな会社を選んでまずは全社カジュアル面談という形で予定を入れていただきました。 自分はこの段になってから、「もし本当に転職するならどういう条件のところ?」というのを具体で考え始めたので結構バタバタとしてしまったので、事前に考えておくと良いと思います。 自分の場合は前述のきっかけと照らして以下のような条件に合致する会社に会ってみるということをしました。 技術投資に対してある程度理解があるか 技術的難度の高い課題があるか 社内にフロントエンド領域に対する深い知見を持ったメンバーが居るか 自分が技術者としてスペシャリストになる上で「この環境に身を置いて揉まれることができそうか」という直感(?) また、これらに加えて、自分がどういった環境だと働きやすいかというのも考慮に入れました。 例としては以下のような感じ。 リモートワーク主体の働き方が許容されるか 神奈川県に引っ越してしまったので週5通勤は避けたい たまにいきたくなった時・集まった方が効率の良い仕事をするときにオフィスに行けると尚嬉しい 人数規模が大きすぎない 人生のキャリアの中で一度は大企業で働いてみたいという気持ち、好奇心はあるのですが今じゃない感じがした(完全にイメージだが、大企業は配属によって働き方やそこで得られる学びの量・質にバラつきがあるように感じていた) 前職が全社200人規模の会社で、居心地がよかった。 事業・プロダクトのことが好きになれるか やはり自分がモノを作っているぞ、という実感を持ってコードを書くのが感覚として好きだから。 実際にお会いしてお話を聞いてみると、環境や人の面では申し分ないけど事業に対して興味が持てない会社さんもあったりしたので、自分の軸を具体レベル決めて話を聞くのは大事なのではないかなと思います。 この時点でも、「様々な面でみて条件が良い会社があれば転職」そうでなければ「現状維持しながら考える」という二つの選択肢で揺れていたので、話を聞いた中で唯一前述の条件を満たしていたnoteの選考に進むことにしました。 その時にも正直に「転職するかしないか気持ちとしては半々で、選考に進んで内定をもらっても転職せずに現職に残るかもしれない」と伝えて選考を受けていました。 こういう話って皆さん正直にするもんなんでしょうかね?初めての転職かつ、身近に相談できる人がいないとこういう細かいところは常に悩みながら進むことになってしまうので、ぜひその辺相談できる人が身近にいる方はしたほうが良いと思います。(地味に気遣いで精神すり減っていくのでw) もしくは、転職ドラフトにそういったコンテンツや相談サービスなんかがあったら喜んで使うのでぜひご検討いただけると... 4. 採用面接 この辺は転職ドラフト関係ないのでざっくり書くと、カジュアル面談終わって数回の面接を経て内定をいただきました。 個人的な話にはなりますが、前職に内定をもらったのはサマーインターン経由だったので、まともな就職面接というのは初めて経験しました。 敬語とか普段使い慣れてないとなかなかしどろもどろになってしまうのですが、営業職の面接ってわけではないし、それでしどろもどろになるくらいならば、敬語はベストエフォートでなるべく明るくコミュニケーションを取るという方向に舵を切りました。内定をいただけたので結果としては正解だったのかもしれないですね。 というわけでまとめ ざっくり書くつもりが結構大作になってしまいましたが総括すると、少なくとも自分の転職において転職ドラフトはなくてはならないサービスでした。 複数回転職をしてきた方ならまだしも、自分のように初めての転職となると自分の市場価値を正しく見積もることは難しいと思うので、自分と同じような経験値のエンジニアがどれくらいのオファーをもらっているのかを事前に確認できるシステムは大変ありがたかったですし、転職活動というのは本当に体力を使うので(ほんとマジで)いざ面接進んで内定もらってみたら年収が思ったより低くて辞退、、、みたいな一番重要であろう給料の部分での不一致が事前に避けられるというのは、終わってみて振り返るとよくできたシステムだったんだなと思いました。 次の転職のことはまだしばらく考えることはないでしょうが、間違いなく次も転職ドラフトは使うと思います。それくらいWeb系にいる方ならオススメできます。 ここまで読んでいただいて、「とりあえず登録でもしてみるかな〜」と思われた方はぜひ僕の紹介コードを使ってやってくださいw 紹介コード: VPGS お互いに好きなオライリー本がもらえるらしいです。こういうプレゼントがいちいちエンジニアナイズド(?)されているところも好感が持てますね 長い記事でしたがお読みいただいてありがとうございました! P.S. 入社から1ヶ月経ったので転職成功プレゼントとしてAppleStoreギフトカード10万円分をいただいてしまいました。 明日夜にAppleのイベントがあるというタイミングで10万円いただいてしまったので何か自分の生産性の足しになりそうなガジェットに使おうと思います! ありがとう転職ドラフト💌
2021/09/13 from blog

Macのdefaultsコマンドで半角カナの入力を有効化する

周回遅れ感は否めないのですが、アップルのオタクとしては過渡期のAppleSiliconのMacに触っておくという経験をしておきたくてM1搭載のMac miniを買いました。 もともとはWWDC2021でMacBookProの新型が発表されたら買う気マンマンだったのですが、半導体不足の影響か?どうかは知りませんが発表されずに終わってしまったので、衝動買いです。 My new gear… pic.twitter.com/TNadh6EGa2 — もがみん (@mogamin3) June 12, 2021 うおお pic.twitter.com/7dxZcUhkQl — もがみん (@mogamin3) June 12, 2021 これでもし年内にMBP出たらそれはそれで買っちゃうのかもしれませんが、その時は売るなり自宅でサーバーにするなりしようと思います。 どうでもいい話はさておき、せっかくまっさらな状態のMacを手に入れたこともあり、前々からやろうやろうと思って中途半端になっていた環境構築のスクリプト化をやりながらセットアップを進めました。 Macには defaults コマンドというのが用意されていて、これを使うことでシステム環境設定とかから設定するような項目をスクリプトから設定変更することができます。 こちらの記事には大変お世話になったのでぜひ参考にしてみてください。 amasuda.xyz …で、たいていの設定項目は誰かがやっていて調べればどの値を書き換えればいいか出てくるのですが、残念ながら半角カナ有効化のやり方だけどうしても見つけることができず、調べたのでここにメモっておきます。 結論から言うと、これでいけます。(実行後要再起動) defaults write com.apple.HIToolbox AppleEnabledInputSources -array-add " <dict> <key>Bundle ID</key> <string>com.apple.inputmethod.Kotoeri.RomajiTyping</string> <key>Input Mode</key> <string>com.apple.inputmethod.Japanese.HalfWidthKana</string> <key>InputSourceKind</key> <string>Input Mode</string> </dict> " 動作確認した環境は macOS 11.4 (Big Sur)です。冪等性があるかとかはちょっと確かめられてないので、もしかすると複数回実行したらおかしくなったりする可能性もあるので自己責任で。 ここから先は余談というか、どうやって設定値を見つけ出したか、という話。 どうやって見つけたか 前述の記事で現在の設定値の確かめ方が載っていたので、 設定値を defaults read で出力したものを適当にファイルにリダイレクトして保存 GUIから設定変更 defaults readで再び設定値出力してファイルにリダイレクト 変更前と変更後でdiffを取ってそれっぽい値に目星をつける みたいなことをやりました。もうちょっとスマートにできて欲しいけどまあ致し方なし。 そういえば、WWDCでMacにもショートカットアプリが来るみたいなこと言っていたので、簡単な設定変更くらいだったらショートカットにまとめたりできる未来があるかもしれないですね。(スクリプトの方がエンジニアにとっては便利なことに変わりはないかもしれないけど) Mac2台持ちになったので片方はBetaのOSとか入れて遊んでもいいなあとか思ったりした。おわり。
2021/06/13 from blog

Lambdaで「exec format error」が出る

AWS Lambdaで実行するためのコードをGoで書いて、Lambdaで動かそうとしてちょっとハマったので備忘録。 https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/golang-package.html こちらのドキュメントにある手順で、 GOOS=linux go build main.go を実行し、吐き出されたバイナリをzipコマンドでアップロードして、Lambdaの管理画面から手動で実行してみたところ fork/exec /var/task/main: exec format error というエラーが。 なんでかなーと思って...
2021/06/13 from zenn

社員を選択できるフォームをつくってよ!と言われたのでAirtableでハックしてみた話

会社で全社イベントの運営っぽいことをしているのですが、その事務作業の一環で社員一覧から一人を選択でき、かつその社員に紐づく情報を入力するフォームみたいなものを作りたいという要望が出てきました。 フォームを作るというと、思いつくのはOffice365やGoogleのフォームなのですが、残念ながら大量の選択肢から何か一つを選ぶというフォーム部品は用意されておらず実現するのは難しそうということでどうしたものかちょっと悩んでおりました。 いろいろ考えた末、Airtableというサービスを使ってそれっぽいことをできたのでやり方を共有。ちなみに、「社員を選択する」という超具体的なケースについて書いてますが、大量の選択肢が用意されたフォームみたいなものを作りたい全ての場合に応用できると思うので、ぜひ。 (注意: この記事は将来同じことしたくなった時に思い出すためのメモ書きなのでちょいちょい端折ってる箇所があるかもしれません。) Airtableについて airtable.com 最近流行りのサービスで、一言で言うとだれでも簡単に扱えるデータベース的なものをイメージしてもらうと良さそうです。 Notionを使ったことがある人にとっては、Notionのデータベース・テーブル機能を抜き出して高機能化したもの、というとわかりやすいかも。 ノーコードの文脈でよく触れられたりする気がします。今回はこのサービスを使っていきます。ちなみにFreeプランありで、この記事の内容程度の使い方であれば無料のままでいけます。 できあがったもの 「対象者」をクリックすると社員名簿が出てきて一人を選択できる 例として社員名の他に、文字列を入力できる箱を用意しましたが、他にもGoogleFormsでサポートしているような部品は一通りあります。 つくりかた 社員名簿を手に入れる いきなりですが、フォームの選択肢の基になる社員名簿を手に入れてください。 Airtableは標準でCSVからのimportに対応しているのでExcel形式とかで存在していれば、CSVとして書き出したりしてください。 自分は社員名簿手に入れるのが面倒だったので(?)SlackAPIを使って社員が所属しているチャンネルのメンバー情報を引っこ抜きました。SlackのAPI的に、チャンネルに所属するメンバーのIDだけを取ってくるAPI(conversations.members)と、メンバーのIDからメンバー情報を取得するAPI(users.info)の二つを組み合わせる必要があるので、適当にコードを書いて引っこ抜きます。(自分はGolangを使って書きましたがシェル芸がお得意な方は多分curlとjqとかで同じようなことができるんじゃなかろうかと思います。僕はチャレンジして2分で諦めてGo書きました) だいたいこんな感じ。 package main import ( "fmt" "github.com/slack-go/slack" "sync" ) const ( token = "insert your api token" channelId = "insert target channel id" ) func main () { api := slack.New(token) members, _, _ := api.GetUsersInConversation(&slack.GetUsersInConversationParameters{ ChannelID: channelId, Cursor: "", Limit: 1000, }) wg := sync.WaitGroup{} fmt.Printf("\"%s\",\"%s\",\"%s\"\n", "name", "slackId", "email") // ヘッダー行を出力しておく。Airtableに取り込んだ時に使われる。 for _, memberId := range members { wg.Add(1) go func(id string) { user, _ := api.GetUserInfo(id) if !user.IsBot { fmt.Printf("\"%s\",\"%s\",\"%s\"\n", user.RealName, user.ID, user.Profile.Email) } wg.Done() }(memberId) } wg.Wait() } ちなみに上記コードは極めて雑です。エラー処理をしていないのはもちろん、rate limitやメンバーが1000人以上いた時の考慮(conversations.membersは1回で1000人までしか取得できない。それ超える場合は、cursorを載せて再度リクエストして続きを取得する必要がある。)なども一切していないのでガチ用途の時は気をつけてください。 で、これを実行するとカンマ区切りで名前・SlackのID・メアドが吐き出されます。ファイルにリダイレクトするとかしてCSVとして保存しておいてください。 ちなみに1列目を名前などフォームで表示したい値にしておいた方が良いっぽいです。あとは適宜必要な項目があれば取得する感じで。(自分は一意に特定して何かしたくなったりした時のためになんとなくSlackのIDとメアドを取るようにしてみた。それ以上の理由は特にないです) Airtableに名簿を取り込む 無事に名簿を手に入れたら、Airtableに登録してもらって適当にbaseをつくります。base = Excelでいうブックだと思います。(たぶん。雰囲気でAirtable触っているので詳しくはわかってない) baseを作ったら、上の方のタブ?のところにある「Add or import」を開き「CSV file」を選択します さっき錬成したCSVファイルをアップロードするとこんな感じになるので、データの切れ目がおかしくなってるところがないかなどをざっと確認しつつImport これで新たテーブル(Excelでいうところのシート)が作られて、名簿が取り込まれます。ちなみにテーブル名ダブルクリックで名前変更できるので、わかりやすい名前に変えておきましょう。 フォームの入力を受け付けるテーブルをつくる 次にフォームの入力が溜まっていくテーブルを作ります。 さっきの「Add or import」のところを再びクリックし、今度は「Create empty table」というのを選択します。名前は適当に。 するとこんな感じになります。最終的にフォームを作った時、列が回答項目になります。(Googleフォームの結果をスプレッドシートに吐き出した時をイメージしてもらうとわかりやすいです。結果を入れるスプレッドシートを先に作って、それに対応するフォームが後から作られるイメージ) 列は「+」ボタンから作れるので任意の項目を足してあげてください。(たとえば文字列での入力が必要ならSingle line textやLong textなど) これだけでもすでにGoogleフォームとかよりいろんな選択肢があっていい感じ。 で、肝心の社員を選択する項目はどう作るかというと、↑の図一番上にある「Link to another record」をクリック。 するとさっきCSVから取り込んだテーブルがあるはずなので選択。 ちょっとテストで色々作ったりしてたのでとっ散らかってますが気にせず。 「Allow linking to multiple records」を選んでおくと複数人が選択できるようになり、外しておくと単一の選択になります。 設定が済んだら「Create field」を。 こんなやつも出てきますがあとから足せるので一旦スキップで大丈夫かと思います。(選ばれた人に紐づく情報を横に出すかどうかが選べる) フォームをつくる ここまできたらフォームの形にするだけです。先程と同じテーブルで左下にある「Form」をクリックしてForm viewをつくります。(Airtableにはviewという概念があって、同じテーブルを複数の見方で見られる。さっき作った表をFormという見方で見るよ、という意味でviewです) この時点ですでにあるフィールドは全て含まれた状態のフォームが出来上がってます。Googleのやつと同じようにマウスのドラッグ&ドロップで順番を入れ替えたりもできますし、タイトルの変更などもできます。無料プランでは✨マークのついている項目のカスタマイズはできません。それが嫌ならお金を払うかフルスクラッチでフォームを作りましょう😇 ちなみにいらない項目(フォームで収集しない項目)があれば、フォーム部品をクリックして右上のボタンから消しちゃうこともできます。 フォームを共有する 最後にフォームを実際に配って書いてもらうためには、左上にある「Share form」を。 こんな感じの画面で共有用のURLを取得できます。 そればかりではなく、「Restrict access with a password」を選ぶと事前に決めておいたパスワードを知っている人でないとフォームを開けないようにすることもできたりします。これはなかなか嬉しい。 おわり という感じでサクッとメモ書きするつもりが、結構ガッツリになってしまった。 Airtable、有料プランだと結構いいお値段しちゃうので個人でゴリゴリ使っていくイメージはあんまりもてなくて触ってなかったのですが、実は結構いろんなことができて楽しいなと思いました。 NotionのDatabaseにも言えることなのですが、英語なのと、若干DB設計に対する理解みたいなものを必要とするので、普段そういうのをやらない事業職の人たちとかからはもしかするととっつきづらさがあるのかもしれないなとは思いつつ、みんなで使いこなせたら幸せになれるんじゃないかとも思いましたとさ。おしまい。
2021/05/18 from blog

AppEngineでBasic認証をしようとしてハマった話

先日、AppEngineにデプロイしたアプリケーションにBasic認証を設定しようとして、ハマったので事の顛末を記しておこうと思います。(今時Basic認証を使いたい機会もそう多くないとは思いますが😅) 前提 GAEのランタイムはGAE Standard go114で、その上で動くアプリケーションには gin を使用して構築したWebサーバを使用していました。 Basic認証にはginに付属している BasicAuthForRealm というミドルウェアを使用していました。 実装はだいたいこんなかんじです。 package main import ( "github.com/gi...
2021/02/21 from zenn

【超小ネタ】Gitリポジトリ内にいるときにリポジトリのrootまで一発で戻りたい

Gitリポジトリの深い階層にいるときにリポジトリのルートまでさくっと戻りたいことってないでしょうか? 自分は cd でホームディレクトリまで戻ってからリポジトリのルートまで移動し直したり、 cd ../../../.. みたいなかんじで戻ったり(そして戻りすぎたり)してました。 gitコマンド使うとリポジトリのルートの絶対パスを取得できることを知ったのでリポジトリのルートまで戻るコマンドをエイリアス貼ってみました。 rootをとるコマンドは git rev-parse --show-toplevel 、これの結果をcdに渡してあげたコマンドをalias貼るだけでOKです。すばら。 rev-parseコマンド、結構いろいろできるみたいですね。 qiita.com おしまい。
2021/02/02 from blog

Node.jsで建てたサーバーでヘビーな処理をしてはいけない【それはそう】

小ネタです。 普段はフロントエンドを書いている人間なのですが、最近Goを学んだことをきっかけに非同期的な処理の仕組みについて、もう少し低いレイヤーで理解をしたいと思い、調べ物をしていました。 そこで目にしたこちらの記事に書いてあることが、当たり前と言われれば当たり前なことながら、知らずにやらかしそうだと感じたので、実際に実験してみたコードとともに紹介です。 https://knowledge.sakura.ad.jp/24148/ const http = require('http'); const server = http.createServer((req, res) =>...
2021/01/23 from zenn

Golang インタフェース型のポインタを扱おうとしてハマった【たすけて】

注:いまいちすっきり解決してないので、誰か知っていたら教えてください。 年末クリーンアーキテクチャの本を読んだので、Golangで実践してみようと思ったら思わぬところでハマったメモ。(クリーンアーキテクチャするならオブジェクト指向の言語でするべきなのでは?というのはあるがGolangの勉強も一緒にしたかったというのが大きい) 簡略化するとこんなコードを書いていた。 package main // 実際は引数受け取ったり値を返したりする type SomeRepository interface { Create() Find() } // DBとかの技術的詳細に関わる値を持っているイメージ type SomeRepositoryImpl struct { CollectionName string } func (repo *SomeRepositoryImpl) Create() { return } func (repo *SomeRepositoryImpl) Find() { return } func CreateSomeRepository() *SomeRepository { return &SomeRepositoryImpl{ CollectionName: "Something", } } SomeRepositoryという抽象を実装したSomeRepositoryImplというのを作りたい、というあるあるなRepositoryのコード。Repositoryを使う側は技術的詳細であるDBに対する操作がどうなっているかということを知らなくて済む、というやつ。 ところが上記コードはコンパイルエラーになる。 エラーになるのは func CreateSomeRepository() *SomeRepository { return &SomeRepositoryImpl{ CollectionName: "Something", } } この関数のSomeRepositoryImplを作っているところで、Cannot use '&SomeRepositoryImpl{ CollectionName: "Something", }' (type *SomeRepositoryImpl) as type *SomeRepositoryというエラーになる。 いろいろ試行錯誤して、散々ハマったが、結局のところ答えはこう。 func CreateSomeRepository() SomeRepository { return &SomeRepositoryImpl{ CollectionName: "Something", } } 関数の返り値の型がポインタ型ではなくなった。どうやらインタフェース型のポインタというのはない?らしい。とりあえずうまくいってしまったので続きをやっていこうかなと思いつつ、これがなぜなのか?というのにすっきりとした答えが出せずにモヤモヤしている。
2021/01/01 from blog

2020年反省会会場

紅白見ながら一気に振り返る。 https://yurufuwa-tech.hatenablog.com/entry/2020/01/06/091359 この記事の答え合わせ。 月2回以上の技術アウトプット これは完全にできなかった。なんなら1月で崩壊してた気がする。 昇級する これも叶わず。 そもそも自分のWillってなんなんだろうなあということに悩み続けた一年だった気がする。現在進行形で悩んでいるが、来年は新卒3年目、流石にそうも言っていられないのでバチっと決めていきたい。 アプリ以外の技術領域をやる これはやった。一応Elmという言語を使ったWebフロントエンドの開発や12月にはGolangを使ったサーバーサイド開発もやったりした。 一人の開発者として、求められるクオリティのモノを作ることはできるというレベル感。 フルスタックになっていくとしても、得意技を持っておきたいと思う今日この頃。 100名以上くるイベントへCfPを出す これは叶わず。 というかそんなイベントもなかったが。(ただの言い訳) 冬キャンプをしたいので貯金する 冬キャンプは叶わなかったが、貯金はした。結構貯めたと思う。 マネーフォワードで可視化してそれを眺めることでモチベーションにつなげたり、持株会を利用してそもそも手元に入ってこない形で資産形成していったのがよかったかな。 生活の質を一定に保つ これはどうだろう?そもそも「普段の生活」の定義が揺れまくっていた2020年、それなりに健全な人間の生活はできていたとは思う。 他人に優しくする これもだめだなあ。 余裕がなくなるとすぐ対人コミュニケーションが雑になってしまって良くない空気にしてしまう。特にオンラインのコミュニケーションだと、相手の気持ちを感じ取りづらいのでより丁寧なコミュニケーションをするべきだったのかもと思うことも多々。 人間的な成長をしないとだめですね。 まとめ 典型的に宣言だけしてやった気になる1年を過ごしてしまった。 コロナもあって環境の変化が激しかったというのはありつつも、怠けすぎた一年だった。
2020/12/31 from blog

Fringe81のオンライン納会を支える技術 配信編

この記事はFringe81 Advent Calendar 2020 25日目の記事です。 メリークリスマス!🎄 今年ももう終わり、アドベントカレンダー最終日の今日12月25日、我々Fringe81…
2020/12/25 from qiita

業務でGolangを書き始めた。最初の週にやったこと雑記 + (少しだけ)思ったこと

新卒2年目も終わろうとしております、もがみです。 ここまでフロントエンド一筋でReact Nativeを使ったアプリ開発とか、Elmを使ったWebフロントエンド開発をやってきましたが、運良くサーバーサイドにチャレンジする機会を得ることができました。チームのタスクがサーバーサイドに偏重している間のお助けとしてやっている部分も大きいので、いつまで続くかは現状未定ですが、せっかくなのでやったこととか、感じたことをだらだら書いておきます。 前提 Tour of goは一通りやった(全部完璧に理解しているとは言っていない)というレベル感。 普段はTypeScriptとかElmとか書いているひと。フロント寄り。 サーバーサイドは学生の頃趣味で書いてたことがあるくらいの知識レベル。 環境構築 なにはともあれ環境がないと開発できないので環境構築をしました。 普段のフロントエンド開発はWebStormを使っているので、Golandを選択。とりあえず体験版を入れつつ、特に問題がなければ、WebStormと統合してIntellJ IDEA Ultimateのライセンスを購入しようかなと思います。 知らなかったんですがIntelliJはJava系の言語のためのIDEというわけではなく、JetBrains系の様々なIDEの機能を内包しているようです。また、すでに持っているWebStormのライセンスをアップデートすることもできるらしい。いくらになるのかよくわかりませんが買うことになったら調べてみようと思います。 support.samuraism.com Goland自体は公式から適当にダウンロードして起動すればOK。個人的必須プラグインであるIdeaVimもインストール。(大事) システムにGoを入れないといけないので、普段使っているanyenvでgoenvを入れて、開発するプロジェクトのgo.modに書いてあったバージョンのGoをインストールした。 改めて、Golandでプロジェクトを立ち上げると go: github.com/example/example-repo@v1.6.0: reading github.com/example/example-repo/go.mod at revision v1.6.0: unknown revision v1.6.0 と言われた。(example/example-repoは実際には会社のプライベートリポジトリ) これはプロジェクト内で使っているプライベートなライブラリが取得できずに怒っているっぽかった。SSH鍵は設定してあるしどうしたら…?と思い調べたら、GOPRIVATEという環境変数を指定してやる必要があるということがわかった。 syfm.hatenablog.com 他にもいくつかの記事をみて、 sumdbというGolangパッケージのチェックサムを返すサーバーがある そいつのおかげでproxyからパッケージを取ってきても改竄が行われていないことを証明できるという仕組み sumdbにチェックサムが存在しなかった時、proxyの他のサーバーにパッケージ名が流出しないように処理を止めるという仕組みがある GOPROXYに指定したパッケージを取りに行くときはproxyではなくオリジン(GitHubとか)に直接取りに行くようになる みたいな理解をした。多分あってる? Golandは設定画面からイイ感じに環境変数を入れられるので入れてあげた。(わかりづらいがインプットの右端にあるボタンを押すと、イイ感じに入力できるフォームみたいなのが出てくる。イイ感じに。) さっきのエラーが出たリポジトリ以外にもいくつかのプライベートリポジトリに依存しているようだったのでワイルドカードで指定した。 ここまできたら、適当にソースコード開いて赤くなってるimport文の上でOpt + Enterを叩いてSync dependenciesみたいな項目を選ぶと依存ライブラリの取得が走る。規模にもよると思うが、ちょい時間かかった。 思ったこと ポインタ 他言語からきて一番戸惑うのはやっぱりポインタのような気がする。理解はしているつもりだったがいくつか致命的なバグを埋め込みそうになった。 Goを始める僕に言いたいことがあるとすれば「*や&を使う時は慎重になれ」ということかなと。(Go普段から書いてる人からしたら当たり前体操だと思うが) TypeScript(他、最近のモダン & 高機能な言語)になれていると、基本的にしっかり型が当ててあって、コンパイラが怒りさえしなければ動くのが普通だと思ってしまうところなんだが、Goも型がある言語という思いが先行して、ポインタは常にnilである可能性を含んでいるということを忘れて、IDEが怒っているからという理由だけで&やら*やらを書いて本当に痛い目をみた。(デプロイしてウキウキしながらリクエストを叩くと500が返り、Loggingにはpanicの5文字が。。。) それを繰り返して、「nilをチェックするのはプログラマの責任なんだぜ」というメッセージに気づくことができた。 フロントエンドエンジニアにGoを書かせる機会があったら是非「TSでいえばasとか!とかああいうのを使う時と同じ気持ちでポインタは扱わないといけないものなんだ」ということを伝えてあげてほしい。(ちょっと意味合いとしては違うと思うが、ポインタとの正しい向き合い方に気づいた後の僕の気分としてはそんな感じだった) 1週間で理解できたこととしてはこんなところだが、いまだに関数の戻り値や引数にはポインタ型を使うべきなのか、そうではないのかというところの判断がつかない。飲みの席での話なので100%理解できていないと思うが、Goは言語の仕組み上、ある程度の大きさまでは値渡しの方がパフォーマンス的にも有利であると聞いた。コピーのコストをとってもパフォーマンスで勝つらしい。不思議だ。 文法が少ないのは良い Goの良いところとして、1個のことやる書き方は1つしか存在しないというのがよく挙げられると思うが初学者にとってそれは本当に嬉しいことだと感じた。 Tour of goの知識があれば、使われているライブラリや、他のメンバーが書いたコードも時間をかけて読めば何をしているか理解するには十分であるというのはめっちゃいい。 テストもわけわからんテストフレームワークの使い方とか覚えなくてもいいし最高。 他にも思うところはあるんだが、社内事情がだんだん濃くなっていきそうなのでブログはこの辺で。
2020/12/20 from blog

elm/urlで?を含むクエリパラメータを正しくパースする

ElmというAltJSではelm/urlというパッケージを使ってURLをパースし、その内容に応じた状態遷移を行わせるのが一般的です。(多分。筆者はElmにそこまで詳しくないです。) elm/urlを使ってURLのパース処理を行っているSPAを開発している際に ?をクエリパラメータに含んだURLを正しくパースできない という現象に若干時間を溶かしたので、起きた事象と解決方法を書いておきます。(微妙にレアケースな気もするので誰かの役に立つかはわからん。) 環境 Elm 0.19.1 elm/url 1.0.0 事象 「?をクエリパラメータに含んだURL」というのは https:/...
2020/10/13 from zenn

PrettierとLinterを共存させるときの公式オススメが変わったらしいという話

個人でやっているプロジェクトにPrettierとESLintを入れようとしたときの話。 ESLintにもコーディングスタイルを整えるための機能があるので、何も考えずにそのまま両方を入れると、お互いのルールが競合してしまうという問題が発生します。 prettier.io これが公式のドキュメント。書いてあることを雑に要約すると コードフォーマットのことはPrettierを、コード品質に関することはLintを使ってくれ ただLintツールのルールと競合することがあるからeslint-config-prettierのようなコンフィグを入れてくれ と書いています。つまり、Linter側のコードフォーマットに関するルールを全て無効化して、その上でPrettierを使ってコードフォーマットをするというのが推奨されています。 blog.ojisan.io (こちらの記事が大変わかりやすく参考になりました) ここまでの話は昔から同じようなことが書いていたのですが、このあとの部分がここ最近変わったみたいです。 この記事を書いている時点のドキュメントを引用すると以下のような注意書きがあります。 When searching for both Prettier and your linter on the Internet you’ll probably find more related projects. These are generally not recommended, but can be useful in certain circumstances. First, we have plugins that let you run Prettier as if it was a linter rule: ・eslint-plugin-prettier most editors have Prettier support. これまた雑に要約すると、 PrettierをLinterルールのように実行するツール(eslint-plugin-prettierなど)があるが、これはPrettierがまだ新しいツールだった時には役に立っていたが、現在はオススメしない。 なぜなら、現在はprettier --check .(dry run的なやつ)があったり、多くのエディターがPrettierをサポートしているからである また、これらのツールを使うデメリットとして以下が挙げられています。 Linterとして実行すると、スタイルに関するエラーがエディター上で赤線で表示されたりする。Prettierはコーディングスタイルを忘れるためにあるのに。 普通に実行するより遅い 1レイヤー増えるので壊れるリスクが増える こちらのアーカイブを見てもわかるように、過去には公式でeslint-plugin-prettierのようなプラグインをオススメしていたみたいですが、公式オススメではなくなったっぽいという話でした。 ちなみに、LintかけたあとにPrettierをかける手段としてはprettier-eslintというのがリコメンドされていました。ちなみに、prettier-eslintはCLI機能を有していないので、CLIから実行したい人はprettier-eslint-cliというパッケージがまた別で用意されているのでそっちを使うといいかもです。
2020/08/27 from blog

Slack Appから送るメッセージに日付・時間を入れるときにdateフォーマットを使ってちょっと感動した件

小ネタです。 Slack App(bot)を作るとき、botから送るメッセージに日付や時間の情報を含めたいことが時々あると思います。 例えばこんな感じ。(右下) 「問合せフォームに入力があると、Sl…
2020/08/16 from qiita

React Native 0.60以降でreact-native-vector-iconsが使えないときのはなし

久々にブログ書いてます。 相変わらず日々React Nativeを触ったりしています。RN界隈の人はご存知かと思いますが0.60以降のバージョンでは react-native link {ライブラリ名} のようなコマンドを実行することなく、ネイティブに依存するライブラリを使用することができるようになりました。 最近、React Native 0.62のプロジェクトでreact-native-vector-iconsを使おうとしたらiOS端末で Unrecognized font family と言われてしまって困ったのでメモ書き。 使えるようにするための手順だけ書くと npm i react-native-vector-icons Info.plistにフォントファイルを列挙 これだけでいけます。今日時点でREADMEには手動でプロジェクトに追加する方法/ react-native link を使う方法 / CocoaPodsを使う方法の3つが書いてますが、多分この方法が一番いいのかなと思います。(経験上手動でXcodeのプロジェクトをいじるのはRNのアップデートとかする時に辛いことになるのでできる限り避けた方がいい) 「Info.plistにフォントファイルを列挙」は具体的にはこう <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <!-- 中略 --> <!-- 以下追加 --> <key>UIAppFonts</key> <array> <string>AntDesign.ttf</string> <string>Entypo.ttf</string> <string>EvilIcons.ttf</string> <string>Feather.ttf</string> <string>FontAwesome.ttf</string> <string>FontAwesome5_Brands.ttf</string> <string>FontAwesome5_Regular.ttf</string> <string>FontAwesome5_Solid.ttf</string> <string>Foundation.ttf</string> <string>Ionicons.ttf</string> <string>MaterialCommunityIcons.ttf</string> <string>MaterialIcons.ttf</string> <string>Octicons.ttf</string> <string>SimpleLineIcons.ttf</string> <string>Zocial.ttf</string> </array> <!-- ここまで --> </dict> </plist> こんな感じでフォントファイルを列挙すればOKです。生のInfo.plistいじるのが怖い場合はXcodeからいじると良き。 GWは巣篭もりしながらなんかRNでつくろーかなと思ってます。気の向くままに。
2020/04/26 from blog

モノレポ on husky戦略

2020年は毎月2本技術的なアウトプットするぞ、と言いつつ1月から打ち破ってしまったので罪滅ぼしに最近業務でやったことについて備忘録的に書いておこうと思います。 モノレポを採用しているプロダクトにhuskyを導入したという話です。 ※前置きが長いので、いらない人は本題のところまで読み飛ばしてくださいませ。 モノレポ モノリシックレポジトリの略。 詳細な定義は知らないので、実際には違うかもしれないが(ていうか多分違う。)この記事におけるモノレポは「一つのGitリポジトリを用いて、一つのプロダクトのフロントエンド/バックエンド等のコードを管理するGit戦略」ということにして進めたいと思います。 husky github.com こいつのこと。これは一言で言うと、JS開発者間でGitフックの設定を揃えるための便利ツールとでも言えば良いのだろうか。 package.jsonに依存関係として定義しておくと、npm installやnpm ciを使って依存ライブラリのダウンロードをした際に、Gitフックを設定してくれるという感じの挙動をします。あとはpackage.jsonや設定ファイルにgit commit時やgit push時にやらせたいことを列挙しておけば、自動的に設定に宣言したことを実行してくれます。 まぁJSを使って何かしらの開発をしていれば、npm installは間違いなくやるだろうし、そのタイミングを使ってGitフックが設定されるので実質的にGitフックの設定を強制することができるという素敵OSSってわけです。 これを使ってcommit前にPrettierやなんちゃらLintとかをかけておけば、誤ってコードフォーマットを忘れたコードがGitリポジトリ上に上がって、コードレビューで「フォーマッタかけてください」みたいな不毛なやりとりを産むこともないので素晴らしいのです。 ちなみに ちなみに、huskyはGitフックを設定してくれるだけなので、lint-stagedというツールと組み合わせることで、ステージに上がっているファイルを対象に必要となるフォーマッタやLintをかけるということができます。どのファイルに対してどのフォーマッタを適用するかみたいなのを指定できるので超良い。超おすすめです。 んで本題。 基本的にここまでで書いたことをやりたかったら、一番早いのはlint-stagedのREAMDEに書いてある $ mrm lint-staged というのをプロジェクト直下で叩いてやるとインストールされているフォーマッタ等をみて良い感じにしてくれるので誰でもできると思います。 ところが、僕がメンバーとして関わっているプロダクトのリポジトリはモノレポ構成を取っており、1つのGitレポジトリの下にWebフロントエンド(ElmとTypeSript)やらスマートフォンアプリ(React Native製なのでTypeScript)、ほかにもサーバーサイドのコード等も入っているというような状況です。 このような状況において、huskyを導入するにはちょっと工夫をする必要があります。というのもGitフックはGitレポジトリ単位でしか設定できないので、たとえばWebフロントエンドのディレクトリ配下でhuskyを設定してしまうとスマートフォンアプリのディレクトリではhuskyを使うことができません。(できません、というか上書きで設定されるので最後にインストールしたものだけが生き残ってしまう) huskyのREADMEにはlernaを使うように書いています。lernaはモノレポでの開発を支援するツールで、複数のnpm packageをスマートに管理してくれるものらしいです。(雑な理解) ユースケースを見た所、npm packageの開発をモノレポを使って行う際に便利な機能を提供しているツールのようで、今回のようなケースには向かないと判断し別の方法を使ってなんとかhuskyを使う方法を模索しました。 そこで今回はGitリポジトリ直下にhusky用のディレクトリを作成し、そこで一括管理するという方法をとりました。 husky-example/ ├── _husky ├── server ├── sp-client └── web-client こんな感じ。 _huskyディレクトリのしたのpackage.jsonのdevDependenciesにhuskyを追加し、設定を書きます。 今回Linterやformatterのツール自体はそれぞれのコードのあるディレクトリのpackage.jsonに書きたかったため、こんな感じで相対パスで指定するようにしました。 { "name": "husky", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "husky": "^4.2.1", "lint-staged": "^10.0.6" }, "husky": { "hooks": { "pre-commit": "lint-staged" } }, "lint-staged": { "../sp-client/app/**/*.{ts,tsx}": "../sp-client/node_modules/.bin/tslint -p ../sp-client --fix" } } 少々冗長な感じは否めないですが、まぁ仕方なし。。。 そしてもう一点やっておくとよいかもしれないのが、Lint対象のディレクトリにあるpackage.jsonのpostinstallに_huskyディレクトリ以下でnpm ciを走らせるスクリプトを書くことです。 具体的にはこんな感じ。 { "name": "sp-client", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "postinstall": "cd ../_husky && npm ci" }, 以下省略 このようにしておくことで、sp-client以下でnpm iやnpm ciをやったとき、一緒に_huskyディレクトリ以下でnpm ciが実行され、Gitフックが設定されます。 ここまで設定しておけば、普段の開発では意識することなくcommit時のlintが走ります。 おわりに ということを先日仕込んでみました。まだマージされてから日が浅いので何か問題が起こったら、考え直そうと思っていますが、今のところは順調に動いています。 ここまでドヤ顔で記事を書きましたが、husky用のディレクトリを切ったらいいのではとか、postinstallを書いたらいいのではとかは全て開発メンバーのアイデアです。。。 それではまた。
2020/02/09 from blog

XcodeでArchiveするとOther items(Generic Xcode Archive)になってしまう原因の探り方

Xcodeからアプリを公開するためにProduct > Archiveを行うと、生成されるファイルがなぜかGeneric Xcode Archiveとなり(iOS App Archiveになることを…
2020/01/16 from qiita

2020年の抱負

仕事初めなのでここらで2020年の抱負を公開しておく。 いつも目標立てては、数週間で頭の端っこに追いやられてしまうので今年はこの記事のリンクをSlackbotのリマインダーにセットするぞ。 追記: やった。 お仕事編 月2回以上の技術アウトプット Qiita記事とか、このブログへの記事とか、勉強会のLT登壇とかなんでもいいが月に2回以上やる。 月2回やったとしたら年間で24回になるので、まぁまぁなボリュームかなと思う。上を見たらきりがないが、ほぼゼロからのスタートなので結構頑張らないといけない。 後述する登壇に繋げたいという意図。 昇級する 詳しいことはここでは省くが、会社の等級制度で今の等級より1つ上を目指す。 昇級するタイミングが、3月と9月なので9月の昇級を目指して課題を一つずつ潰していく。 アプリ以外の技術領域をやる 今はRNでアプリ開発をしていて、開発アイテムをそこそこ無難にこなす能力はあると思っている。 +αで技術的負債の返済とかは昨年に引き続きやっていくが、今年は少しだけできることの幅を広げていきたい。 具体的にはサーバーサイドとか。とはいえ器用貧乏になっても仕方ないので、上半期は今任されている領域においてプロになることに専念する心算。 100名以上くるイベントへCfPを出す TSConfとかJSConfとかそういうイベントへCfPを出す。 CfP出すだけならぶっちゃけすぐにでもできるっちゃできるんだが、そうではなく、採用されるだろうという勝算が持てるレベルの内容を出したい。 これも下半期になりそう。いつでも出せるように技術アウトプットを通してネタを貯めておきたい。 プライベート編 冬キャンプをしたいので貯金する しまりんになりたい 10万から15万くらい貯めてパーっと使いたい。 生活の質を一定に保つ 仕事が忙しかったりすると、ついつい生活の質を落としがちだった。(掃除がおろそかになったり、畳んでいない洗濯物貯めたり、食事が雑になったり) 忙しい時、忙しくない時があるのは仕方ないので、その中で無理なくできる生活リズムみたいなのをちゃんと作っていきたい。 目指すところは、いつ人がきても大丈夫な家。 他人に優しくする 自分に余裕がなくなると、他人に冷たくしたり強く当たってしまったりすることがまあまああった気がする。 他人には常に優しく、一歩大人になりたい。
2020/01/06 from blog

2019-2020 年末年始をまとめる

さて、冬休みも終わるので、2019年末〜2020年始なにやってたかをまとめようとおもいます。 2019年末① 4回目の納会幹事をやった 物好きというか、なんというか笑 毎回なんだかんだ達成感もあり、次回への課題もあり、たくさんの人から感謝されるのが楽しくて気がついたら入社して4回目の納会幹事をしました。納会は四半期に一度なのでこれで1年やったことになりますねw 2019年末② Flutterをやってるよ FlutterのDevToolがえげつなくてすごいぞこれ — もがみん (@mogamin3) December 29, 2019 年末だけじゃなく、年始もやってるけど個人的な興味からFlutterを触ってみたりしてました。上記ツイートはFlutterのDevToolsの作り込まれ具合に感動している様子。この辺はちゃんと勉強したらまとめたいと思ってます。 作りたいものがあるというワケではないので、業務で作っているアプリの一部をFlutterで再現してみて、違いを体感したりしたい。 2020年始① 初日の出を見にオフィスへ カメラが趣味というのもあり、初日の出を見たいと思ったものの、思い立ったのは大晦日。 有名スポットに向かったら人混みに飲まれてしまうのがわかりきっていたのでなんとかならないか…と考えた結果。。。。 日の出、有名スポットとかじゃなくていいから人が少ないところでゆっくり拝みつつ写真撮りてえと思って悩んだ結果オフィスから見るのが一番いいのでは、という結論に到達した — もがみん (@mogamin3) 2019年12月31日 普段めっちゃ景色いいところにおるやんけ、と気づいたので実家からバイクで職場に向かってみました。 参考: 普段の景色 ほんとに来てみたけど窓が邪魔なのとそもそも今日天気が悪い pic.twitter.com/jV3b5ZjIwR — もがみん (@mogamin3) 2019年12月31日 あんまりちゃんと見えませんでした。。。 (天気のせいにしているが、これもうあと10分くらい待ってたらちゃんと見えたのかも。。。日の出の時間過ぎて見えなかったから諦めてビル降りてしまった…) 帰りにODOが1111kmになった。 1/1に1111kmいったよーという pic.twitter.com/Lnw22GEbKb — もがみん (@mogamin3) 2019年12月31日 2020年始② ツーリング初め また後輩に誘ってもらったので大洗〜栃木ツーリングに行ってきました。 大洗の景色、天気良かった。 で、大洗から栃木のツインリンクもてぎへ。 下調べ全然できてなかったのですが、ツインリンクもてぎってサーキットだけじゃなくて様々なアクティビティができるんですね。 Hondaのミュージアムがあったり。 モトコンポの実物をみられる日がくるとはw ずっとやってみたかったカートをやりました。(写真撮り忘れた) www.twinring.jp 初心者向けの体験カートだったので、最大速度は45km/hなのですが、低いのと狭いのもありスピード感があって楽しかったです。これはハマりそう。 そういえば、栃木にはセイコーマートがあるんですね。道も広いし、実質北海道ツーリング。。。 おわり そんなわけで結構充実した年末年始をすごせたかなとおもいます。 ここには書かなかったものの年末年始はたくさん買い物をしました。 シードバッグがついたよおおん🆒 pic.twitter.com/cI14FHg1sC — もがみん (@mogamin3) 2019年12月28日 何を思ったかおしゃれな靴を買ったのね 人生で一番高い靴 pic.twitter.com/Z7hTSVyenh — もがみん (@mogamin3) 2020年1月3日 静寂の世界を手に入れました すごいこれ pic.twitter.com/c1ec9IX210 — もがみん (@mogamin3) 2020年1月2日 カードの請求が怖いですね。。。
2020/01/05 from blog

近況報告的な記事(趣味要素つよめ)

社会人になって半年経った。という記事から一切更新しておらず、このままだと社会の荒波にもまれて闇落ちしたのかと思われてもしょうがない(?)のでここらで近況報告をしておこうと思います。 久しぶりの記事で申し訳ないですが、技術要素はほぼないです。ゆるふわ技術日誌とは一体。。。。 仕事 相変わらずReact Nativeでアプリを書いています。 入社以来、開発しているアプリにおける技術の面を支えていたスペシャリストの方が別の役職の仕事を優先するためチームから離れることとなり、その後任として技術面の意思決定をする役割をもらったりと、自分としては少しチャレンジな日々を過ごしていると思っています。 任せてくれた上司の期待を裏切らずやっていきたい。そう思いながら必死に悩んだり、コード書いたりいろいろしてます。 言い訳でしかないものの、日々忙しくせっかくやっている技術に関してアウトプットできていないのは痛いところ。 qiita.com 先日会社のアドベントカレンダーに書いたこれくらいかもしれないな。これは2020年の課題。 本来の仕事とは外れるものの、職場のちょっとした課題を技術で解決するのが最近の趣味だったりします。 Slack bot作ったり、GASで作ったAPIとReactで適当に作ったフロントエンドで困りごとを解決したり。やっぱ本質的に自分は人に感謝されることが好きなんだなあと感じておる今日この頃です。 技術 なんだかんだ仕事で使ってる技術以外に手を出して遊んでみたり、とかできてないなあという反省。 最近唯一ハマってちょいちょいやっているのはGCPのいろんなサービスをつまみ食いすること。特にCloud Functionsにはハマっています。あれ、Chromeが使えるのでPuppeteerが使えるんですよね。めちゃ楽しい。 qiita.com つい最近書いたやつ。 趣味 何を思ったか8月末のある日、二輪免許が欲しくなり教習所を検索すると、なんと家から通える範囲に教習所が…! これは行くしかないと思い立ち入校。目黒と恵比寿の間という土地柄もあってか、相場よりだいぶ高く普通免許所持の普通二輪免許取得のはずが14万位払いました。 後から聞いた話、通っていた教習所は芸能人御用達らしい。 仕事をしながらなので土日しか通えませんでしたが、無事ぴったり2ヶ月後の10月末日に教習所を卒業。10月31日に二輪免許を取得しました。 免許センターを出たその足で、YSP(ヤマハのディーラー)へ行きお目当てだったSR400というバイクを見に行きました。 ぶっちゃけこれを買うことを目標に免許を取ったところがあるのですが、なんと納車待ちが2ヶ月。。。。しかも思ったより見積もりも高く(車検のある車両の乗り出し価格は結構すごい)ひとまず諦めて、ふわっと頭の片隅にあったもう一台のバイクを見に行くためホンダドリームへ。 こんなバイク。 思った以上にかっこいいし、思った以上に安く(これは直前にSR400の見積もりを見ていたせい。このバイクは250ccなので税金等がSR400より安い)しかも在庫あり。1週間ちょっとで納車可能とのこと。 うっかり契約と相成りました。 納車はこんな感じで。 店の一番目立つところに置かれていたマイバイク マジの新車 その後同期に連れられて東京駅に。カメラの充電切れててスマホ撮影になってしまったのが悲しい。 というのが約1ヶ月前の話。 それから1ヶ月の間は、冬でクソ寒い中毎週土日にちょこちょこバイクに乗る生活をしていました。大好きな海ほたるへ行って初高速を体験したり、これまた大好きなアイドルであるでんぱ組.incの幕張で開催されたライブにバイクで行ったり、東雲のバイク用品店に行ったり、ずっと行ってみたかったコメダ珈琲店に行ったり。 住んでるところがバリバリの都会なので全然バイクなんてなくても生きていけるし、電車なら寒くないし、コケて怪我したりする可能性もないけどそれでもエンジンの振動や音を感じながらいろんなところへ自力で行けると言うのはなんとも言えない楽しさがあります。 これはそのライブで行ったライブのひとまく。初めてスマホによる撮影が解禁されたライブとなりました。しばらくアイドル熱は冷め気味だったのですが、やっぱりライブはいい。というか「でんぱ組の」ライブはいい。(オタク特有の早口) で納車から1ヶ月が経ち、昨日は初めてツーリングをしました。行先は千葉。 バイク乗りの後輩に誘われて行ってきました。買ったけどサイズが合わなかったらしい冬用グローブを納車祝いにいただいてしまいました。本人は安物と言っていたけどアレがなかったら今頃手が凍傷にでもなっていたと思う。本当に救われた。 ちょっとした(いやけっこう?)ハプニングはありつつも、楽しく千葉をまわることができました。天気も👍 1ヶ月経って走った距離はこのツーリングを含めておよそ950kmくらい。だいぶ慣れてきましたが、これからも安全に楽しく乗っていきたいなと思います。 てなわけでほとんどバイクの話しかしてないけど近況報告でした。 学生のころはしょっちゅう病んでたけど、今は平日精一杯仕事して、休日はバイクに乗ってあっちこっちへ。というとてもメリハリのある生活をしているおかげか心もわりかし健康です。 ついついいろんなことに首を突っ込んでしまって、めっちゃ忙しいので体を壊さない程度にがんばっていきます。
2019/12/16 from blog

CloudFuntionsで「File ./dist/index.js that is expected to define function doesn't exist」と言われた(TypeScript)

Google Cloud FunctionsとTypeScriptを使ってとあるSlackボットを作っていたら、正しく依存関係を指定しているはずなのに「File ./dist/index.js th…
2019/12/14 from qiita

社会人になって半年経った。

表題の通りです。 ちょっとだけ振り返っておく。 4月/5月 この辺の話は過去にブログに書いてた。 yurufuwa-tech.hatenablog.com 初めての一人暮らしで浮かれているのがよくわかる記事。 あの頃は、目覚ましかけなくても朝目が覚めてしまって、それで凝った朝食を作っていたなあというのを思い出した。 多分一人暮らしに体が慣れずに目が覚めてしまっていたというのと、業務もそれほど忙しくなかったのがあるのかなあ。 結局朝食は、目玉焼き+トースト+(ときどき)ヨーグルト+コーヒーというので安定しました。ウインナーとか毎朝焼くのはちょっとコストパフォーマンスが悪いのでやめました。 6月 なんだか必死に目の前のタスクだけをこなしていたような。 試しにそのあたりのSlack遡って見てみたら、オリジナルなライブラリ作ってプロダクションコードにマージされて喜んだり、React Nativeのアニメーションが扱えるようになってニヤついたりしてた。 あとは業務でHTML/CSS書いたり。(CSSなんて趣味のレベルでしか書いたことなかったのに、急に書くことになって雑に書いたら「コーディング規約あるよ…」って言われて死んだ) この頃はとにかく、毎日会社にいけば新しいチャレンジができて、自分のスキルが上がっていくのが身を以て体感できて仕事が楽しいと思っていたような気がする。 yurufuwa-tech.hatenablog.com yurufuwa-tech.hatenablog.com TSの言語機能勉強したりとかもしていた。 記事にしていないことを含め、継続的に勉強していたのだが、いつの日かやめてしまった。 というのも、プロダクトのコードを触る程度であれば、基本的な型やinterface/enum/typeあたりがわかっていれば差し支えなく、やっても実戦に活きないと感じたから。 実戦の役に立たなければそれは無駄な知識なのか、と言われれば絶対にNOだと思うしなんでやめてしまったんだろうと、ちょっとこの記事を書きながら後悔している自分がいる。 こういうところから差は広がっていくんだろうな。 7月 驚くほどに何をやっていたか思い出せない。それくらい虚無。 それなりに毎日仕事をして、帰ってご飯食べて寝て翌朝仕事に行くという生活をしていたんだと思う。 Slack遡って調べてみたら、Reactのパフォーマンス計測/チューニング的なことをやっていた。 結局、shouldComponentUpdateを適切に書いたり、PureComponentを使って再レンダリングを抑制するのがもっとも効果がある、という結論が出て、じゃあやるか、と思ってコードに手をつけたら、構造上手をつけられないコンポーネントが大多数で、結局ちょっとだけ手を入れて終了した記憶。。。。 8月 業務は引き続きなにをやってたんだか全く覚えてないくらい無難に黙々とタスクをこなしていた気がする。 プライベートでは勉強会に2本登壇した。なぜか2週連続で。 nihonbashi-js.connpass.com meguroes.connpass.com 喋りが苦手とかそういうのは練習不足だったのもあるし、致し方ないと思えたが、やっぱりエンジニアとして自分はイマイチなんだなと思った。 こういう場にいくと上には上がいることを思い知って辛くなってしまう。こういうタイミングで、悔しさをバネにして成長できる人は大成するんだろうと思うが、残念ながら僕はそう言うタイプではない。 28歳くらいまでにスペシャリストとかそういう技術で食ってる状態になれなかったらエンジニア辞める 今決めた — もがみん (@mogamin3) 2019年8月8日 こんな発言をしていた。発言当初はできると思って発言しているんだと思うが、今は全く自信がない。 9月 流石にまだ記憶にある。 ここまでの振り返りでお気付きの通り、普段の開発アイテムは一通り無難にこなせるようになって、完全に仕事がつまらなくなっていた。 そんなタイミングで降ってきた巨大開発アイテム。ある画面の挙動を変更するために、アプリケーション全体のデータ構造を変更するというものだった。 普段の開発アイテムは、雑に見積もっても大抵それ通りに終わるし、と思っていつも通りろくに既存の実装も確認せず見積もりをしたら大誤算。数日残業しまくっても終わらず、決められたバージョンでのリリースができなかった。 ここにきて初めて挫折した。 というのが半年の振り返り。綺麗にまとめて、じゃあ次の半年もがんばるぞ!って言って終わるつもりが記事を書き始めたらこうなってしまった。 慣れって怖くて最近全然仕事に対して、やりがいとか楽しさを感じなくなってしまった。 おまけに、周りはすごい人だらけ自分は上半期トータルで見ると全然成長した実感がない。 今目の前にある仕事に本気で向き合ったら、その先には何があるんだろうか。 そもそも自分がどうなりたいというのがなさすぎて、何に向かって努力すればいいのかわからない。 あるのは、自分の書いたものが意図通りに動くことは嬉しいし楽しいという気持ちだけ。とはいえそんなの学生インターンでもできる。 じゃあどうすればいいのか、何を目指せばいいのか。全くわからん。 そして、こういう自分の意思がない人は会社も求めてないだろうと思うと、余計に苦しい。 追記 どこ目指してんのかわからんけど、とりあえず目の前の仕事を全力でやるよ — もがみん (@mogamin3) 2019年10月6日 将来とか知らんけど目の前の仕事は全力でやることにした。 点と点はどっかでつながるかもしれないし スティーブ・ジョブス 伝説の卒業式スピーチ(日本語字幕) - YouTube この動画、中学生の時に初めて見て、それなりに感銘を受けたつもりだったが、先日思い返してまた観たらその時より染みた。
2019/10/06 from blog

TypeScriptのReadonly/Partial/Pick/Recordについてまとめる

引き続きTypeScript handbookの英語に苦しみつつ読み進めています。 ちょっとだけ日本語訳にも頼ったりしているけど許してね。 さて、今日はAdvanced TypesのMapped Typeというところに出てくるReadonly/Partial/Pick/Recordという型について。 つい先日やりたいと思っていたことが全部解決したので、自分用メモとしてまとめておきます。 www.typescriptlang.org Readonly これは、既存の型の各プロパティを読み取り専用にしたい時に使う型。定義は以下。 type Readonly<T> = { readonly [P in keyof T]: T[P]; } 使い方は、 interface SomeType { hoge: string; } type ReadonlySome = Readonly<SomeType> これでReadonlySomeは、 { readonly hoge: string; } と等しくなります。 Partial これは、既存の型の各プロパティをoptionalにしたい時に使う型。定義は以下。 type Partial<T> = { [P in keyof T]?: T[P]; } 使い方はReadonlyと変わらないので省略。ちなみに僕はこれがやりたくて、つい先日interfaceを2個書きました。。。 Pick これは既存の型から、一部のプロパティを抜き出した型を作るのに使う型です。定義は以下。 type Pick<T, K extends keyof T> = { [P in K]: T[P]; } だいぶ型が複雑になってきますね…。使い方は以下。1つ目の型引数には元となる型を渡して、2つ目の型引数には、キーを渡してやります。 interface SomeType { hoge: string; fuga: string; piyo: string; } type PickedType = Pick<SomeType, 'fuga' | 'piyo'> PickedTypeは、 type PickedType = { fuga: string; piyo: string; } となります。 Record 新しい型を定義するための型。(ちょっとうまく説明できない) 定義は以下。 type Record<K extends keyof any, T> = { [P in K]: T; } 使い方は以下。 type SomeType = Record<'hoge' | 'fuga' | 'piyo', string> ↑のようにするとSomeTypeは、 type SomeType = { hoge: string, fuga: string, piyo: string } と等しくなります。 実際はkeyofとかと組み合わせて、動的に型を生成するのに使うのかなと思います。 const some = { hoge: 1, fuga: 2, piyo: 3 }; type SomeType = Record<keyof typeof some, string> こんな感じ??? 所感 Readonly/Partialあたりは割とすぐ使いどころが出てきそうな感じがした。 あと、副作用として、これくらいのレベルの型の定義を読み解けるようになっておくと、他でも役に立つ気がした。 今日も朝から学びになりましたね。
2019/06/18 from blog

JavaScriptのインスタンスメソッドを変数に代入してはいけない

JSerにとっては当たり前の事なのかもしれないが、うっかりハマってしまったので備忘録として書いておく。 こんな感じのコードがあったして… class User { constructor(name) { this.name = name; } getName() { return this.name; } } const user = new User('mirin'); UserクラスのインスタンスであるuserのgetNameメソッドを呼び出します。 user.getName() // -> mirin これは間違いなく、インスタンスかする時にコンストラクタで指定した名前が返ってきます。 しかし、以下のような感じで呼び出すと… const gn = user.getName gn() // -> Uncaught TypeError: Cannot read property 'name' of undefined となる。 なぜか。 (ちょっとこの辺は正確さに欠ける表現があるかもしれないので、ご承知おきください) JavaScriptのthisは、呼び出したオブジェクトが入ります。(アロー関数を使った場合の挙動は別になります。要注意) user.getName()の場合は、userがthisになるため、名前を取り出す事ができますが、メソッド自体を変数に代入して呼び出してしまうと、thisはundefinedとなってしまうため↑に示したエラーが起こります。 ちなみに 実際に僕がやらかしたのは、条件によって呼び出すメソッドを変える必要があるという、割と複雑なロジックを書いていた場面でした。 結局、それくらい複雑なことをやるなら関数分けた方がいいよね、となってやめたのですが、もしインスタンスメソッドを変数に代入したい場合は、 const gn = user.getName.bind(user) gn() // -> mirin という感じで、bindを使ってthisを束縛してやればOKです。もしくはメソッドの定義をアロー関数を使う、でもOKです。
2019/06/15 from blog

TypeScripのkeyofについて

TypeScriptのHandbookに一通り目を通す、というチャレンジを今週はしております。 なんとも読みにくい英語だなーなんて思いながら読んでたらkeyofという知らない演算子が出てきたので、調べてみました。 keyofが出てきたのはこちらの「Using Type Parameters in Generic Constraints」というセクション。 www.typescriptlang.org サンプルコードを引用すると、 function getProperty<T, K extends keyof T>(obj: T, key: K) { return obj[key]; } let x = { a: 1, b: 2, c: 3, d: 4 }; getProperty(x, "a"); // okay getProperty(x, "m"); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'. こう。 どうやら、keyofにオブジェクトのキーを渡すと、そのオブジェクトのキーのいずれかを取るUnion Typeになるみたいです。 単純にするとこう interface HogeInterface { a: string; b: number; c: boolean; } type Keys = keyof HogeInterface; const hogeKey: Keys = 'a'; const fugaKey: Keys = 'd'; // error Keysは'a' or 'b'or'c'になります。 特定のオブジェクトのkeyの値しか許容しない、みたいなパターンの時に使えるって話なんだとは思うのだがこれがどこで使えるのか…というのはちょい謎。。。 誰か教えてほしい。 追記 2019/06/15 誰か教えて欲しい。 と書いていたら本当に教えてくれた方がいました。感謝。 shgam.hatenadiary.jp
2019/06/13 from blog

結局ジェネレータって何に使うの…?って話

JavaScript基礎力強化を図っています。 初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発 作者: Ethan Brown,武舎広幸,武舎るみ 出版社/メーカー: オライリージャパン 発売日: 2017/01/20 メディア: 単行本(ソフトカバー) この商品を含むブログを見る この本を読み返しながら、知識のないところを学習するシリーズ。 ※先に結論を話すと、表題に関して答えを見つけられませんでした😉 ジェネレータについて話す前に、イテレータについて。 JSのイテレータについてざっくり 他の言語にあるイテレータ同様、繰り返しのための機構で、JSの場合Array/String/Map/SetなどがIterable(イテレート可能)なオブジェクトです。 イテレート可能なオブジェクトは[Symbol.iterator]という名前で、iteratorプロトコルに準拠したメソッドを実装しています。(Symbol.iteratorについては前回の記事参照) developer.mozilla.org 詳しくは↑のMDNをみてもらうとして、ざっくり説明すると、 nextという名前のメソッドを持つ 呼び出した時に{value: any, done: boolean}なオブジェクトを返す というのがイテレータの条件です。 上記の条件を満たすことでfor..ofが使えたりします。もちろん自作のクラスに対して実装してあげてもOK。 で、ジェネレータは? で、なぜイテレータについての説明を先にしたかというと、ジェネレータは呼び出すとイテレータを返す特殊な関数のことです。 こんな感じで定義します。 function* generator() { yield 'hoge' yield 'fuga' yield 'piyo' return } function*とyieldという特別なキーワードを使って宣言するのが特徴で、この関数を呼び出すとイテレータがかえります。 const it = generator(); it.next(); // -> {value: 'hoge', done: false} it.next(); // -> {value: 'fuga', done: false} it.next(); // -> {value: 'piyo', done: false} it.next(); // -> {value: undefined, done: true} こんな感じ。 何が起こっているかというと、ジェネレータが返したイテレータを実行していくと、ジェネレータ内のyieldまで実行して、渡された値を返します。 実行はその時点で一旦ストップし、次に呼ばれたら、前回のyieldの位置の続きから実行して、次にyieldが出てきたら、渡された値を返します。 最後、returnが呼ばれるとイテレータはdone: trueを返すようになります。 また、イテレータのnextメソッドには引数を渡すことができ、 function* generator() { const name = yield 'What is your name?'; console.log(`Your name is ${name}.`); return; } const it = generator(); it.next(); // -> {value: 'What is your name?', done: false} it.next('mogami'); // Your name is mogami. // -> {value: undefined, done: true} みたいな感じで、前回実行したyieldの返り値がnextに渡した値になります。 何に使えるのか やっとここで何に使えるのか、という話になります。 オライリー本では、イテレータ/ジェネレータの説明は12章で行われているのですが、14章 非同期プログラミングのところで再度ジェネレータが出てきます。 ジェネレータランナーという関数を用意することで、非同期処理が同期的に書けるという話。 本のソースコードを引用すると、 function grun(g) { const it = g(); (function iterate(val) { const x = it.next(); if (!x.done) { if (x.value instanceof Promise) { x.value.then(iterate).catch(err => it.throw(err)); } else { setTimeout(iterate, 0, x.value); } } })(); } こんな感じの関数を用意してやって function* fileReadAndWrite() { const dataA = yield readFile('a.txt'); const dataB = yield readFile('b.txt'); const dataC = yield readFile('c.txt'); yield writeFile('d.txt', dataA+dataB+dataC); } (readFile/writeFileはいずれもPromiseを返す関数) 最後にこのジェネレータを最初に作ったジェネレータランナーに投げ込む grun(fileReadAndWrite); すると、非同期処理が同期的に書けて人間にみてもわかりやすいよね、と書いてありました。 とはいえ、コレって今となってはasync/awaitで解決しちゃう問題なんですよね…。 async function fileReadAndWrite() { const dataA = await readFile('a.txt'); const dataB = await readFile('b.txt'); const dataC = await readFile('c.txt'); await writeFile('d.txt', dataA+dataB+dataC); } fileReadAndWrite(); こうか? で、よりわけわからなくなった。 じゃあもうジェネレータって何に使うのよ、って感じですね。 はぁ…。
2019/05/30 from blog

RegExp.prototype.execが偶数回しか動かない謎に遭遇したハナシ

先日、既存のコードのテストをしていたところ、正規表現のマッチの結果が実行するごとに変わるという謎の現象に遭遇しました。 適当な例を作るとこんな感じ。 const regExp= /\*\*(.+?)\*\*/g; // MarkdownのBoldの箇所を抽出する正規表現 const markdown = "こんにちは。今日の気温は**33度!**とめっちゃ暑いので熱中症に注意しましょう!" regExp.exec(markdown); 意図としては、Markdownの文章中からBoldのところ(アスタリスク2つで始まり、間になんらかの文字があって、アスタリスク2つで終わる)を抽出するという感じ。(もちろん実際のMarkdownパーサを書くならもっと考慮する事はありますが。。。) 実際には、これがUtil系の処理の一部として組み込まれていて、場合によっては数回叩かれるケースがある、というようなコードでした。 さて、これを実行してみると以下のような結果になります。 regExp.exec(markdown) /* ↓結果 [ '**33度!**', '33度!', index: 12, input: 'こんにちは。今日の気温は**33度!**とめっちゃ暑いので**熱中症に注意**しましょう!', groups: undefined ] */ Node.jsで実行していますが、ブラウザでも同じだとおもいます。 見事「33度!」という値が取り出せているので、これで良さそうな感じがします。 しかしこれと全く同じコードをもう一度実行するとこうなります。 regExp.exec('/hoge?fuga=thisisvalue') null なんということでしょう…。 ちなみにこれ以降、もう一度実行すると成功し、さらにもう一度実行すると再びnullになるという挙動を繰り返します。 MDNのexecメソッドの説明をみると以下のように書いています。 developer.mozilla.org exec() メソッドは、指定された文字列内で一致するものの検索を実行します。結果の配列、または null を返します。 実はこれが罠で、結果の配列を返すというのは、一致する全ての結果を配列で返すという意味ではないのです…。 今回正規表現にgフラグが付いているのに気づいたでしょうか…? これはグローバルフラグと呼ばれるもので、文字列中から正規表現に一致する全ての結果を得たいときに使います。今回の例の場合、これをつけるとexecは実行するたびに、前回ヒットした位置より後ろで、正規表現にマッチする箇所がないかを探すという挙動をします。 探した結果、存在しなければnullを返します。偶数回しかうまくいかなかった原因は、1回目は文字列を先頭から探して、ヒットする箇所があったので値が返却されましたが、2回目の実行では、前回のヒット位置より後ろ側にヒットする箇所がなかったためnullが返ります。これが今回遭遇したバグの原因となっていました。。。 どう解決するか 解決アプローチは複数あります。 まず1つ目。RegExpクラスのインスタンスは前回のヒットした位置をlastIndexというプロパティで持っています。 developer.mozilla.org lastIndex は、次のマッチの始まりの位置を示す、正規表現インスタンスの読み書き可能な整数値のプロパティです。 とあるので、この値をexecの実行前に0に戻してあげれば、毎回同じ結果を返す事になります。 ただし、通常gフラグを使うという事は、複数マッチする事が想定されているはずなので、毎回0に戻すと、先頭のマッチしか取得できなくなってしまいます。 そこで2つ目のアプローチは、String.prototype.matchを使うというパターン。 developer.mozilla.org こちらはexecとは異なり、gフラグが付いている正規表現を使用すると、一致する全ての箇所が配列となって返ってきます。 "**hoge** fuga piyo **puyo**".match(/\*\*(.+?)\*\*/g); // -> [ '**hoge**', '**puyo**' ] ただしこちらは、マッチした位置のindexなどの詳しい情報や、カッコを使ったキャプチャ(正規表現内でカッコを使うとカッコ内の文字を取得できる)を使う事ができないため、必要に応じてマッチした文字列をさらに加工する必要が出る可能性があります。 ……あ、もちろん先頭のマッチ結果しかいらないならgフラグを外す事でexecの結果は冪等になりますことよ! 要件次第というところかなとは思いますが、一つ言えるのはgフラグが付いている正規表現を使うときはロジックを一度確認してみたほうが良いということですね。 なるべく副作用のない関数を書きたいと心がけているのですが、まさかこんなところに罠が潜んでいるとは…。という感じでした。おわり。
2019/05/26 from blog

ES6で追加されたSymbolって結局なんなのか

JavaScript基礎力強化を図っています。 初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発 作者: Ethan Brown,武舎広幸,武舎るみ 出版社/メーカー: オライリージャパン 発売日: 2017/01/20 メディア: 単行本(ソフトカバー) この商品を含むブログを見る この本を読み返しながら、知識のないところを学習するシリーズ。 ES6から新たにSymbolという型のデータが追加されました。 developer.mozilla.org Symbol() 関数は常に一意の値を返します。symbol 値はオブジェクトのプロパティ識別子として使われます。symbol 型はこの目的のためだけに使われます。 とのことなので、実際にどんな感じで使われるのかをみていこうと思います。 シンボルの特徴 シンボルはSymbol()関数で作ることができます。 先頭が大文字なのでクラスっぽいですが、new Symbol()は使えず、 エラーになります。 Symbol()は呼ばれる度に一意な値を返します。つまり Symbol() === Symbol() // -> false となります。 使われ方 その① MDNにもあるように、シンボルはオブジェクトのプロパティ識別子(=キー)として用いることができます。具体的には const sym = Symbol() const obj = { [sym]: 'hoge' } ということができます。([sym]としないと、symという名前のキーになってしまうので注意) これが具体的に役に立つケースは、既存のオブジェクトやクラスに対して、プロパティを追加したりするパターン。 Symbol登場以前は既存のオブジェクトやクラスに対してプロパティを追加する際に、キーが競合する可能性があるのを回避する手段がありませんでしたが、Symbolは作成する度に一意な値となることが保証されているので、安全に行うことができます。 const TATEGAKI = Symbol(); // Stringのインスタンスメソッドに縦書き(1文字ごとに改行)にするメソッドを追加する String.prototype[TATEGAKI] = function () { return Array.from(this).join('\n') } console.log("文字列"[TATEGAKI]()) これでESの仕様で縦書きにするメソッドが実装されても(笑)自分の作った縦書きメソッドと衝突する恐れはないので、実行系が新しくなった瞬間に既存のコードが壊れるといった現象を回避することができます。 使われ方 その② シンボルにはSymbol()を使って自分で作る値だけではなく、事前に定義された値があります。 その中の一つに、Symbol.iteratorという値があります。この値は、イテレート可能なオブジェクト(StringやArray、Map、Setなど)がイテレータを持つときのキーとして使われています。 "Stringはイテレータを持っています"[Symbol.iterator]; // -> function new Date()[Symbol.iterator]; // -> undefined なぜシンボルをキーに使うかについては、以下の記事が大変わかりやすかったです。 qiita.com ざっくりとまとめると、 JSには特殊メソッド(使用者が上書きしてはいけないメソッド)を定義する方法がない いきなり、イテレータを返すメソッドの名前を仕様で決め打ちにしてしまうと、正常に動かないプログラムが発生する可能性がある そこで定義済みのシンボルを用意し、その値をキーとして用いることで、安全に特殊メソッドを実装することにした。 という感じ。言語の仕様を考えるような人たちって、本当に頭いいんですね…と思いました。
2019/05/22 from blog

近況報告

なんとびっくり、ぴったり80日ぶりの更新です。 お久しぶりです。 ブログを書く習慣をつけるのは大変だったのに、書かなくなったら本当に書かなくてびっくりしました。 前回の更新である、2月23日から今日に至るまでに何があったかざっくり書いておきます。技術的要素はないです。 2月〜3月末 4月から入社する会社で、一足先にインターンとして働いていました。 内容としてはReact NativeとTypeScriptを使ったアプリ開発、という感じ。前回の更新がRNだったのも、業務の一環でつまづいたところとかのうち、一般的に役に立ちそうなものを書いたものでした。 無難に楽しく、週5日で働いてました。 人とコミュニケーションとるのがそれほど得意でない自分にとって、このインターン期間は既存社員とのコミュニケーションをとる良い機会になりました。 4月 入社。新元号発表のその日に入社式でした。 とはいえインターンで通い慣れていたので、いつも通り…と思って出勤したら入社書類を一式家に置いてあったことに30分くらい電車乗ってから気がつきました。 その場で引き返して、自宅最寄り駅から自宅までタクシーを使って、なんとか5分遅刻くらいで到着しました。入社式に遅刻しなかったのでセーフ。 そこから1ヶ月くらいは研修の日々。 最初の3日間くらいはビジネス職・エンジニア職合同の研修を受け、残りはエンジニア・デザイナーの研修。 こんな絶景の会議室で研修を受けてました 世の中の研修って結構つまらない、ひたすら退屈なイメージが強かった(こんな記事があったり)が、幸いにもうちの会社の研修は、必要最低限を抑えた実践的かつ、普遍的に使える知識を身に着ける研修で大変良かった。そこは良かった。 同期と仲良くなれずに悩んで、病みそうにもなったりしたけど、なんとか無事に研修を修了。 と、同時に世の中はGWに突入。私は横浜の実家を離れ一人暮らしを開始しました。 大学も実家から通っていたので完全に人生初の一人暮らしです。 引越し初日の様子 自宅の車がミニバンだったことと、実家が横浜とそれほど遠くないことから、自力での引越しを決断。 結局GWは荷物作っては車で運ぶというのを繰り返していたら終わってしまいました。 新卒1年目のGWとか、一番やる気に満ちてる時だったのに、有意義な時間を過ごせなかったのは残念。 一人暮らし話は引っ越して1ヶ月経ったくらいで書きたいな。ふとした瞬間(今とか)に死ぬほどさみしくなるけど、今のところはとっても楽しんでます。 5月 一人暮らし & 本格的な業務開始。 業務は結局インターン時代と同じチームに配属され、引き続きReact Nativeを使ったアプリ開発をやっています。 リリースからはすでに数年経っているものの、「とにかく機能開発を優先する」というフェーズからつい最近脱したアプリなので、手の入れどころ、リファクタリングのやりがいがあるプロジェクトだと個人的には感じています。 コード規模もまぁまぁ。利用者数も(正確な数字は知らないけど)下手すりゃ万単位で居る感じ。 JavaScript→TypeScriptの基礎力をこの辺りで一回ちゃんとつけておきたいと感じています。 一人暮らしの方はというと、やっと落ち着いてきて、生活のリズムもできてきたかなと思っているところです。 料理を作って写真を撮るということをなぜか趣味にしています。 同期にめっちゃ好評だったやつ CGみたいと言われた朝飯 with オライリーな朝食 こんな感じ? 今の所9割くらいの晩飯は自炊してます。クラシルには頭が上がらない。 あと、一人暮らしになって変わったことといえば、家のネット回線がとっても速くなりました。(実家はADSLだった) マンションタイプの光の割には速いと思うんですよね。 せっかく高い金払って光引いたのでちゃんと活用してお勉強しようと思います。 まとめ まとめもクソもない。 せっかく家に課金したので、この環境(出社時間が超短い/インターネットが引かれている静かな部屋が24時間使い放題)を活かして圧倒的成長を遂げたいです。 今日は眠いので寝ようかしらね。
2019/05/14 from blog

【ReactNative】AndroidとiOSではキーボードが開いた時の挙動が違う

※タイトルにRNとかいてますが、おそらくRNに関係ない話だと思います。多分。 ReactNativeを使ってて、キーボードが開いた時の挙動がOS間で違うのでは?と思って調べてみたらやっぱりそうだった、という話。 どっかに書いてるかな、と思ったけど見つけられなかったのでここに書き残す。 結論 どう違うのか なにがどう違うかというのをアニメGIFで撮ったので貼ります。 (追記: いらんとは思うけどコードあげました。 GitHub - uutarou10/rn-view-height-test ) (width/heightのラベルはそれぞれが100%に指定してある親Viewの値です) キーボードの分、Viewが縮むのがAndroidの挙動で、そうではないのがiOSの挙動です。 なので、キーボードが開いた時にキーボードの下に要素が隠れないようにするとか、そういうものを作ろうとするとちょっと工夫する必要が出てきます。 でも… Androidのキーボードが開いた時の挙動はAndroidManifest.xmlというファイルにあるandroid:windowSoftInputModeという値で設定されているようです。(この辺、Android開発者ではないのでかなり怪しめです。) react-native-cliで作ったアプリは、この値が最初adjustResizeになっています。(ちなみにAndroidManifest.xmlはRNの場合、android/app/src/main/AndroidManifest.xmlにあります) developer.android.com こちらのページに書いていますが、この値をadjustPanにすると、フォーカス位置が隠れないように画面をズラしてくれます。 adjustPanに設定した場合の挙動はこうなります。 ただ、画面をズラしてくれると書いたように、Inputがキーボードが出る位置の下にある場合、フォーカスが当たると全体的に画面がズレます。 当然画面上にある要素は見えなくなってしまうので、実際に使うには注意が必要です。 実際、先ほどのAndroid公式のドキュメントには、 一般にこの方法はサイズ変更に比べると望ましくありません。ユーザーがソフト キーボードを閉じて、ウィンドウの隠れた部分を操作する必要が生じる可能性があるためです。 と書いています。 じゃあお前どうすりゃええねん、という話はまた調査して書こうかなと。
2019/02/22 from blog

最近知ったTypeScriptのちょっとしたTipsとか

相変わらずインターンではTypeScriptを書いています。 最近は、ちょっと自分でも成長したなと思うのですが、バグの原因を追い求めてライブラリの中をウロウロしていたりします。 人生22年、ライブラリの中をのぞいてみよう、なんならバグ見つけてPRだそうとか考えたこともなかったですが、人間必要になればやるし、やってみると案外できるもんですね。(もちろん楽ではないけど、一個ずつ読み解くことくらいは、努力次第でできるな、と思った。) 雑談はさておき、そんなこんなの業務の中で知って、「へー」と思ったTypeScriptの諸々をメモ書き程度に書いておきます。 tscのメッセージを日本語にする Compiler Options · TypeScript まぁ公式に書いていることなんですけど。(この記事に出てくることは、私が知らなかったというだけで、全部公式に書いていることです。私の勉強不足です。) オプションとして--locale jaを渡してあげると、いろいろ日本語になります。 たとえばこんなの $ tsc --locale ja バージョン 3.2.4 構文: tsc [オプション] [ファイル...] 例: tsc hello.ts tsc --outFile file.js file.ts tsc @args.txt tsc --build tsconfig.json オプション: -h, --help このメッセージを表示します。 -w, --watch 入力ファイルを監視します。 --pretty 色とコンテキストを使用してエラーとメッセージにスタイルを適用します (試験的)。 --all コンパイラ オプションをすべて表示します。 -v, --version コンパイラのバージョンを表示します。 --init TypeScript プロジェクトを初期化して、tsconfig.json ファイルを作成します。 -p ファイルまたはディレクトリ, --project ファイルまたはディレクトリ 構成ファイルか、'tsconfig.json' を含むフォルダーにパスが指定されたプロジェクトをコンパイルします。 -b, --build 最新でない場合は、1 つ以上のプロジェクトとその依存関係をビルドします -t バージョン, --target バージョン ECMAScript のターゲット バージョンを指定します: 'ES3' (既定)、'ES5'、'ES2015'、'ES2016'、'ES2017'、'ES2018'、'ESNEXT'。 -m 種類, --module 種類 モジュール コード生成を指定します: 'none'、'commonjs'、'amd'、'system'、'umd'、'es2015'、'ESNext'。 --lib コンパイルに含めるライブラリ ファイルを指定します。 例がぱっと用意できなかったですが、コンパイルエラーなどももちろん日本語になります。 英語がわからんとき、やってみると救われるかもしれない。 (TSのコンパイルエラー自体そんなに難しい英語は一切出てこないので、必要かと言われれば微妙ですが) (変数名)!(Non-null assertion operator) コード読んでいたら、hoge!(hogeは変数)みたいなのが出てきて、これはなんだ?と思ったという話。 !という時点で察しのいい人は分かりそうな気もしますが、これはコンパイラに対して、変数が強制的にnullにならないと伝えるためのオペレーターみたいです。(Non-null assertion operatorと言うらしい) つまり、hoge変数の型がstring | undefinedだったとき、hoge!とするとhoge as stringとした時と同じ動きをすることができるようです。asなんちゃらと書くとどうしても長くなるので、これは使っていきたいテク。(本来はキャストなんぞ使いたくないが) ここに書いてた。 TypeScript 2.0 · TypeScript 型と型を&でつなぐ(Intersection Types) うまい例が思いつかないですが、こんな感じ。(公式の例をパクってシンプルにした) interface Person { name: string; age: number; } interface Speakable { greet(): void; } const kanameRin: Person & Speakable = { name: '鹿目凛', age: 22, greet() { console.log('イラストも描けちゃうあなたの彼女♡'); } } PersonとSpeakableというインタフェースが宣言されていて、定数kanameRinはPerson & Speakable型になっています。 右辺を見てもらえれば一目瞭然ですが、型名と型名を&でつなぐことで、型を組み合わせることができます。 (ちなみに、サンプルコードの元ネタはこちら。最近の推しです。) ちなみに interface A { hoge: string; } interface B { hoge: number; } const aAndB: A & B = { hoge: 'hoge' // ここでコンパイルエラーになる、hogeはstring & number型 }; こんな感じで、同名で別の方が存在すると、hogeはstirng & number型として扱われるみたいです。(なので上記の例はエラーになります。) これ、string | numberとして扱ってくれた方がいいような気がしなくないけど、そうでもないのかしら。 あ、ちなみにこのような感じで、型を&でつなぐのをIntersection Typesというみたいで、以下に載ってます。 Advanced Types · TypeScript
2019/02/21 from blog

インターンを始めて1週間が経った。

表題の通りなのだが、4月から就職する内定先で、入社に先立って、インターンを始めて約1週間が経過したので、今の気持ちをまとめておこうかな、というのがこの記事の主旨。お気持ちポエムなので、スルーしてほしい。 何をやっているか どこまで書くと怒られが発生してしまうのかわからないので、適当にぼやかして書くと、TypeScriptで書かれたReact Nativeアプリの機能開発をしています。 とは言いつつ、1週間では環境構築→設計の理解→追加する機能の設計→見た目に関係のない部分の実装というところまでしか到達しなかったので、RN要素はほぼ無で、ひたすらTypeScriptと戯れていた感じの1週間でした。 1週間過ごしてみての所感 技術以外のところで結構課題を感じたので、とりあえず書いておく。 初日、出社したらきているはずのSlackの招待が来ていないというトラブルに見舞われた。おまけに、一緒のチームの人たちは朝からミーティングで席を外してしまうという…。 自分の席の周りに誰もいなくなってしまって、Slackの招待も来ていなくておどおどしてしまった。 結局、数分おどおどしたあと、なんとか顔見知りのエンジニアの人を捕まえて、指示を仰ぐことができたが、どうしてもっとサクッとできないかなーと、ちょっと自己嫌悪に陥った。 実際仕事を始めてみると、様々な機会でコミュニケーションをとる必要があることを知った。既存の実装のわからないところを開発メンバーに聞いたり、API仕様を聞くためにサーバーサイドのエンジニアのところに行ったり。 幸いなことに、関わる人は皆さんいい人で、私が新人であることも理解してくれているので、どんな小さなことでも聞いたら丁寧に教えていただけるので、1週間経ってやっと慣れてきた感じがあるが、それでも初めての人に声をかけるのは精神的に結構くる。 これから先、入社したらもっと多くの人と関わる機会があると思うし、チームの入れ替えとかも結構激しくやってるような話を聞いたりするので、コミュニケーション能力の強化は真っ先に今後の課題になった。 ひとまず、精神的にきつくてもガンガン話しかけるということを目標に週の後半は過ごしてみた。 仕様の確認とかも、トレーナーが代わりにやってくれていたのを、誰に聞けばいいかだけ聞いて自分で行くようにしたり、ディスプレイがなかったので、貸してほしいとCTO(!!)に言いに行ったり。 CTOに直接言いに行くのは、さすがに緊張してしまって、喋る言葉がフェードアウトするというコミュ障大爆発っぷりだった。 ちょっと与えた印象悪かったかもなぁ…とか考えちゃうけど、そんなことずっと考えてても仕方がないので、忘れることにする。 技術編 技術的なところでももちろん課題に感じたことはたくさんあった。 割としっかり触ってきたつもりのTypeScriptも、業務レベルになれば全然理解が足りてないし、でかいコードの動きを追うのは本当に厳しいし、ついでに環境構築でも結構つまづいたし。 そんな感じのレベルでも、呆れず懇切丁寧に教えてくれるトレーナーをはじめとする周りの皆さんには頭が上がらないし、現状は時給泥棒状態なので、早く給料に見合った働きをできるレベルまで成長していきたいです。 本当は、技術以外編と同じくらいの分量、技術編も書いていたんだけど、技術は(少なくとも自分の現在のレベルでは)やればやるだけ伸びる状態にあると思うので、あえて書かないこととしてみた。 お尻に火のついた僕は強い。 結局何が言いたかったのか 文章書くの苦手なのに、オチを考えずに書くので、いつも駄文が出来上がる。この辺も今後の課題としていきたい。 ここまで読んでしまった方がいたら、ごめんなさい。言ってくれたらお詫びにコーヒーおごります。 結局何が言いたかったのか僕もわかりませんが、月曜から始まる次の1週間は、 頑張ってコミュニケーション取っていく。コミュ力の底上げにチャレンジする。 頑張らずにコミュニケーション取れるようになるのは頑張った後なのではないかなという仮説 自分の限界を決めず、(少なくとも今はまだ限界が見える段階じゃない)貪欲に学ぶ。フロントエンド書いているけど、必要ならサーバーサイドも読むとか、今開発している機能以外の部分についても、理解を進める。 とかこん感じでチャレンジしていこうかな。 月曜が楽しみです。 実は土曜日は1週間の疲れで丸一日死んでいたので、日曜は月曜に備えて勉強したりしたい。(インターン生はコードを持ち帰れないので、きついなーとか思っていたけど、実際の実装という超具体的なものではなく、もっと抽象的なところを学べというメッセージなのかもとか勝手に思った。多分違うけど)
2019/02/16 from blog

【iOS12】iOS Simulatorにペーストするのがうまくいかない時

久しぶりの更新です。ずっと書いてないと書く習慣が失われそうなので、ちっちゃなネタでもどんどん投下していきます。 昨日から始めたバイト?インターン?での知見。 Macでコピーした文字列などをiOS端末上で貼り付ける方法。iOSはv12、Xcodeはv10.1です。古いバージョンだと違うかも。 通常はCmd + Vで通常通り貼り付けられます。なんの問題もないです。 ところが、開発していたら急に効かなくなってしまいました。 長いURL手打ちするのかよ〜と思っていたのですが、 Edit > Automatically Sync Pasteboardのチェックが外れていました。 この状態でコピペを使う方法は2通りあって、 Automatically Sync Pasteboardのチェックを入れて再度Mac側でコピーする Send Pasteboardをクリックして、iOS内で貼り付けの操作を行う です。 古い情報に惑わされたりして地味に時間を潰したので書いてみました。
2019/02/13 from blog

PuppeteerのちょっとしたTipsいろいろ

ちょっと用事があってPuppeteerを初めて触ってみました。 以前、バイトをしていた時にSeleniumを触っていたことがありましたが、そちらと比べると、サクッとインストールできるし(npmだけで入る)、async/awaitで現代的だし、素晴らしいです。 Puppeteer触ってて調べたことをメモしておく。ちなみにv1.12.1。 PDFにマージンを設定する const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://example.com'); await page.pdf({ path: savePath, format: 'A4', margin: { top: 30, left: 30, right: 30, bottom: 30 } }); await browser.close() こんな感じ。 ブラウザを表示する(非ヘッドレスにする) launch()を呼ぶ時に、 await puppeteer.launch({headless: false}); としてあげる。 ちなみに、要注意な点として、非ヘッドレス状態では、PDF出力は利用できずエラーになります。 (Error: Protocol error (Page.printToPDF): PrintToPDF is not implementedとなる) 直接HTMLをブラウザに流し込む Webサイトを開くのではなく、直接HTMLの文字列を流し込みたい時。 await page.setContent('<h1>Hello Puppeteer!!</h1>'); こんな感じ。 これと、ejsを組み合わせてちょっと企んでますが、その話はまた今度。
2019/02/05 from blog

findコマンドでパスを検索する(ディレクトリも含めて検索する)

ド初心者かよ、という話。(普段からシェル慣れしている人なら、当たり前に知っていそうな話) あまりそのようなシチュエーションもないかもしれませんが、弊研究室は、卒論発表のスライド資料を全員共通のGitリポジトリで管理しています。 ディレクトリ構成は(user name)/卒論/(ユーザー名).pptxみたいな感じになっています。(実際とは少し違うけどだいたいこういう感じ) これをうまいことスライドだけ集めて発表用PCにコピーしたいという話。 -nameオプションはファイル名に合致するものしか検索できないので、どうしたものかと思っていたら-pathというオプションがあるみたいです。(-wholenameでも同じ) というわけで、 $ find -path "*/卒論/*.pptx" -exec cp {} ./slides + みたいにすることで、うまくいきました。めでたしめでたし。というわけで、これから卒論発表してきます😀 ちなみに、findのexecでハマったところ↓ takuya-1st.hatenablog.jp
2019/02/03 from blog

22歳になりました。気が狂いそうな話。

22歳になりました。 もう誕生日も終わりそうですが、本日2月2日で22歳になりました。めちゃ2が並ぶ。 今年はというと、就職というビッグイベントが待っているので、激動の1年になりそうです。頑張ります。 人生の目標としては、自立することでしょうか。なんだかんだ、親に頼りながらここまできたので、就職をきっかけに、経済的にも心理的にも自立して生きていけるようになりたいです。 具体的なアクションとしては、一人暮らしがあるのかなと現状では考えています。資金貯めたりして、2019年内くらいで引っ越ししたいな、という目標です。 気が狂いそうな話 そして、気が狂いそうな話。 悲しいことに、10年弱使ってきたTwitterアカウントがロックされました。 ことの発端は、2月1日。何気なくTwitterのプロフィールにある誕生日を登録したところ、突然↑の画面に。 実は、今まで使っていたアカウント、2009年に登録したものなので、当時12歳。これがマズかったようで、Twitterのガイドラインに違反してロックと相成りました。 フォームから、解除の申請は出してみたものの、希望は薄そうです。 僕くらい、Twitter漬けの日々を送っていると、Twitterアカウントのロックは致命傷のようなもの。 何も表示されないタイムラインを見るために、5分おきくらいにTwitterのアプリを開いてしまう始末。凍結されたことを報告するためにTwitterアプリを開くアホさ。 愚痴や、情報源や、昔のサークルの人々との連絡も全てTwitterでやっていたので、アカウントが死んだことで、孤独老人のようなお気持ちになってしまいました。知らんけど。 アカウントは最悪どうでもいいので、フォロー、フォロワーだけ復元させてほしい…。Twitterさん…。
2019/02/02 from blog

今更ながらtypescript-fsaが地味に便利だなという話

3日ぶりのブログ更新です。 「ゆるふわ技術日誌」なのに、技術のことでもない日記をつらつらと書くのも、精神的に来るものがあるので、これからは更新頻度を落としても技術的なことを書くブログにしていきたい所存。 久々にReactやりたいな(というかやらないと、書き方忘れそうだな)と思ったので、小さなアプリを作り始めました。 React + TypeScriptのプロジェクトを作るのも、いつのまにか $ create-react-app hoge --typescript でできるようになってるし、すごい。 Reduxのアクションやreducderは、普通のJSで書くのであれば、そのままてきとうに書けばいいのだが、TypeScriptとなると、型を当ててあげないとダメですね。(ダメってことはないけど、それならJS使う) その時に便利なのがtypescript-fsa。 github.com Reduxの型定義ファイルにも、Actionの型とか定義されてるけど、どうもいまいちなので、その辺をよしなにしてくれる。 import { Action } from "redux"; import actionCreatorFactory, { isType } from 'typescript-fsa'; const actionCreator = actionCreatorFactory('common'); export const signedIn = actionCreator<{ uid: string }>('SIGNED_IN'); interface StateType { uid: string | null; } const defaultState: StateType = { uid: null }; export default (state: StateType = defaultState, action: Action) => { if (isType(action, signedIn)) { return { ...state, uid: action.payload.uid }; } return state; }; こんな感じ。 なんかもっと語るつもりだったけど面倒になってしまった。
2019/01/29 from blog