ひよっこエンジニアの雑多な日記

とあるプログラミングスクールで働くひよっこエンジニアが覚えたことや悲しみを記すブログ

Railsでソーシャルログインを作る(Yahoo編)

あけましておめでとうございます。
今年も気が向いたらブログ更新していくスタイルでぼちぼちやっていきたいと思います!

今日は突然Yahooでソーシャルログインを作る機運が高まり、試し実装したのでメモ書きしておきます。

mikanmarusan.hatenablog.com

少し古めではありますが、このエントリーにある内容をそのままなぞる形でいけました。

準備(YahooのAPIキーを取得)

YahooのID連携を利用する場合は以下のURLにアクセスします。

developer.yahoo.co.jp

右横にあるアプリケーション開発のボタンをクリックして、遷移したページでアプリケーションを登録のリンクにアクセスします。

f:id:kimuraysp:20190108083400p:plain

次にアプリケーションの初期設定を行います。
今回は開発用としてサイトURLにhttp://localhost:3000を設定します。

f:id:kimuraysp:20190108083745p:plain

あとはガイドラインへの同意を同意するを選択してください。
ここまで設定したら画面下部の確認ボタンをクリックして先に進んでください。

確認画面に遷移するので内容に誤りがなければ登録ボタンをクリックして登録完了です。
登録完了時にClient IDとシークレットキーが表示されるのでメモしておきます。

コールバックの設定

登録時の画面には項目がないので見落としますが、コールバックするURLの設定をしておく必要があります。

アプリケーションの管理:Yahoo!デベロッパーネットワークにアクセスして自分が作成したアプリケーションの編集ボタンをクリックします。

f:id:kimuraysp:20190108084608p:plain

編集画面に遷移します。
コールバックURLという項目があるのでコールバックしたいURLを設定します。
今回はhttp://localhost:3000/auth/yahoojp/callbackとしておきます。

f:id:kimuraysp:20190108084845p:plain

ここまでできたら更新ボタンを押して準備が完了となります。

アプリケーション作成

Yahoo ID連携の準備が整ったので、コードを書いていきます。

バージョン

Ruby 2.5.3
Rails 5.2.2

サンプル

今回作成したサンプルは以下になります。

GitHub - kimuray/social_test: OAuth実装して遊ぶ

開発手順

ひとまずrails newし終わっている前提でやって行きます。

ライブラリの追加

yahooとOAuthするために必要なライブラリをGemfileに追記します。

gem 'omniauth'
gem 'omniauth-yahoojp'

追記したらbundle installします。

omniauth設定

config/initializers配下にomniauth.rbというファイルを作成します。
作成したファイルに以下のコードを書きます。

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :yahoojp, ENV['YAHOOJP_KEY'], ENV['YAHOOJP_SECRET'],
  {
    scope: 'openid profile email address'
  }
end

APIキーとシークレットキーはそれぞれYAHOOJP_KEYYAHOOJP_SECRETという環境変数に設定します。
YahooでID連携のアプリケーションを作成した際に表示されたClient IDとシークレットキーを設定しておきます。

また、scopeの設定はしておかないとOAuth時にエラーになるので設定しておきます。

Yahooと連携する処理を作成

ルーティング
root 'sessions#top'
get '/auth/:provider/callback' => 'sessions#callback'

参考にしているエントリに習って、雑にルーティングを設定します。
'/auth/:provider/callback'のルーティングはYahooで設定したコールバックURLとして扱います。

コントローラ
rails g controller sessions top callback

として雑にコントローラとviewを作成してしまいます。

app/views/sessions/top.html.erb

<%= link_to 'Yahoo Japanでログイン', '/auth/yahoojp' %>

を追記します。

これでYahooと連携できるアプリケーションができました。

あとはsessions_controller.rbのcallbackアクションにbinding.pryを仕掛けるなどしてrequestを見て見たりすると連携できていることが確認できます。

本当にこれぐらいしかコードは書いていませんが、中身を見たいという方はサンプルを見てください。

最後に

めちゃんこ雑に紹介しましたが、ライブラリの力を使えば30分ちょいぐらいでYahooと連携できてしまうってすごいですねえ。

2018年振り返り

2018年も残すところ2日ということで今年の振り返りをざっくりしておこうかなと。
今年の年始に立てた目標を元に振り返っていきます。

年始に立てた目標

kimuraysp.hatenablog.com

  • 個人的にサービスを10個作ってリリースする
  • 使える技術の幅を広げる
  • 現在の会社で収益の柱になるサービスを立ち上げる
  • 自分のブランディングを考える・土台を築き始める
  • 人との繋がりを広げる
  • 副収入を今の3~5倍にあげる

うーん、我ながら香ばしいくらいに意識高い目標です。

とりあえず一つずつ振り返ってみます。

振り返り

ではでは早速振り返っていきましょう。

個人的にサービスを10個作ってリリース

これ絶対『とりあえずキリいいし10個目指そ』のノリで立てたんだろうなあ。当時の自分。

今年リリースしたサービスは結局1つでした…. とはいえ1つリリースできたというところは褒めていきたい。えらい自分。

リリースしたサービスは『まんがのおばけ』という漫画の感想を質問箱的に投稿できるサービスでした!

mangaobake.net

これは友人の企画で作ったサービスなんですが、気の置けない人とのサービス開発の楽しさを知ることができました。
気兼ねなく議論して、より良いサービスを提供するにはを考えるのは控えめに言ってすごく楽しかった。

次はサービスをどのように運用して行くかも考えて、また新しくサービス開発したいです。

達成度的には1/10なので10%って感じですね。

使える技術の幅を広げる

これは定量で測れる指標を用意してなかったので達成度は測れなさそうです…

当時の記事を見てみるとデータ解析系の知識を云々と言っていますが…
データ解析系の勉強は1mmもしてないですね…

今年は幅の広がった技術領域があまりないのでエンジニアとしてやばい感

DockerやReactなど軽く触れるみたいなことはしたものの、手に馴染むまではいっていないというお粗末な状況…

12月に転職してWebエンジニアとしてやって行くことになったので、来年は技術の分野もしっかり磨いて行きたいです。

現在の会社で収益の柱になるサービスを立ち上げる

これは完全に未達ですね…
2018年開始当初は立ち上げに向けて動いていたのですが、なかなか前に進まない感じと結局何がしたかったのかがわからなくなってしまい頓挫しました。

サービス立ち上げにはそれなりのエネルギーを使わないといけないのだなあという学びでした。
達成度0%です…

自分のブランディングを考える・土台を築き始める

当初の記事を見てみると自己分析をして自分が何をやりたい人間なのかを考える的なことが書いてありました。
そういう意味で行くと今年は自分が向かいたい方面が少し見えた年だったかもと思います。

キャリア × IT

この方向性に興味があることが個人的に判明しました。
これは迷走しながら転職活動やMBTI認定トレーナー取得などに取り組んだ結果かなあと思います。

自分を嫌でも見つめ直す機会ができたことで、自分が密かに感じていた課題感に気づくことができたのかもという振り返りです。

MBTIは今年どハマりして無事認定トレーナーにもなっているので、来年どうにか活用して行きたい所存。
来年は国家キャリアコンサルタントの試験も受けるので、しっかり取得したいところです。

達成度としては定量目標ではなかったので、肌感で考えると方向性は見えたので50%くらいでしょうか。

人との繋がりを広げる

全然広がっていないです(白目)
1, 2月に勉強会などに週3, 4ペースで入れて参加していたのですが、目的なく人が多い場所に行くと何もできずにただただ精神が消耗して疲れだけがたまりました…

結果3月は仕事以外は外に出ない引きこもりになりました…(白目)

成果としては自分は見知らぬ人が不特定多数いる空間に行くと非常に精神が消耗することがわかったことでしょうか。
立食系の懇親会とか地獄でしかないということがわかりました。

そして人脈は目的なく広げるべきものでもないのかなと思いました。

昨日、陸王の再放送を見ていて思ったことがあります。

それは人脈は目的を持って行動している時に作られて行くものだということです。

陸王では社長である宮沢が陸王を作ろうと奔走することでシルクレイ著作者の飯山やシューフィッターの村野といった色々な人と繋がっていました。
これは陸王を作ろうという目的と意思があったからこそ出来上がった人脈だと思い、大事なのは場数を踏むことではなく目的を持つことなのだと勝手に解釈しました。

達成度的には圧倒的0%です。
2019年は人と繋がる意味や目的を見出して、時がきたらきちんと人脈を広げていきたいです(戒め)

副収入を今の3~5倍にあげる

この目標、金額だけでいえば達成はできているんですよね(困惑)
というのも仮想通貨でそれなりにプラスになったのが大きな要因です。

某取引所のXEM流出事件にしっかり巻き込まれたのですが、XEMを買った時期が春先だったので某取引所の補償額でかなりプラスになったんですよね。

ただ年始の目標を見ていると文脈的に仮想通貨というより副業でという側面が強そうなのでなんとも言えない…
仮想通貨は一過性の副収入で、副業は現在何もやっていないので来年どのように収入の戦略を立てて行くかが課題ですね。

達成度的には金額は満たしているので70%にしておきます。
ただ来年も副収入はなにかしら得たいので、来年は収入の口を増やすこともKPIとしてやっていきたいです。

総括

とりあえず全体の達成度を出すと

(10% + 0 + 50% + 0 + 70%) / 5 = 26%
※ 技術の幅の目標は定量化不可だったので除外

正直定量目標が少なかったので参考値でしかないですが26%の達成です。
感覚値だと3%くらいだと思っていたので、意外と高いかもしれない。

思ったより人生は進捗していたとポジティブに考えよう(現実から目をそらしながら)

文中に何回か出しましたが今年は転職やプライベート的に変化のあるイベントをこなしているので、目標以外のところで進捗が出ている面はありそうです。

とはいえ2018年の目標は雑だったなと思うので2019年の目標はもう少しリアリティ出しつつ、ストレッチできるようなものを考えていきたいです。

なんやかんやで今年も色々ありました。
2018年も残り2日ですが少しでも進捗出していきたいです。

AWS LambdaでSinatraを動かしてみる

12月から晴れてWebエンジニアになりました。

ということでアウトプットを増やしていかねばと久々の執筆です。

概要

今回はRubyのランタイムが追加されたAWS LambdaでSinatraを動かしてみたいと思います。

GitHub - aws-samples/serverless-sinatra-sample: Demo code for running Ruby Sinatra on AWS Lambdaを使ってREADMEに書かれているコマンドを実行していけばサクッとできます。
ただ個人的に何が起きているのかさっぱりで釈然としなかったので自分なりに理解しながら新しく作ってみました。

↓ 今回作ったサンプルコード
https://github.com/kimuray/sinatra_lambda_sample

登場人物

今回登場する役者は3つです。

AWS Lambda

言わずと知れたサーバーレスのコード実行サービスです。
サーバーを管理する必要がなくなるのでサーバーの準備や運用を考えなくてよくなります。

aws.amazon.com

Sinatra

Ruby製のシンプルにWebアプリケーションが作れるフレームワークです。
Railsほど機能はいらんけど、ルーティングあたりの機能は欲しいなどの要望に応えてくれます。

Sinatra

AWS CloudFormation

AWSでのインフラ構築を自動化してくれるサービスです。
一度設定してしまえばそれに従って同一環境を何度でも簡単に作れるようになります。
今回はCloudFormationが主役になります。

AWS CloudFormation (設定管理とオーケストレーション) | AWS

Sinatraアプリを作る

今回はサンプル的に雑にテキストボックスを用意して、POSTリクエストを投げたら、投稿内容が画面に追加されていくようなアプリを作りました。

f:id:kimuraysp:20181211084603g:plain

AWSのサンプルコードでもよかったのですがDynamoDBが使われていたりして、 俺は単純にviewをレンダリングさせて、POSTしてみたいだけなんじゃ!という気持ちになったので新しく作りました。

AWS Lambdaのコードを書く

コードは以下になります。

https://github.com/kimuray/sinatra_lambda_sample/blob/master/lambda.rb

これは完全にAWSサンプルをそのまま持ってきました。
AWS Lambdaを使う際は

def handler(event:, context:)
  # なんらかの処理
end

という形で処理を書いていきます。
AWS LambdaでHello worldしてみるとわかると思います。

コードの内容的には受け取ったリクエストを整形してSinatraに食わせてレスポンスを整形して返却といったことをやっているようです。

CloudFormationを設定する

CloudFormationの設定はtemplate.yamlというファイルに書いています。

https://github.com/kimuray/sinatra_lambda_sample/blob/master/template.yaml

これも大体AWSサンプルと同じです。
唯一違うとしたらDynamoDBを用意する設定を書いていないぐらいです。

設定内容のざっくり説明としては

  • AWS Lambdaを準備
  • AWS Lambdaを叩くためのAPI Gatewayを準備
  • AWS Lambdaへのアクセスポリシーを設定
  • エンドポイントへのURLを設定

といった設定が書いてあります。 template.ymlを設定し終わったらCloudFormationの準備は環境です。

デプロイ

デプロイはAWSのサンプルに書いてある通りawscliのコマンドを叩いていくだけで完了します。

※ 前提としてS3にソースを配置するバケットを作っている必要があるので作っておきましょう。

まずはデプロイをするための設定ファイルを作成します。
以下のコマンドでserverless-output.yamlという名前で作成されます。

aws cloudformation package \
     --template-file template.yaml \
     --output-template-file serverless-output.yaml \
     --s3-bucket { your-bucket-name }

{your-bucket-name}には自分で作ったS3のバケットを設定します。

次に生成された設定を使ってAWS Lambdaにデプロイします。

aws cloudformation deploy --template-file serverless-output.yaml \
     --stack-name { your-stack-name } \
     --capabilities CAPABILITY_IAM

{your-stack-name}は任意の名前になります。

これでデプロイが完了します!

デプロイの完了を見届けたらAWSコンソールにアクセスして、AWS Lambdaに作成したアプリケーションがデプロイされていること確認します。

f:id:kimuraysp:20181213084717p:plain

作成された項目にアクセスするとAPI Gatewayの欄をクリックすると、画面下の方にアプリケーションのエンドポイントが表示されます。

f:id:kimuraysp:20181213084742p:plain

このエンドポイントにアクセスして、自分が作ったSinatraアプリが表示されたら成功です。

最後に

久々のブログだった...
ちゃんとエンジニアになったのでもっとインプット・アウトプットの量を増やさねば...

プログラミングスクール勤めのエンジニアが転職するってよ

お久しぶりです。
かなり久々のブログ投稿になります。

今回は転職活動について取り上げたいと思います。
というのも7月あたりからぼちぼち転職活動していて、最近転職先が決まったのです。

私はWebエンジニアとしてプログラミングスクールで開発を行っています。
しかし、かなり我流で開発を行なっている状態になっています。
そこでエンジニアとして今後通用していくのか?と疑問を感じて転職活動を始めました。

そんな中で数社の企業様から内定をいただくことができました。
今回の転職活動で精神面がかなり成長したと感じています。
そして、もしかしたらこの2ヶ月ほどで考えていたことが誰かに役に立つかもしれないと思い記事を投稿することにしました。

特に自分のキャリアに迷っている人や何かに駆られて転職活動している人に届けられたら嬉しいと感じます。

転職活動記録

これから感じたことを書いていこうと思うのですが、その前に自分自身の体験を知ってもらった方が良いかと思います。
割と赤裸々に書いているつもりです(照)

転職活動のきっかけ

ここ1年くらいずっとエンジニアとしてのキャリアについて悩んでいました。 そんな悩んでいる中で今年の7月に完全にスケジュール管理おじさんになるような業務をすることになり、

『あれ?俺このままでええんかな?』

という気持ちに駆られるようになりました。

個人的には20代をどのように過ごすかが30代以降の生き方を左右すると考えています。

私はエンジニアとしてのキャリアを積みたいと考えていました。
そのため、スケジュール管理おじさんの状態は20代の時間を棒に振ってしまっているのではないか?と感じるようになりました。

7月 転職活動の火蓋が切って落とされる

一回転職しているとはいえ、現在の職はお声をかけてもらっての転職でした。
そのため、ほぼ転職活動は行なったことがなく実質今回の転職活動が初めての転職活動という形でした。

何がともあれ情報収集だと思ってとりあえずエージェントに話を聞きに行きました。

行ったエージェントはIT系に強い、よく名前を聞く2社とビズリーチ経由で繋がったエージェントが1社です。
3社のうち2社は転職活動の最後まで付き合うことになりました。
個人的な感覚ですがエージェントの良し悪しみたいなところはなんとなく見えた気がします。
エージェントの話はまた別記事で出していこうかと思います。

あとは転職ドラフトに参加しました。
思い悩んだタイミングがちょうどドラフトが始まる時期だったので、参加して選択肢を増やして行く手段に出ました。

選択肢は多めに用意しておくと思いもよらない形で結果が出たりするので種は撒いておいて損ないです。

7月は本当に種まき的な感じで情報収集ぐらいしかしてないですね。

実働はエージェントと話した3時間くらいかなあ

8月 面接面談が始まり迷路に迷い込む

8月になり、転職ドラフトで数社から指名いただきました。

とにかく話は聞こうというスタンスで指名いただいた全社にカジュアル面談を申し込みました。

そして、3社のエージェントのうち1社で

エージェント「とりあえず興味のある企業選んでください」
僕 「このあたりの企業さん興味ありますね」

と雑に興味ある企業を数社選んだらいつのまにか全社にエントリーされ、書類もするっと通ってしまい面接の予定がどんどん組まれていきました。

このあたりから平日夜の予定が面談面接で全て埋まってしまって精神が疲弊しはじめました。

そして、面談面接に行っては

「kimurayspさんはなんで転職しようと思ったんですか?」
「どのようなキャリアを積みたいと考えていますか?」

となんとなくで転職活動を始めてしまった自分には辛い質問を受け、うろたえる日々を繰り返していました…
雰囲気では答えられるけど深められるとすぐに底についてしまうということがかなりありました。

ある企業さんでは技術スキルを見られる面接を受けて、固まってしまうといったことがおきました。

もはや自分はエンジニアに向いていないのではないだろうか…?

ぐらいまで落ち込むこともありました。

そして始まる自己啓発

これは自分の癖のようなものなんですが、

自分が苦しい時や怒っている時に、なぜそう感じているのかを紙に書いてみて整理したり、自己啓発本を読んだりして自分にない考え方を取り入れたりしてみる

ということをよくやります。

今回も例に漏れず苦しさが尋常じゃなかったので自分についての整理を始めました…笑

整理の前に自己肯定感が尋常じゃなく下がっていたので自己啓発本を読むところから始まりました。

今回読んだのは「嫌われる勇気」でした。
チョイスは完全に勘だったのですが、これが意外といいチョイスでした。

読む中で 目的論 の考え方や 他人の人生ではなく自分の人生を生きる ことが重要だと知りました。

そこで考え始めたのが自分はなぜ転職活動を始めたのかというところです。

この時期は転職活動もやめようとも考えたりしていたので、このあたりが何を目的にしているのかも考えました。

転職活動を始めた目的
  • スキルを身につけられる環境にいきたい
  • 自分の将来を考えた時に現状の状態だと活躍している姿がイメージできない
  • 成長できずにいたら最終的に自分に無能の烙印が押されてしまうことに恐怖を感じる
転職活動をやめようと考え始めた目的
  • 迷っている状態で転職活動をしても結果に繋がらない
  • 面接に行って自分という人間が否定された気持ちになるのが辛い
  • 今の状態で転職できても役に立たないのではないか?
  • 転職活動やめて現職に残れば役に立つ存在ではい続けられるかも

ざっと転職活動を始めた目的とやめようと考えた目的を見て行くと 自分の無力感を感じることを避けたい という目的があるように感じました。
自分の中に渦巻いていた感情がはっきりして割とスッキリはしました。

ここで出した結論は、持ち玉があるうちは転職活動を続けるが内定が出ても出なくても持ち玉がなくなったらきっぱり活動をやめるということでした。

どちらの選択肢をとっても感じる不安が同じなのであれば、全力で転職活動をして運命に身を委ねて、選択された運命の中で全力を出し切ろうという方針ができたという形です。
8月はそんな感じで方針がなんとなく決まって自己肯定感が少し回復してきたところで終わりました。

9月 自己理解が深まる、そして内定へ

9月の1週目にとある心理検査の認定トレーナー資格取得研修に参加しました。

この心理検査との出会いが自分の運命を変えました。
正直心理検査一つで大げさなという感じですが、マジで変わりました。
この出会いがあったから転職決まったと言っても過言ではないです。

この心理検査は自己理解を深めることが目的の検査でした。
認定トレーナーの講座では実際に心理検査を受験しました。
9月1週目は自分の性格を知り、自分の考え方について深掘りをひたすら行いました。

そこで無意識的だった自分の認知と考え方が意識できる領域に出てきました。

その結果自分は人の可能性を引き出せるようなことに興味があるのだとわかりました。

自分の行動や思考を振り返ってみると

  • なんとなく国家キャリアコンサルタントの講習を受けはじめる
  • プログラミングスクールで楽しいと感じたのは一緒に開発している人が成長したなと感じる時

など無意識のうちに人に関する領域に興味を持っていたと認知しました。

心理検査を受けた後の変化

自分の興味がはっきりしたことが転職活動に転機をもたらしました。

まず大きく変わったところとしては自分の興味がはっきりしたことで、今回の転職活動に目的が見えてきました。

人の可能性を引き出すことに携わって行く上で、まずは自分自身が行動することで自分の人生を選択することができることを証明すること

今後の長い自分の人生キャリアを考えた時に、この目的を達成することがまず重要であると考えられるようになりました。

次に自己理解が進んだため、面接で自分の考え方について深掘りされてもうろたえることなく自分の見解を伝えることができるようになりました。

その結果、心理検査を受けた後の面接は一度も落ちることなく最終的に数社から内定をいただくことができました。

この結果から 転職活動において自分への理解を深めることがとても重要 だと感じました。

自己理解を深めることの重要性

自分の転職活動の中で自己理解がかなり重要な要素だと感じました。 では、なぜ自己理解を深めることが転職活動で有効になるのか?
その理由を考察してみます。

なぜ転職するのか?に対応できる

この質問は面接の際には95%ぐらい(肌感)の確率で聞かれます。
転職活動に至る動機は人によって異なります。

ただこの動機をうまく言語化するのは難しかったりするのではないかなと感じています。
その結果、割と漠然とした動機しか話すことができずに爆死するという事案が起きる印象です。

例えば

  • 未経験だけどWebエンジニアになりたいという動機

    • なぜWebエンジニアになりたいと感じたか?
    • Webエンジニアになってどんなキャリアを描きたいか?
      • Webエンジニアになることでそのキャリアに向かって何が必要だと感じている?
  • 現職が劣悪過ぎて、会社を変えたい

    • 現職がどのように劣悪で、自分はそれに対してどんな印象を抱いているのか?
    • 劣悪さの内容によっては会社を変えても変わらない可能性があるが、どんな観点で次の会社を探しているか?
    • 現職の問題がもしかしたら業界の問題かもしれないが、なぜ同業界で会社を探しているのか?
    • 会社を変えてどんなキャリアを描きたいか?

のような形で漠然とした動機だと、ざっくり掘るだけでもそれなりに質問ができてしまいます。

うまく動機が言語化できていないと、深掘りされた時に支離滅裂になってしまったり、イメージを言語化できずあやふやになってしまいます。
自分自身も自己理解が深まるまではこの辺りがあやふやでした…。

「なぜ転職するのか?」という質問には

  • 転職することで次の職場に何を期待しているのか?
  • その人の考え方と会社の志向がマッチしているか?
  • 会社はその期待していることを提供できるか?

といった会社と転職者の考え方の方向性があっているか見たいという意識があると思います。

漠然としていると会社とマッチしている人かどうかが不透明となり残念な結果になる傾向あるのではないかなあと推測しています。

これを明確にするためには、

  • 自分の興味関心
  • 将来のキャリア像
  • 現状と理想のギャップ

この辺りを言語化できると、深掘りに耐えれるようになりますし、軸を持って転職活動に取り組めるので自分が求めている環境を探しやすくなります。

ちなみに自分は

  • 興味関心
    • 技術的なスキルアップをしたい
    • toC向けでいろんな人に使われるサービスの開発に携わって見たい
    • 将来的には人の可能性を引き出せるようなことをやって見たい
  • 将来のキャリア像
    • エンジニアチームでメンバーのやりたいことを引き出したり、仕事と関連付けたりするようなポジションに興味がある
    • キャリアに困っている人を助けられるような仕事に興味がある
    • いずれの方向性に進むにしてもエンジニアという仕事をベースにしたいので技術スキルを固める必要がある
  • ギャップ
    • 現職だとサービスの性質上システム開発はクリティカルではなく、開発スキルをもりもり身につけていくことが難しそう
    • 色々な人に使ってもらえるものを作りたいが、スクール事業で今作っている受講生管理システムは最大でも200人ぐらいにしか使ってもらえない
    • 立場的に上の人間がいないので、自分が目指すべきエンジニア像が見えない
      • どのように成長する必要があるかが見えづらい

といったあたりの理由がありました。
個人的な見解ですが、だいたいこれぐらいの筋道が立っていると納得していただけたり、深められても自分の中から答えを探し出しやすくなる印象があります。

自分という人間がどんな思考をするのか伝えられる

正社員の採用だと、その人がどんな思考をして、どんな行動をするのか?という部分は重要視されるのではないかと考えます。

この思考と行動の傾向がみえるとその人がどのように働く人なのかが見えてくると個人的に感じています。

思考がわかれば少し長い目で見た時にどれぐらい成長して成果を出してくれるかが見えてくると考えます。

自分の思考と行動を認識することができれば、

  • どのような環境なら成長しやすいか?
  • 成長のためにどのような取り組みをするか?(してきたか?)
  • 何が得意か?苦手か?
  • 仕事で大事にしていること
  • やりがいに感じること

この辺りを面接等で伝えられるようになると

  • どのように働く人なのか
  • どのような成長をしてくれるのか
  • 将来的なポジションのイメージ

といった仕事についての考え方のマッチ度合い、どれくらいで会社の利益に繋がる成長をしてくれるかが見せることができると考えます。

つまり思考と行動がどれだけ整理されているかで一緒にやっていけるかどうかのイメージに与えられるかに繋がってくると考えられます。

ここで一緒にやっているイメージを与えることができれば採用に近くことができます。

ここまで自分の思考を明確にして、お互いに一緒にやっているイメージがつかないのであればマッチしなかったんだなと割り切ることもできます。

ここでも自分の考えを当てはめてみます。

  • どのような環境なら成長しやすいか?
    • ある程度裁量があって自分で動いたりすることができる
    • モチベーションの高い優秀な人がいる
      • 自分がその人とどんな差異があるか見出し埋めていけると考えている
  • 成長のためにどのような取り組みをするか?(してきたか?)
    • 足りないと感じたスキルについては自己学習
    • 自分の感情や思考について分析している(内省)
      • 自分の感情・思考に関する気づきがあると改善に繋げられる
  • 何が得意か?苦手か?
    • 得意
      • チームの中で調和をとって活動すること
        • 人の感情について考えながら仕事に取り組む
    • 苦手
      • 決断すること
        • 人の感情などを気にして決断を思い切ってすることが苦手
        • 合理的な判断基準を設けることで決断に踏み切るようにしている
  • 仕事で大事にしていること
    • 仕事は一人ではできないのでチームで協調することが重要
  • やりがいに感じること
    • 自分が作ったものが人に使ってもらえる
    • チームメンバーが成長していることを感じるとき

当てはめてみると自分は

人との接し方に気を使ったり、チームで何かを成し遂げたりすること

にモチベーション感じる思考をしているのだとわかりました。

これをもう少し深掘りできると大体の質問には答えられると思います。
自分の場合は過去の経験の中にチームで一つのことを成し遂げた経験があったのがあったのでそれがベースという考えを伝えていました。

総括

個人的な感性ですが、自分は自己理解を深めたことで転職活動の風向きが変わったと感じています。
自分のことを自信を持って伝えられるようになることは面接の場面においてはかなり有効だと思います。

これはエンジニアへの転職活動に限らず、様々な業種で転職活動をしている人に共通するのではないかと考えています。

転職活動は内定をもらうことがゴールではありません。

働き始めた後に良い状態で働き続けられることが重要なのです。

そのためには自分のことをできるだけ多く会社に伝えてマッチするかを測っていくことが重要です。

実際に働いてみないとわからない要素もあると思いますが、全力のミスマッチは防いでいけると思います。

そして会社に多くのことを知ってもらうためには、自分のことを理解することが重要です。

自分のことを考えるのが難しい場合は、世にあるアセスメントツール(心理テスト等)を使ってみるといいかもしれません。
客観的に自分を分析する助けになります。
自分の場合はこれが9月に受けた心理検査でした。

この体験が転職活動を行なっている人が自分のことをきちんと理解し、より幸せな人生をあゆむための一助になれば嬉しいなあと感じます!

【Rails】Webpackerを導入してモダンなJavaScriptをRailsで使う

今回はWebpackerの導入について書いていきます。
内容的には手垢つきまくりの内容ですが、地味に体系的にまとまっているものがなかったのでまとめてみました!

やりたいこと

Webpakcer導入

RailsでモダンなJSフレームワークなどを利用する際にはWebpackerを導入して行きます。
WebpakcerはRails5.1以降からrails newの段階から導入できるようになっています。
またWebpackerはyarnに依存しているためyarnをインストールしておく必要があります。
今回はrails newからではなく、途中のプロジェクトからWebpakcerを導入していきます。

yarnインストール
https://yarnpkg.com/lang/ja/docs/install/#mac-stable

Railsプロジェクトの作成

$ rails new webpacker_sample --skip-turbolinks

turbolinksはjavascriptで画面を実装している際に思わぬ落とし穴になりがちなので入れないようにします。
Railsプロジェクトでまず実行するコマンド周りを実行しておきます。

$ bundle install --path vendor/bundle
$ rails db:create

Webpakcerの導入

Gemfileにwebpackerをインストールするように記載します。
ついでに必要なくなる子達も消しておきます。

# 追記
gem 'webpacker', '~> 3.5'

# 削除
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.2'

基本的にフロントエンド周りのライブラリはnode_module経由で利用するようにしたいので、sassやcoffeeは削除しておきます。

Gemfileを削除したらbundle installします。
bundle installが完了したら、webpackerをインストールします。

$ rails webpacker:install

インストールが完了するとconfig配下にwebpackerの設定ファイル、app配下にjavascriptディレクトリが生成されます。

rails newのタイミングでwebpackerを導入するとこの工程が不要になります。

Webpackerの設定を調整する

初期の状態だとapp/javascriptjavascriptしか使えないん?という感じのディレクトリ名なので、わかりやすいディレクトリ名に変更します。
config/webpakcer.ymlを修正することで対応することができます。

default: &default
  source_path: app/frontend # 変更
  source_entry_path: packs
  public_output_path: packs
  cache_path: tmp/cache/webpacker

この修正を加えた後にapp/javascriptディレクトリをapp/frontendにリネームしておきます。
またapp/frontend/配下にjavascriptsというディレクトリを作成して、その配下にapplication.jsを作成します。

app/frontend/packs/application.jsはwebpackのビルドの取りまとめを行うファイルとして扱います。

スタイルシートや画像も読み込めるようにする

スタイルシートと画像を保存するためのディレクトリを作成しましょう。
app/frontend/stylesheetsapp/frontend/imagesというディレクトリを作成しておきます。
stylesheets配下にはapplication.scssというファイルを作成しておきましょう。

ディレクトリとファイルが作成できたら、諸々の読み込みができるように app/frontend/packs/application.jsに追記します。

import 'stylesheets/application';
import 'javascripts/application';
require.context('../images', true, /\.(png|jpg|jpeg|svg)$/);

設定したjavascriptをviewで読み込めるようにする

javascriptの読み込みとstylesheetの読み込みをできるようにします。

<%= stylesheet_pack_tag 'application', media: 'all' %>
<%= javascript_pack_tag 'application' %>

stylesheet_link_tagstylesheet_pack_tagjavascript_include_tagjavascript_pack_tagに変更します。

設定できているか確認する

viewを作ってみてWebpackerの設定がうまくいっているか確認します。

$ rails g controller pages top

次にrails serverとwepack-dev-serverを立ち上げます。

$ rails s
$ bin/webpacker-dev-server

Webpakcerを使うとbin/webpakcer-dev-serverを実行する必要が出てきます。
rails sとwebpacker-dev-server二つをいちいち立ち上げるのが面倒な場合はforemanを導入するとコマンド一つで立ち上げられるようになります。
https://github.com/ddollar/foreman

コマンドをうったらページ確認のためにブラウザでhttp://localhost:3000/pages/topにアクセスしてみましょう。
問題なくアクセスできれば設定はうまくいっています。

もう少し実感できるようにするためにapp/frontend/javascripts/application.jsapp/frontend/stylesheets/application.scssを編集してみます。

alert('テスト'); // 追記
// 追記
h1 {
  color: red;
}

すると画面にアラートが表示されタイトルが赤く表示されると思います。

f:id:kimuraysp:20180615145956p:plain

rails-ujsを導入する

rails-ujsはdeleteやputといったrequestを飛ばすために必要なライブラリです。
app/assets配下を読み込まないようにしたためrails-ujsが効かなくなってしまっているので導入し直します。

$ yarn add rails-ujs

まずはyarnでrails-ujsをインストールします。
インストールができたらapplication.jsでrails-ujsの読み込みを行います。

// 追記
import Rails from 'rails-ujs';
Rails.start();

ここまで設定することでモダンなJavaScriptRailsで扱えるようになります。

最後に

これでVueでもReactでもなんでもござれです。 ただreact-routerやvue-routerといったクライアントサイドルーティングとRailsの相性が悪い(経験則)ので、SPAにするときはRailsにはAPIに徹してもらうのが一番そうです。

【Rails】ActiveStorageを使ってお手軽にファイルアップロードを試す

最近ぼちぼちアウトプットしようとせこせこインプットしています。

前回Rails5.2でたからActionCable試すという舐めた記事を書きましたが、今日はRails5.2で標準搭載されるようになったActiveStorageを試します!

ActiveStorageとは

ActiveStorageはRails5.2から標準で搭載されるようになったファイルアップローダーです。
AWS S3などのクラウドストレージへのアップロードも設定で手軽に実装できる代物です。

rails/activestorage at master · rails/rails · GitHub

今日はこのActiveStorageを使って簡単な画像も投稿できる機能を作ります。

導入

まずは適当にrails newでサンプルアプリプロジェクトをつくります。
(DBにpostgresql使いますがなんでもOKです)

$ rails new active_storage_sample -d postgresql

プロジェクトができたらGemfile内のmini_magickコメントアウトを外します。
画像処理のために導入するためです。

# Use ActiveStorage variant
gem 'mini_magick', '~> 4.8' # ここのコメントアウト外す

コメントアウトを外したらbundle installでインストールしておきます。
これで導入に必要なものは整いました。

ActiveStorageをインストールする

ActiveStorageを使うためにはまずインストールのコマンドを実行します。

$ rails active_storage:install

実行するとActiveStorageでアップロードファイルを管理するテーブルのmigrationファイルが生成されるのでrails db:migrateを実行しておきましょう。

生成されるテーブルは以下の二つになります。

active_storage_blobs

カラム名 保存内容
id ID
key ファイルを一意に識別するkey
filename アップロードしたファイルの名前
content_type ファイルの種類
metadata メタデータ(画像なら縦横の大きさなどが格納される)
byte_size ファイルサイズ(byte単位)
checksum チェックサム
created_at 作成日時

active_storage_attachments

カラム名 保存内容
id ID
name モデルの属性名(Userモデルのavatarとか)
record_type モデル名(Userとか)
record_id record_typeのモデルのID
blob_id active_storage_blogsのID
created_at 作成日時

ActiveStorageの設定を確認する

ファイルの格納先はconfig/storage.ymlで設定されています。

test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

例えばlocalの設定を使えばプロジェクトルートにあるstorageディレクトリ配下にファイルを格納するという意味になります。

次にconfig/environments/development.rbをみてみます。

# Store uploaded files on the local file system (see config/storage.yml for options)
config.active_storage.service = :local

という記載があり格納先にconfig/storage.ymlで定義したlocalの設定を使うよという設定が書いてあります。

これで設定の確認は完了です。

ファイルアップロードする画面を作る

まずは画像アップロードできるようにUserモデルを作ります。

$ rails g model user name:string

ActiveStorageを扱う際は画像アップロード用のカラムを定義する必要はありません。
コマンドを実行したらrails db:migrateを実行します。

Userモデルができたら、ActiveStorageを使うための記述を追記しておきます。

class User < ApplicationRecord
  has_one_attached :avatar # 追記
end

この追記を行うことでUserモデルにavatarという画像を扱う属性が付与されます。
has_oneがあればhas_manyもあります。
has_many_attachedを利用すれば複数画像を扱うこともできます。

詳しくはこちらで

Active Storage の概要 | Rails ガイド

ActionStorageを使うための記載はだいたい終了なので、あとはざっと画面などを作成します。

# config/routes.rb
Rails.application.routes.draw do
  root "users#index"
  resources :users, only: [:new, :create]
end
# app/controllers/users_controller.rb
class UsersController < ApplicationController
  def index
    @users = User.all
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)

    if @user.save
      redirect_to root_url, notice: 'Add User'
    else
      render :new
    end
  end

  private

  def user_params
    params.fetch(:user, {}).permit(:name, :avatar)
  end
end
<!-- app/views/users/new.html.erb -->
<h1>Add User</h1>

<%= form_with model: @user, local: true do |form| %>
  <div>
    <%= form.label :name %>
    <%= form.text_field :name %>
  </div>

  <div>
    <%= form.label :avatar %>
    <%= form.file_field :avatar %>
  </div>

  <div>
    <%= form.submit %>
  </div>
<% end %>
<!-- app/views/users/index.html.erb -->
<h1>Users Index</h1>
<%= link_to 'Add user', new_user_path %>

<ul>
  <% @users.each do |user| %>
    <li>
      <p><%= user.name %></p>
      <%= image_tag user.avatar %>
    </li>
  <% end %>
</ul>

ここまでやると、こんな感じになります。

  • 投稿画面 f:id:kimuraysp:20180420235321p:plain

  • 一覧画面 f:id:kimuraysp:20180420235349p:plain

という感じですごく簡単に画像アップロードが実装できてしまいます!

S3にアップロードできるようにする

S3でバケットを作る

せっかくなのでS3にアップロードできるようにしてみます。

まずはAWS S3で適当な名前のバケットを作成します。
(わかりやすくactive-storage-sampleというバケットを作りました)

f:id:kimuraysp:20180420235619p:plain

作成したらS3を操作できるIAMユーザーを作成してアクセスキーとシークレットキーを取得しておきましょう。

格納先の設定をS3に向くように変更する

config/storage.ymlの以下のコメントアウトを外します。

amazon:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  region: ap-northeast-1
  bucket: active-storage-sample

config/environments/development.rbで先ほどlocalとなっていることを確認した設定をamazonに変更します。

config.active_storage.service = :amazon # :localを:amazonに変更

またS3へのアップロードを行うためにaws-sdk-s3を導入します。
Gemfileに以下を追記しましょう。

gem 'aws-sdk-s3'

追記したらbundle installしておきます。

アプリケーションからS3につなぎこむ

アプリケーションからS3につなぎこむためにIAMユーザーを作成して取得したアクセスキーとシークレットキーを設定しましょう。

Rails5.2からcredentialsという機密情報を暗号化する機能が追加されています。
これを使ってアクセスキーとシークレットキーを設定します。

$ EDITOR=vim rails credentials:edit

これを実行するとエディタ(この記載だとvim)が開いてキーを設定できます。

エディタが開いたら以下のように設定を記載します。

aws:
  access_key_id: アクセスキー
  secret_access_key: シークレットキー

記載したら保存して閉じます。
するとconfig/credentials.yml.encというファイルとconfig/master.keyというファイルができています。
config/credentials.yml.encは暗号化されているので内容を見ることはできません。

暗号化のキーにはconfig/master.keyに記載されているキーが使用されています。(環境変数RAILS_MASTER_KEYが設定されていれば、これを使う)

設定を確認したい場合はrails credentials:showを実行すれば生のデータを確認することができます。

先ほどconfig/storage.ymlでコメント外したところに

Rails.application.credentials.dig(:aws, :access_key_id)

という記載がありましたが、これはcredentialsのawsaccess_key_idを取得するという記載になります。

ここまで設定できれば画像を保存した際にローカルではなくS3にファイルが格納されるようになっています。
クラウドストレージへのアップロードも少ない手順で実現できてしまうのはお手軽で素晴らしいですね。

ちなみに

config/master.keyRAILS_MASTER_KEYの取り扱い間違えて消してしまったりすると、credentialsの複合ができなくなり詰んでしまうので注意しましょう。
詰んでしまった場合はconfig/credentials.yml.encを削除してrails credentials:editで1から設定し直すと持ち直せる可能性があります(個人開発に限る。チーム開発だとハラキリしかないかもしれない)

最後に

ActiveStorage手軽で便利なのですが、バリデーションやキャッシュの機能を持ち合わせていないとどこかでみたのでアップロード時にファイルチェックが必要な要件があったりすると扱いにくいかもしれません。

ただ厳密さが求められないような状況であれば素早く実装できるので検討してみても良さそうです!

Rails5.2が出たし、このタイミングでActionCableを使う

こんにちは!Rails5.2がリリースされましたね! ということで今回はActionCableを試してみましょう。

…ActiveStorageの間違いじゃないかって?

振り返ってみると個人的にActionCable使った実装ってやったことなかったり、そもそも必要性なくて触ってなかったという方も多いのではないか(直感)ということで、このタイミングであえてActionCableに触れます!

作るもの

今回作るのは簡単なチャットアプリです!
イメージ的にはこんな感じ

f:id:kimuraysp:20180415200842g:plain

複数のブラウザを立ち上げて、一つのブラウザで投稿したらリアルタイムで別のブラウザにも反映されるようなものを作りたいと思います!

ともあれ導入

とりあえずrails newですね!

$ rails new action_cable_sample --skip-turbolinks -d postgresql

turbolinksは邪魔な子になりそうだったので退場してもらいます。
rails newが終わったらrails db:createもやって準備万端にしておきましょう。

チャットに必要になりそうなコントローラーとmodelも作っておきます。

$ rails g controller chat_rooms show
$ rails g model chat_message content:text
$ rails db:migrate

一通りコマンドを実行して役者を揃えておきます。

作ったcontrollerとviewを整えておきます。

# app/controllers/chat_rooms_controller.rb
class ChatRoomsController < ApplicationController
  def show
    @chat_messages = ChatMessage.all
  end
end
<!-- app/views/chat_rooms/show.html.erb -->
<div id="chat">
  <% @chat_messages.each do |chat_message| %>
    <p><%= chat_message.content %></p>
  <% end %>
</div>

今回は試しなのでチャットルームへはルートにアクセスしたら飛べるようにします。

Rails.application.routes.draw do
  root 'chat_rooms#show'
end

channelを作成する

ここからwebsocket通信を行うために必要になるActionCableのファイルを作成していきます。
といってもやることは簡単でコマンドを実行するだけです!

$ rails g channel chat_room speak

すると以下2つのファイルが作成されます。

# app/channels/chat_room_channel.rb
class ChatRoomChannel < ApplicationCable::Channel
  def subscribed
    # stream_from "some_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end

  def speak
  end
end
// app/assets/javascripts/channels/chat_room_channel.js
App.chat_room = App.cable.subscriptions.create("ChatRoomChannel", {
  connected: function() {
    // Called when the subscription is ready for use on the server
  },

  disconnected: function() {
    // Called when the subscription has been terminated by the server
  },

  received: function(data) {
    // Called when there's incoming data on the websocket for this channel
  },

  speak: function() {
    return this.perform('speak');
  }
});

次にActionCable用のルーティングを準備します。

# config/routes.rb
mount ActionCable.server => '/cable'

ここまできたらActionCableを使う準備は完了です!

ひとまず動作確認

ActionCableと繋がっているかを確認します。
rails sを立ち上げてhttp://localhost:3000にアクセスします。
アクセスしたらchromeの検証ツールを開いてApp.chat_room.speak()を実行してみます。

f:id:kimuraysp:20180415203327p:plain

app/assets/javascripts/channels/chat_room_channel.jsApp.chat_roomにActionCableのオブジェクトを代入しているのでApp.chat_room.speak()が呼べるようになります!

とはいえまだコード的なものは全然書いていませんが、ActionCableへのつなぎこみはこれで完了です!

まずはリアルタイムでalertをあげてみる

手始めにApp.chat_room.speak('Hello')とコンソールで実行したら起動しているブラウザにalertをあげるようにしていきます。

まずはapp/channels/chat_room_channel.rbを以下のように修正します。
subscribedでどのchannel(今回はchat_room_channelとします)を購読するかを指定します。
speakでは購読しているチャンネルにメッセージを配信するというような記載をします。

# app/channels/chat_room_channel.rb
class ChatRoomChannel < ApplicationCable::Channel
  def subscribed
    stream_from 'chat_room_channel'
  end

  # 変更ないので省略

  def speak(data)
    ActionCable.server.broadcast 'chat_room_channel', message: data['message']
  end
end

変更したら次にapp/assets/javascripts/channels/chat_room.jsを以下のように修正します。

// app/assets/javascripts/channels/chat_room.js
App.chat_room = App.cable.subscriptions.create("ChatRoomChannel", {
  // 変更ないので省略

  // 購読側が受け取る内容
  received: function(data) {
    alert(data['message']);
  },

  // App.chat_room.speak(message)で配信する
  speak: function(message) {
    return this.perform('speak', { message: message });
  }
});

speakに引数を追加します。
performに追加した引数を渡すように記載します(オブジェクト形式で書く)。

receivedは購読しているチャンネルから配信があった場合にどうするかを記載します。
今回はalertをあげたいのでalert(data['message'])と記載します。
配信されてきた情報はdataオブジェクトに乗って入ってきます!
messageはActionCable.server.broadcast 'chat_room_channel', message: data['message']message: data['message']で指定されています。

ここまでやるとコンソールでApp.chat_room.speak('Hello')を実行するとalertでHelloが表示されるのが確認できます。

チャットっぽくしてみる

ここからチャット風に変えていきます!
まずはapp/views/chat_rooms/show.html.erbに投稿するための以下を末尾に追記します。

<form>
  投稿: <input type="text" />
  <input type="submit" value="投稿" onClick="postChatMessage()" />
</form>

投稿ボタンがクリックされたらpostChatMessage()という関数を発火させるようにしておきます。

postChatMessage()はこんな感じに実装しておきます。
一旦、app/assets/javascripts/application.jsの末尾にでも記載してください。

function postChatMessage() {
  event.preventDefault();
  var element = document.querySelector('input[type="text"]');
  App.chat_room.speak(element.value);
  element.value = '';
}

投稿ボタンが押されたら今までコンソールでチクチク実行していたApp.chat_room.speakを実行するようにしています。

channelのspeakにDBに登録する処理を追記する。
単純にcreate処理を追記するだけです!

# app/channels/chat_room_channel.rb
def speak(data)
  chat_message = ChatMessage.create!(content: data['message']) # 追記
  ActionCable.server.broadcast 'chat_room_channel', message: chat_message.content
end

それができたら、チャットが投稿されたら画面に反映されるようreceivedにDOMを操作する処理を書いておきます。
alertを消して以下の記述に変更します。

// app/assets/javascripts/channels/chat_room.js
received: function(data) {
  var chat = document.getElementById('chat');
  var newMessage = document.createElement('p');
  newMessage.innerText = data['message'];
  chat.appendChild(newMessage);
},

配信を受け取ったらid="chat"のDOM内に投稿内容を記載したpタグを追加するようにしています!

こうすることで冒頭に見せたチャットっぽいものが動くようになります!

さいごに

ActionCableなんだかんだ触ったことがなかったので新鮮でした!
ActionCableはRailsだけでなくJSも絡んでくるので割と混乱しやすい機能なのかなあとも感じたりします…

次はActiveStorageにでも触れよう