【2021年】23歳⇨24歳。厄年を✅

現役エンジニア3人、運営一人と飲んで自分も現役エンジニアになったと勘違いしている23期早くエアコンを買いたいこと寝るときはダウン3枚着てるです。

 

宣伝

ZEROKENをリリースいたしました!

サイトURL

https://www.zeroken.site/

Image from Gyazo

簡単にお酒の強さを測る事ができて、アルハラを予防する事ができるアプリになります!

自分に合ったお酒の飲み方の順番を見つけて自分のペースで飲み会を乗り切ってください!

 

今日は12月31日ということで、2021年1月から12月までの一年を振り返っていきたいと思います。

さて、どんな一年だったのでしょうか。

2021年1月

出来事

  • html,cssを学習し始める。
  • 彼女が出来る
  • 資格を3つ取得。
  • トライアスロンチーム「iron will」に加入する
  • 転職に向けた企業探しを始める
  • トライアスロン用のバイク「Giant」を11万で購入する

心境

  • 1997年生まれは厄年だと聞き、「うわ、不安を煽ってお守りを交わせるタイプのやつだ。神社もマーケティングするんだな〜」と感じる。
  • 一緒にいて楽しい、笑顔可愛い、癒されるという3点に魅力を感じ彼女(今の彼女)と付き合った。
  • 生涯スポーツだから一生かけて自己記録を更新できそう。自分の限界を知りたいと思いトライアスロンを始める。
  • とりあえずmy naviのIT企業を片っぱしから応募してみる。
  • iron willの人が25%引で売ってくれるというので新品のGiantを購入。サドルが硬いことにイライラ。一漕ぎの推進力に驚きを感じる。

2021年2月

出来事

  • プログラミングスクールの説明会に複数応募(G’s academy,DMM ,RUNTEQ,GEEK JOB)。結局どこも入会せず。
  • 英検1級に落ちる。2028点合格のところ2004点だった。
  • ルービックキューブ6面を1分30秒で揃える事ができるようになる。
  • 転職先が決まる。
  • 吉祥寺のシェアハウスに移住を決める
  • 甥っ子に初めて会う。

心境

  • プログラミングと1年ぶりの再会を果たす。htmlにcssを使って色をつけられたことに感動をしていた。
  • 意外と英検1級ってちょろいと思っていた。正答率7割を超えたのに落ちてイライラ。
  • 転職先では最初の6ヶ月間でphpを学習し、その後はSESになる事ができると聞いていた。ワクワクが止まらなかった。
  • 新しい住居の下見をしてワクワク。外国人が多いため、英語の勉強になっていいかな。
  • 甥っ子が可愛い。

2021年3月

出来事

  • 将来起業するためには何をすればいいのかと本気で考えるようになる。「LIFE SHIFT」「WORK SHIFT」を読む。
  • 課長、次長、支店長に退職を告げる。
  • マナブログに感化されてword pressでブログを始める。
  • 食事に興味を持つ。オートファジーで暮らすために16時間のプチ断食を始める。7日で終了。空腹には耐えられないと悟る。
  • 両学長にハマる。長期投資、格安スマホ、FIREに興味を持つ。

心境

  • 「100年ある人生を幸せに生きるためにはどうすればいいか」を漠然と考えていた。割と迷走していた。
  • 月5万稼げる副業に興味を持っていた気がする。それゆえ、マナブログ、両学長、中田敦彦Youtube大学、西野孔明エンタメ研究所などにハマっていた。
  • 退職を告げる時は、好きな人に告白をする時のように緊張した。浮き足立っていたような気がする。10年目に年収が1000万円になる会社を辞めるんだ俺は。すごい決断をしているんだ。と息巻いていた。
  • プチ断食をすることで体内の炎症を抑えることに興味を持っていた。

2021年4月

出来事

  • 転職をする。
  • phpを学習し始める。サイト作成に勤しむ。
  • ふるさと納税を頼む。
  • 高配当株に興味を持つ。SPYD、VOOを一括購入する。
  • 陸上を再開し始める。

心境

  • phpが難しい。ログイン機能に苦戦。<? echo hoge?>の記述に目が慣れてきたな。
  • html,cssのレスポンシブ対応にイライラ。
  • シェアハウスにreactでアプリを作ったという大学3年生がいることを知る。

2021年5月

出来事

  • Reactを使ったアプリ作成に興味を持つが、挫折。
  • SQLが分からない。
  • 横浜国際トライアスロンに初出場。
  • Web制作とWeb開発の違いを理解し始める
  • 案件先がテレアポの会社になる。もちろん業務中にコードはさわれない。

心境

  • 6ヶ月かかるカリキュラムが意外と2ヶ月くらいで終わりそうだな。ポートフォリオを作成するフェーズに入ったが、作るイメージがわかない。
  • 退社の意向を固める

2021年6月

出来事

  • Ruby on Railsを学習できるプログラミングスクール(RUNTEQ,Fyord BootCamp)を探し始める。
  • 退職の意向を伝える。
  • 40kgのダンベルをAmazonで購入。毎日筋トレ生活が始まる。
  • 現場Railsを始める

心境

  • RUNTEQがいいらしい。amazon株を売却して得た資金で入学金を工面。
  • なりたい自分になれないというかなり曖昧な理由で退職を伝える。

2021年7月

出来事

心境

  • sorcery課題が尋常じゃないくらいに難しい。というより、環境構築が出来なくてイライラ。

2021年8月

出来事

  • 高校で部活が同じだった同士と本格的に陸上競技を始める。
  • 彼女の誕生日を祝う。
  • アプリ「Optime」をリリースする。

心境

  • 陸上競技を通じて運命的な出会いを果たした。人生何があるか分からないな。
  • 彼女が可愛い
  • 個人開発が面白い。

2021年9月

出来事

  • 10月からシェアハウスの家賃が2万引上ることに。陸上の同志と競技場から近い武蔵小杉に引っ越さないかと提案をする。そして引っ越し。
  • RUNTEQカリキュラム応用篇が終了。READMEの作成に入る。

心境

  • 新生活にワクワク。武蔵小杉タワマン多すぎやろ。引っ越し先にエアコンがついていないことに気がつく。なんとかなるだろうと考える。
  • いよいよアプリの作成だ〜ワクワク。飲み会で飲むお酒の順番を診断するアプリにしよう。そうだな、名前は「Preliquo」にしよう。

2021年10月

出来事

  • 陸上生活3ヶ月目。現役の時の感覚が戻ってくる。
  • ポートフォリオを作成し始める。
  • Vueが分からない。
  • MySQLのエラーに1週間費やす。

心境

  • 思ったよりアプリの完成が進まなくて焦る。診断系はjavascriptを使って動きをつけたほうが離脱率が下がると聞いたからVueを使った。しかし、キャッチアップに時間がかかりすぎていると感じている。
  • MySQLのエラーに泣かされる。何度もブランチを切るハメに。

2021年11月

出来事

  • なんとなくVueを理解し始める。Rubyを使って開発をすれば良かったと後悔。
  • JSONの加工に苦しむ。
  • MVPをリリースする。

心境

  • プルリクエストは早い段階で作成して講師の方々に質問をすれば良かった。
  • なんとか診断機能が完成してMVPをリリースする事ができた。だが、診断結果表示がぐちゃぐちゃ。なんとかしなきゃ。
  • ベンチプレスがすごい上る。体が大きくなり始める。

2021年12月

出来事

  • もくもく会に参加し始める。
  • ブログ連続投稿が120日を超える。
  • アプリをリリースする。
  • 将来のお医者さん達と何故か砂浜練習をする
  • 現役エンジニアと運営に囲まれたパーティに参加する。
  • コスパの良いシェアオフィスを見つける。
  • 業務委託の話をいただく

心境

  • 流石に暖房がないと死ぬんじゃないかと焦り始める。
  • 就職できそうな未来が見えてきて少し嬉しい。
  • ベンチプレスが100kg上がったぞ。マッチョの仲間入りや。

総括

24年生きてきた中で一番苦労した。忘れられない一年になったかなと思います。

厄年にビビって過ごした一年だったので、来年は伸び伸びと生きたいと思います。

飛躍の年になりますように。

では、良いお年を。

【javascript】データ型・リテラルを✅

人狼オールとかいう学生みたいなことをしてしまって狼というより眠気に襲われて体調が頗る悪い23期中野昴です

.

宣伝

ZEROKENをリリースいたしました!

サイトURL

https://www.zeroken.site/

Image from Gyazo

簡単にお酒の強さを測る事ができて、アルハラを予防する事ができるアプリになります!

自分に合ったお酒の飲み方の順番を見つけて自分のペースで飲み会を乗り切ってください!

 

さて、今回はjavascriptの基本を理解するために、データ型とリテラルに関して学習していきたいと思います。

データ型とは

文字列、数値、真偽値といった値の型のこと**。**

javascriptは動的型付け言語であるため変数の型

静的型付け言語とは

事前にコンパイルを行うことで、プログラムの実行時には、型の整合性チェックの必要量が少なくなるというメリットを持つ。C、JAVACOBOLのような高級言語も静的型付け言語である。処理が早い。

動的型付け言語とは

プログラムを書くときに変数や関数に何が入ってくるかというのが特に決まっていない形を指している。

要は、プログラマーは、変数や関数になんとなく、こんな感じのデータが入るであろうということを予測するだけで、どんな値が入るかはコーティングには影響なく、実行時に多少影響するぐらいで、型の管理はインタプリタコンパイラが実行時にしてくれるという形態のことを言っている。

データ型は大きくプリミティブ型オブジェクトの2つに分類されている。

プリミティブ型

真偽値や数値などの基本的な値の型のことです。

下記のような特徴を持つ

  • 一度作成したらその値自体を変更できないというイミュータブル(immutable)の特性
  • JavaScriptでは、文字列も一度作成したら変更できないイミュータブルの特性を持ち、プリミティブ型の一種として扱われます。

オブジェクト

ざっくりプリミティブ型ではないものをオブジェクトという。

複数のプリミティブ型の値またはオブジェクトからなる集合を指す。

下記のような特徴を持つ。

  • 一度作成した後もその値自体を変更できるためミュータブル(mutable)の特性を持っている。
  • 値そのものではなく値への参照を経由して操作される。そのため、参照型のデータとも言われている。

さらにデータ型は、7つのプリミティブ型とオブジェクトに分類する事ができる。

  • プリミティブ型(基本型)
    • 真偽値(Boolean): trueまたはfalseのデータ型
    • 数値(Number): 42 や 3.14159 などの数値のデータ型
    • 巨大な整数(BigInt): ES2020から追加された9007199254740992nなどの任意精度の整数のデータ型
    • 文字列(String): "JavaScript" などの文字列のデータ型
    • undefined: 値が未定義であることを意味するデータ型
    • null: 値が存在しないことを意味するデータ型
    • シンボル(Symbol): ES2015から追加された一意で不変な値のデータ型
  • オブジェクト(複合型)
    • プリミティブ型以外のデータ
    • オブジェクト、配列、関数、正規表現、Dateなど

リテラルとは

リテラルとは、直接データ型に格納できる値のこと。

今まで聞いたことはあるがそれぞれの違いをあまり理解していなかった、配列,オブジェクト.文字列などは語尾にリテラルという言葉が省略されていた。

次の4つのプリミティブ型は、それぞれリテラル表現を持っている。

  • 真偽値
  • 数値
  • 文字列
  • null

また、オブジェクトの中でもよく利用されるものに関してはリテラル表現が用意されている。

上から順番に理解していきたい。

真偽値(Boolean)

真偽値にはtruefalseリテラルがある。

それぞれはtruefalseの値を返すリテラルで、見た目どおりの意味となっている。

true; #=> true
false; #=>false

数値(Number)

数値には42のような整数リテラル3.14159のような浮動小数点数リテラルがある。

整数リテラル

進数の種類が4つある。

浮動小数点数リテラル

浮動小数点数リテラルとして書く場合には、次の2種類の表記が利用できる。

  • 3.14159 のような .(ドット)を含んだ数値
  • 2e8 のような e または E を含んだ数値

文字列(String)

文字列リテラル共通のルールとして、同じ記号で囲んだ内容を文字列として扱います。

文字列リテラルとして次の3種類のリテラルがあり、その評価結果はすべて同じ"文字列"になる。

console.log("文字列"); // => "文字列"
console.log('文字列'); // => "文字列"
console.log(`文字列`); // => "文字列"

シングルクォート、ダブルクォート

''、""で囲まれた範囲を文字列とするリテラルのこと。

改行の代わりに改行記号のエスケープシーケンス(\\n)を使うことで複数行の文字列を書くことができる。

"明日の\\n晩御飯は\\nカレー";
#明日の
#晩御飯は
#カレー

バックスラッシュを入れてエスケープをする必要がある。

'8 o\\'clock'; // => "8 o'clock"

テンプレートリテラル

テンプレートリテラルは、```(バッククォート)で囲んだ範囲を文字列とするリテラルのことを指す。

複数行の文字列も```で囲めば、そのまま書くことができる。

`明日の
晩御飯は
カレー`; // => "複数行の\\n文字列を\\n入れたい"

${}で囲むことで、文字通りテンプレートとして使用することもできる

const str = "文字列";
console.log(`これは${str}です`); // => "これは文字列です"

nullリテラル

nullリテラルnull値を返すリテラルのことを指す。

Reference Errorを吐き出す。

const foo = null;
console.log(foo); // => null

オブジェクトリテラル

javascriptで基本となるリテラル

{}(中カッコ)を書くことで、新しいオブジェクトを作成できる。

const case = {}; # 中身が空のオブジェクトを作成

キー名には、文字列またはSymbolを指定し、値にはプリミティブ型の値からオブジェクトまで何でも入れることができる。

const case = {
    "sake": "highball"
};

この場合、 caseというオブジェクトはsakeというプロパティを持っていると言える。

casesakeプロパティを参照するには、.(ドット)でつないで参照する方法と、 [](ブラケット)で参照する方法がある。

const case = {
    "sake": "highball"
};

// ドット記法
console.log(case.sake); // => "highball"
// ブラケット記法
console.log(case["sake"]); // => "highball"

配列リテラル

オブジェクトリテラルと並んで、よく使われるリテラルとして配列リテラルがある。

[]で値をカンマ区切りで囲み、その値を持つArrayオブジェクトを作成するという特徴を持つ。

ちなみに 配列(Arrayオブジェクト)とは、複数の値に順序をつけて格納できるオブジェクトの一種のこと。

const alcohol_cases = []; // 空の配列を作成
const alcohols = [1, 2, 3]; // 値を持った配列を作成

配列は0からはじまるインデックス(添字)に、対応した値を保持している。

作成した配列の要素を取得するには、配列に対してarray[index]という構文で指定したインデックスの値を参照できる。

const sake = ["highball:0", "beer:1", "wine:2"];
// 0番目の要素を参照
console.log(sake[0]); // => "highball:0"
// 1番目の要素を参照
console.log(sake[1]); // => "beer:1"

正規表現リテラル

JavaScript正規表現リテラルで書くことができる。

/(スラッシュ)と/(スラッシュ)で正規表現のパターン文字列を囲み、正規表現リテラルを作成している。

次のコードでは、数字にマッチする特殊文字である\\dを使い、1文字以上の数字にマッチする正規表現リテラルで表現している。

const numberRegExp = /\\d+/; // 1文字以上の数字にマッチする正規表現
// `numberRegExp`の正規表現が文字列"123"にマッチするかをテストする
console.log(numberRegExp.test("123")); // => true

まとめ

  • javascriptは動的型付け言語であり、データ型を持っている。
  • データ型はオブジェクトとプリミティブ型に分かれている。
  • 今までなんとなく使ってきた、配列や文字列という言葉はリテラルのことだった。

データ型とリテラル

ゲストユーザーの診断結果を引き継ぐ方法を✅

早く就職して暖房を買いたいこと23期室温10度で凍え死にそうです。

宣伝

ZEROKENをリリースいたしました!

サイトURL

https://www.zeroken.site/

Image from Gyazo

簡単にお酒の強さを測る事ができて、アルハラを予防する事ができるアプリになります!

自分に合ったお酒の飲み方の順番を見つけて自分のペースで飲み会を乗り切ってください!

 

さて、今回は、Zerokenを2回以上使ってもらう方法に関してを考えていきたいと思います。

ユーザーがいきなり会員登録してくれるわけない。その前提から話を進めていく。

ひさじゅさんくらい強強な方が「個人情報を簡単に取れると思うな」と言うのだからそうなんだろう。

であれば、一旦サービスを使っていただいてまた使いたいとユーザーに思ってもらうことが重要になる。

では、どんな時にまた使いたいと思うのか。

先日、ひさじゅさんのtimesでこんな相談をさせていただいた。

「ZEROKENはサーバーサイドエンジニアになる上で必要な技術スタックを備えているのか」

こんなざっくりな質問に対して、下記のような返答をいただいた。

「フロントのUIはいい感じだったが、テーブル数やモデル数が足りない気がする。サーバーサイドで働きたいのであればテーブル数を増やす、もしくは既存のDBを最大限活用する必要がある。」

「また、一回診断して終了になってしまっている。ユーザー機能を発展させてユーザー体験を引き伸ばすべき。」

この、「ユーザー離脱(リテンションというらしい。)」と「モデルを活用できていない」解決することが12/31までの課題。

方向性

  1. 診断結果表示画面でログインの案内。
  2. ゲストユーザーで作成した酒ケジュールをログイン後に引き継ぐ
  3. 実際に飲んだお酒を投稿できる機能追加
  4. マイ酒ケジュールはTwitterに投稿する事ができる。

1. 診断結果表示画面でログインの案内。

診断結果の酒ケジュールを保存できるようにする。

下記のようにボタンを設置し、データを保存するタイミングでログインモーダルが出るようにする

Image from Gyazo

2. ゲストユーザーで作成した酒ケジュールをログイン後に引き継ぐ

ゲストユーザーとして作成した酒ケジュールを、ログインをした後でも使えるようにする。

そのためには、下記のようにPromise構文を使って処理を進める。

registerFunction() {
      const allAnalyzes = this.analyzes
        const targetAnalyzes = allAnalyzes[allAnalyzes.length -1]
      this.registerUser(this.user).then((user) => {

      //  酒ケジュールデータのshucheduleとalcohol_strongnessだけ引き継ぎたい
     
        if (user) {
const userId = user.data.id
const targetShuchedule = targetAnalyzes.shuchedule
const targetAlcoholStrongness = targetAnalyzes.alcohol_strongness

const dataPassedDownToLoginUserFromGuest = {
 id: userId,
shuchedule: targetShuchedule,
alcohol_strongness: targetAlcoholStrongness,
}

this.createSucceedShuchedule(dataPassedDownToLoginUserFromGuest)
          this.$router.push({ name: 'UserProfile' });
        } else {
          this.fetchSnackbarData({
            msg: '新規登録に失敗しました',
            color: 'error',
            isShow: true,
          });
        }
      });},

下記記述で、引き継ぎ情報を新しく作成する事ができるはず。まだ試してはいない。

userIdとデータを紐づけることで、ゲストとして作ったデータを、あたかもログイン後のユーザーとして作ったデータかのようにすり替えている。

const userId = user.data.id
const targetShuchedule = targetAnalyzes.shuchedule
const targetAlcoholStrongness = targetAnalyzes.alcohol_strongness

const dataPassedDownToLoginUserFromGuest = {
 id: userId,
shuchedule: targetShuchedule,
alcohol_strongness: targetAlcoholStrongness,
}

this.createSucceedShuchedule(dataPassedDownToLoginUserFromGuest)
  1. 実際に飲んだお酒を投稿できる機能追加
  2. マイ酒ケジュールはTwitterに投稿する事ができる。

下記のように、飲んだお酒を保存するページを作りたい。accepts_nested_attributes_forを使ったら実装できるかもしれない。

Image from Gyazo

一言

リリースしたのはいいけど、追加機能が結構あって大変だ。

【RSpec】RSpecのdebugを✅

面接対策動画に思っていた数倍苦戦している23期ユーザーのリテンション対策中です。

宣伝

ZEROKENをリリースいたしました!

サイトURL

https://www.zeroken.site/

Image from Gyazo

簡単にお酒の強さを測る事ができて、アルハラを予防する事ができるアプリになります!

自分に合ったお酒の飲み方の順番を見つけて自分のペースで飲み会を乗り切ってください!

Javascriptだったらconsole.logやdebugger、rubyであればbinding.pryを使って変数に何が入っているのかを確認していました。

RSpecruby同様binding.pryでエラー箇所を切り出せばいい。

さらに、エラー文の詳細を知る方法も突き止めた。ここに備忘録として残しておきたい。

今回はリクエストスペックを書いていた際に出たエラー対処についての備忘録を書かせていただきます。

RSpecでエラーが出た際の対処法

APIのテストを書く際に、下記のようなエラーが出た場合

Image from Gyazo

エラーが発生した箇所にbinding.pryを挟む

request.statusを確認する

下記コードをコンソールに打ち込む

$ pry>File.write("tmp/debug.html", response.body)

pryからexitする

pry > exit

consoleで下記Linuxコマンドを打ち込むと、

tmp配下のファイルが出力される

$ ls -la tmp/
total 248
drwxrwxrwx  11 subaru  staff     352 12 28 10:03 .
drwxrwxrwx  45 subaru  staff    1440 12 25 22:34 ..
-rwxr-xr-x   1 subaru  staff       0 11 15 08:31 .keep
drwxrwxrwx   5 subaru  staff     160 12 24 06:57 cache
-rw-r--r--   1 subaru  staff  119684 12 28 10:03 debug.html
-rwxrwxrwx   1 subaru  staff     128 10  5 18:38 development_secret.txt
drwxrwxrwx  13 subaru  staff     416 12 28 09:00 miniprofiler
drwxrwxrwx   4 subaru  staff     128 12 26 06:13 pids
-rwxrwxrwx   1 subaru  staff       0 10  5 20:27 restart.txt
drwxrwxrwx  16 subaru  staff     512 12 28 09:32 screenshots
drwxrwxrwx   2 subaru  staff      64 10  5 20:27 sockets

pryを挟んだ時にエラー文を記入しておいたdebug.htmlを書きコマンドを打ってブラウザで開く

$ open tmp/debug.html

すると下記のようにエラーの箇所を見つける事ができる。

Image from Gyazo

rspecのrequest specでうまくいかない時の原因調査のちょっとしたハック - Qiita

YouTube Data APIを✅

30日のブシトラさん宅パーティでは「モテスパイラルの体系的な知識」が学べそうで楽しみな23期アルコリズム改良中です。

 

https://www.zeroken.site/

宣伝

ZEROKENをリリースいたしました!

サイトURL

https://www.zeroken.site/

Image from Gyazo

簡単にお酒の強さを測る事ができて、アルハラを予防する事ができるアプリになります!

自分に合ったお酒の飲み方の順番を見つけて自分のペースで飲み会を乗り切ってください!

さて、

年末に下記質問内容を解決できるようなアプリを作りたいと考えています。

質問: ①下記ってそもそも技術的に可能? ◆やりたいこと ⇨python(javaでも)とYouTube Data APIを使って、YouTubeでチャンネル内の動画再生回数が合計100未満のチャンネルをリストアップする

②この流れでやりたいことできそう? 1.YouTubeに存在するチャンネルのIDを条件付きで取得

⇨ 視聴回数100回未満 2.取得したチャンネルIDをリスト化 3.それぞれのチャンネルIDの ・チャンネル名 ・登録者数 ・チャンネルの視聴回数

そのために、ざっくりとYoutube Data APIからデータを取ってくる方法を学習していきたいと思います。友人にかっこいい姿を見せたいという気持ちでがんばります笑

APIとは

application programming interfaceの略。アプリとアプリを繋げる接合部分。

既存のサービスが提供するAPIRailsやLarabelなどのバックエンドフレームワークを使って叩く事が多い。

このAPIを叩くという言葉は厳密にはリクエスレスポンスに分類される。

アプリケーション(ユーザー)が外部API(プロバイダ)に対してデータのリクエスを実行。外部API(プロバイダ)はレスポンスとしてJSONを吐き出す。

Json.perse(response.data)や().to_jsonのようなメソッドを使ってRailsJsonを解析し、フロントで使えるようにしている。

これは20期の青木さんがめちゃくちゃに分かりやすく説明してくれているqiita記事を参考にして理解を深めた。

やっぱり図解されていると分かりやすい。

Youtube Data APIとは

Youtubeで使われているデータを外部アプリで使ってもらうために作られたInterface。

Railsを使ってYoutubeデータにアクセスする事ができるらしい。

簡単な流れは以下の通り

Rails(バックエンド)⇨Youtube Data API ⇨Rails(コントローラー)⇨Viewのscript(フロントエンド)⇨Viewのhtml(フロントエンド)

  1. Rails(バックエンド)⇨Youtube Data API

Railsがリクエストを出している(APIを叩く)

  1. Youtube Data API ⇨Rails(コントローラー)

Youtube Data APIがレスポンス(JSON形式)を返している

  1. Rails(コントローラー)⇨View(フロントエンド)

解析したJSONをrender :jsonなどでフロントエンドフレームワーク(VueやReact)に渡している

  1. Viewのhtml(フロントエンド)

jsで加工したJSONをtemplateタグ内でそれっぽく加工している。

0. APIキーの取得

Youtube Data APIで遊ぶ前に、まずは**認証情報の作成(APIキーの作成)**が必要。下記記事を参考にしてAPIキーを取得していきたい。

【Youtube】APIキーの取得手順(2021/04/08時点のキャプチャ) - Qiita

1. Railsを使ってAPIを叩く

先程APIを叩くとは、RailsAPIプロバイダに対してHTTPリクエストを出すことと述べさせていただいた。

Youtube Data APIはエンドポイントを多く提供している。

  • Cannnels:

GET [<https://www.googleapis.com/youtube/v3/channels>](<https://www.googleapis.com/youtube/v3/channels>)

ユーチューバーのチャンネルデータを取得できる

  • Videos

GET <https://www.googleapis.com/youtube/v3/videos>

YouTubeに上がっている動画を取得する事ができる

  • Activities

POST <https://www.googleapis.com/youtube/v3/activities>

Youtubeのアクティビティデータを取得する事ができる。

Railsの設計

現段階だと全然わからないが、完成形は以下のような形になる事が想定される。

#!/usr/bin/ruby

require 'rubygems'
gem 'google-api-client', '>0.7'
require 'google/api_client'
require 'google/api_client/client_secrets'
require 'google/api_client/auth/file_storage'
require 'google/api_client/auth/installed_app'
require 'trollop'

# This OAuth 2.0 access scope allows for full read/write access to the
# authenticated user's account.
YOUTUBE_SCOPE = '<https://www.googleapis.com/auth/youtube>'
YOUTUBE_API_SERVICE_NAME = 'youtube'
YOUTUBE_API_VERSION = 'v3'

def get_authenticated_service
  client = Google::APIClient.new(
    :application_name => $PROGRAM_NAME,
    :application_version => '1.0.0'
  )
  youtube = client.discovered_api(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION)

  file_storage = Google::APIClient::FileStorage.new("#{$PROGRAM_NAME}-oauth2.json")
  if file_storage.authorization.nil?
    client_secrets = Google::APIClient::ClientSecrets.load
    flow = Google::APIClient::InstalledAppFlow.new(
      :client_id => client_secrets.client_id,
      :client_secret => client_secrets.client_secret,
      :scope => [YOUTUBE_SCOPE]
    )
    client.authorization = flow.authorize(file_storage)
  else
    client.authorization = file_storage.authorization
  end

  return client, youtube
end

def main
  opts = Trollop::options do
    opt :message, 'Required text of message to post.', :type => String
    opt :video_id, 'Optional ID of video to post.', :type => String
    opt :playlist_id, 'Optional ID of playlist to post.', :type => String
  end

  # You can post a message with or without an accompanying video or playlist.
  # However, you can't post a video and a playlist at the same time.
  if opts[:video_id] and opts[:playlist_id]
    Trollop::die 'You cannot post a video and a playlist at the same time'
  end
  Trollop::die :message, 'is required' unless opts[:message]

  client, youtube = get_authenticated_service

  begin
    body = {
      :snippet => {
        :description => opts[:message]
      }
    }

    if opts[:video_id]
      body[:contentDetails] = {
        :bulletin => {
          :resourceId => {
            :kind => 'youtube#video',
            :videoId => opts[:video_id]
          }
        }
      }
    end

    if opts[:playlist_id]
      body[:contentDetails] = {
        :bulletin => {
          :resourceId => {
            :kind => 'youtube#playlist',
            :playlistId => opts[:playlist_id]
          }
        }
      }
    end

    # Call the youtube.activities.insert method to post the channel bulletin.
    client.execute!(
      :api_method => youtube.activities.insert,
      :parameters => {
        :part => body.keys.join(',')
      },
      :body_object => body
    )

    puts "The bulletin was posted to your channel."
  rescue Google::APIClient::TransmissionError => e
    puts e.result.body
  end
end

main

Implementation: Videos | YouTube Data API | Google Developers

【Ruby on Rails】最もわかりやすいYouTube API 使い方 - Qiita

2. JSONの加工

レスポンスを加工していく必要がある。

1でVideosエンドポイントを利用し、コントローラーの作成に成功したと仮定する。

その状況下でAPIを叩くことに成功した場合に返ってくるJSONの例は下記の通り。

API レスポンス:

{ 
 "kind": "youtube#videoListResponse",
 "etag": "\\"UCBpFjp2h75_b92t44sqraUcyu0/sDAlsG9NGKfr6v5AlPZKSEZdtqA\\"",
 "videos": [
  {
   "id": "7lCDEYXw3mM",
   "kind": "youtube#video",
   "etag": "\\"UCBpFjp2h75_b92t44sqraUcyu0/iYynQR8AtacsFUwWmrVaw4Smb_Q\\"",
   "snippet": { 
    "publishedAt": "2012-06-20T22:45:24.000Z",
    "channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw",
    "title": "Google I/O 101: Q&A On Using Google APIs",
    "description": "Antonio Fuentes speaks to us and takes questions on working with Google APIs and OAuth 2.0.",
    "thumbnails": {
     "default": {
      "url": "<https://i.ytimg.com/vi/7lCDEYXw3mM/default.jpg>"
     },
     "medium": {
      "url": "<https://i.ytimg.com/vi/7lCDEYXw3mM/mqdefault.jpg>"
     },
     "high": {
      "url": "<https://i.ytimg.com/vi/7lCDEYXw3mM/hqdefault.jpg>"
     }
    },
    "categoryId": "28"
   },
   "contentDetails": {
    "duration": "PT15M51S",
    "aspectRatio": "RATIO_16_9"
   },
   "statistics": {
    "viewCount": "3057",
    "likeCount": "25",
    "dislikeCount": "0",
    "favoriteCount": "17",
    "commentCount": "12"
   },
   "status": {
    "uploadStatus": "STATUS_PROCESSED",
    "privacyStatus": "PRIVACY_PUBLIC"
   }
  }
 ]
}

波括弧にたくさんネストされてわけわからなくなってますね。

【Python】YouTube APIを使った「再生順、更新順(再生数下限あり)」動画リスト取得(コピペでOK) - Qiita

3. 検索結果を絞る

先程2で取得したレスポンスデータを加工するには、下記のように記述する必要がある。

const responsData = { #レスポンスデータをresponsDataとして定義。
 "kind": "youtube#videoListResponse",
 "etag": "\\"UCBpFjp2h75_b92t44sqraUcyu0/sDAlsG9NGKfr6v5AlPZKSEZdtqA\\"",
 "videos": [
  {
   "id": "7lCDEYXw3mM",
   "kind": "youtube#video",
   "etag": "\\"UCBpFjp2h75_b92t44sqraUcyu0/iYynQR8AtacsFUwWmrVaw4Smb_Q\\"",
   "snippet": { 
    "publishedAt": "2012-06-20T22:45:24.000Z",
    "channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw",
    "title": "Google I/O 101: Q&A On Using Google APIs",
    "description": "Antonio Fuentes speaks to us and takes questions on working with Google APIs and OAuth 2.0.",
    "thumbnails": {
     "default": {
      "url": "<https://i.ytimg.com/vi/7lCDEYXw3mM/default.jpg>"
     },
     "medium": {
      "url": "<https://i.ytimg.com/vi/7lCDEYXw3mM/mqdefault.jpg>"
     },
     "high": {
      "url": "<https://i.ytimg.com/vi/7lCDEYXw3mM/hqdefault.jpg>"
     }
    },
    "categoryId": "28"
   },
   "contentDetails": {
    "duration": "PT15M51S",
    "aspectRatio": "RATIO_16_9"
   },
   "statistics": {
    "viewCount": "3057",
    "likeCount": "25",
    "dislikeCount": "0",
    "favoriteCount": "17",
    "commentCount": "12"
   },
   "status": {
    "uploadStatus": "STATUS_PROCESSED",
    "privacyStatus": "PRIVACY_PUBLIC"
   }
  }
 ]
}
#視聴数をyoutubeViewDataとして定義
const youtubeViewData = responsData["videos"][0]["statistics"]["viewCount"]

console.log( responsData["kind"])
console.log(youtubeViewData )
#expected output
> "youtube#videoListResponse"
> "3057"

どうやらこの動画は3057回再生されているらしいですね。。

Youtube: APIを使って詳細な検索結果を取得する

他にも絞り込み条件はたくさんあるみたいだから学習して年末には冒頭に記したアプリを作成したいと思う!

  • date – リソースを作成日の新しい順に並べます。
  • rating – リソースを評価の高い順に並べます。
  • relevance – リソースを検索クエリの関連性が高い順に並べます。このパラメータのデフォルト値です。
  • title – リソースをタイトルのアルファベット順に並べます。
  • videoCount – アップロード動画の番号順(降順)にチャンネルを並べます。
  • viewCount – リソースを再生回数の多い順に並べます。

この、viewCountを絞り込み条件にする。

チャンネルに関するAPI

Channels: list | YouTube Data API | Google Developers

Channels | YouTube Data API | Google Developers

statistics.viewCount
unsigned long

statistics.subscriberCount
unsigned long
チャンネルの登録者数。
statistics.hiddenSubscriberCount
boolean
チャンネル登録者数を公開表示するかどうかを指定します。
statistics.videoCount
unsigned long
チャンネルにアップロードされた動画の数。

Search: list | YouTube Data API | Google Developers

api-samples/ruby at master · youtube/api-samples

一言

APIを叩くの楽しそう!!

【Web技術】SessionとCookieを✅

やっとこさ正式リリースをする事ができたけど開発に終わりが見えていない23期酒ケジュール作成中です。

アプリURL

https://www.zeroken.site

携帯だと背景画像がぐわンぐわん動いてしまうエラーを早急に解決させたいです。

今回はsessionとcookieについて学習していきたいと思います。

Sessionとは

コンピュータシステムやネットワーク通信において、接続/ログインしてから、切断/ログオフするまでの、一連の操作や通信のこと

(https://e-words.jp/w/セッション.html)

何故必要なのか

HTTPはステートレスなプロトコルなため、「状態」を持てないから。

そのため、状態をもつことのできるモノ、sessionを代わりに作成する必要がある。

こうすることで、リンクなどを張ってページを移動しても内容を保持することができる。

セッションが不要になった場合は、reset_sessionを使って全体のsessionを削除することが出来る。

特徴

  • クライアント側のブラウザに保持され、サーバー側にリクエストする際に、HTTPリクエストのボディにsession情報が記述されたcookieを格納している。
  • Webブラウザを閉じるまで保存される
  • cookie内のセッションidによって識別できる。

中身にあるメソッドは、下記の通りになっている。

  • ActionDispatch::Session::CookieStore: すべてのセッションをクライアント側のブラウザのcookieに保存する
  • ActionDispatch::Session::CacheStore: データをRailsのキャッシュに保存する
  • ActionDispatch::Session::ActiveRecordStore: Active Recordを用いてデータベースに保存する (activerecord-session_store gemが必要)

あらゆるセッションは、セッション固有のIDをcookieに保存される(注意: セッションIDは必ずcookieで渡さなくてはならない)。

Cookieの役割

  • WebサーバーからWebブラウザへHTTPレスポンスのヘッダを利用して小さな情報を送る。この情報は「名前=値」の組み合わせで表される。
  • Webアプリケーション側では、リクエスト•ヘッダに入っているCookieを調べることで、アクセスしてきた相手がどのような相手なのかを知ることができる。

セッションの中身は以下の通り。現在のユーザーを認証している裏側。

class ApplicationController< ActionController::Base

  private
# キー付きのセッションに保存されたidでユーザーを検索する
# :current_user_id はRailsアプリケーションでユーザーログインを扱う際の定番の方法。
# ログインするとセッション値が設定され、
# ログアウトするとセッション値が削除される。
  def current_user
    @_current_user||= session[:current_user_id]&&User.find_by(id: session[:current_user_id])
  end
end

セッションに何かを保存したければ、ハッシュのようにキーに対して保存したい情報を割り当てる。

**class** **LoginsController** **<** ApplicationController
  *# "Create" a login, aka "log the user in"*
 **def** **create
  if** user **=** User.**authenticate**(params[:username], params[:password])
      *# セッションのuser idを保存し、
       # 今後のリクエストで使えるようにする*
  session[:current_user_id] **=** user.**id**
  redirect_to root_url
    **end
 end
end**

SessionとCookieのやり取り

  • セッションに保存された内容は、Webサーバーにファイルとして保存されている。
  • ユーザーのWebブラウザにはセッションID(無作為な英数字)がCookieに記録される。
  • セッションIDとWebサーバー上のファイルが照合されてセッション内容を取り出す。

Session関連のセキュリティ

Sessionハイジャック

サイトからログアウト(セッション情報を削除)し忘れると、悪意のある第三者がそのサイトにアクセスしてセッション情報を乗っ取ってしまう可能性がある。そのことにより、下記のような攻撃を受けてしまう恐れがある。

攻撃対象のWebサイトの脆弱性を突き、攻撃者がそこに悪質なサイトへ誘導するスクリプトを仕掛けることで、サイトに訪れるユーザーの個人情報などを詐取する攻撃のことを指します

(https://www.amiya.co.jp/column/cross_site_scripting_20210118.html)

クロスサイトスクリプティング (XSS) 攻撃は、多くの場合、ユーザーのcookieを手に入れるのが目的。サイト制作者としては、目立つ場所にログアウトボタンを作成して、ユーザーにセッション情報を削除してもらう工夫が必要。

Rails セキュリティガイド - Railsガイド

Cookieとセッションをちゃんと理解する - Qiita

Action Controller の概要 - Railsガイド

【Web技術】polyfillを✅

クリスマスプレゼントを何にするか迷った挙句「一緒に選んで買う」という選択肢を選んでスニーカーをプレゼントさせていただいた23期酒ケジュール作成中こと「優柔不断」です。

昨日行った技術面談のおかげで10日間悩んでいたエラーが丸っと解決いたしました。

今回は、そこで学んだpolyfillという技術をチェックしていきたいと思います。

Polyfillとは

ブラウザ、あるいはブラウザのバージョンの違いによる動きの差分を埋めてくれるサービス。大抵はjavascriptがpolyfillをになっている。

「IE11だと動くがChromeでは動かない」「ブラウザを新しいバージョンにアップデートしたら動きがおかしくなった」などの不具合に対処してくれる。

polyfill.ioには、「webを自動でアップデートしてくれる」というキャッチコピーが書いてある通り、ブラウザに応じてバージョンをアップデートしてくれる優れもの。

具体的にどんな時に役に立つのか

ブラウザかんで差が出てしまうメソッドをアプリ内で使っている時に役立つ。

例えばZEROKENでも使用しているObject.values()。引数に入れたオブジェクトを配列に整形してくれる便利メソッドだが、E11では未実装のため動作しない。こういったブラウザごとの実装・未実装を埋めてくれるのがPolyfill。

ZEROKENでは下記のように使っている。

Image from Gyazo

beforeでは{}というふうにオブジェクトだった変数の中身が、[]というように配列に置き換わっている事がわかりますね。

Image from Gyazo

どう使うのか

Polyfill.ioというライブラリをCDN形式で埋め込むことで、アプリの作動を統一させることができる。

こちらのサイトが用意しているpolyfillのCDNをindex.html(rubyの場合はapplication.html.erb)に埋め込むだけでいい。

+  <script src="<https://polyfill.io/v3/polyfill.min.js?features=es6>"></script>

?feature=に続けて、統一後の文法名あるいはブラウザ名を入れるだけでpolyfillを使えるようになる。

Polyfill.io

ECMAScript 6 compatibility table

Polyfill (ポリフィル) - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN

実際に使ってみる

なぜかデバイス毎にjavascriptの動作が適応さないというエラーに陥った。こちらのissueに問題は全てまとめてある。

https://github.com/subaru-hello/Zeroken/issues/107

問題の所在を切り分けたところ、どうやらsafariだとjavascriptの挙動がおかしいことがわかった。

そこでpolyfillの登場。

smooth-scroll用のpolyfillライブラリが存在するらしく、実際に使ってみたところ見事に解決する事ができた。

参考までにsmooth-scroll用のpolyfillであるsmoothscroll-polyfillを適用させたときの手順を下記に記しておく。

  1. yarnあるいはnpmパッケージを用いてsmoothscroll-polyfillをダウンロード
yarn add smoothscroll-polyfill
or 
npm install smoothscroll-polyfill
  1. main.jsでimportする。私の場合はhello_vue.jsでimportした。

javascript/packs/hello_vue.js

import smoothscroll from 'smoothscroll-polyfill';
smoothscroll.polyfill();

この2つの手順のみでブラウザ間でsmooth-scrollの動きが違うという問題を解決する事ができる。

before

Image from Gyazo

after

Image from Gyazo

まとめ

  • polyfillとはブラウザ毎の差分を埋めてくれるライブラリ。

一言

クリスマスイブに摂取した総カロリーが5000kcalを超えた。これはやばいと思い、今日総重量5000kg以上をエニタイムで挙げてきた。

内訳

デットリフト 120kg * 5 * 3 = 1800kg

スクワットジャンプ 70kg * 10 * 3 = 2100kg

レッグカール 50kg * 10 * 3 = 1500kg

ベントオーバーロウ 45kg * 10 * 3 = 1350kg

総重量 6750kg

つまりはカロリーゼロ。

https://developer.cybozu.io/hc/ja/articles/360022880491-webpack入門-Babel-Polyfillを使って快適ES6ライフ-