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
言わずと知れたサーバーレスのコード実行サービスです。
サーバーを管理する必要がなくなるのでサーバーの準備や運用を考えなくてよくなります。
Sinatra
Ruby製のシンプルにWebアプリケーションが作れるフレームワークです。
Railsほど機能はいらんけど、ルーティングあたりの機能は欲しいなどの要望に応えてくれます。
AWS CloudFormation
AWSでのインフラ構築を自動化してくれるサービスです。
一度設定してしまえばそれに従って同一環境を何度でも簡単に作れるようになります。
今回はCloudFormationが主役になります。
AWS CloudFormation (設定管理とオーケストレーション) | AWS
Sinatraアプリを作る
今回はサンプル的に雑にテキストボックスを用意して、POSTリクエストを投げたら、投稿内容が画面に追加されていくようなアプリを作りました。

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を用意する設定を書いていないぐらいです。
設定内容のざっくり説明としては
といった設定が書いてあります。 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に作成したアプリケーションがデプロイされていること確認します。

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

このエンドポイントにアクセスして、自分が作った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エンジニアになることでそのキャリアに向かって何が必要だと感じている?
現職が劣悪過ぎて、会社を変えたい
- 現職がどのように劣悪で、自分はそれに対してどんな印象を抱いているのか?
- 劣悪さの内容によっては会社を変えても変わらない可能性があるが、どんな観点で次の会社を探しているか?
- 現職の問題がもしかしたら業界の問題かもしれないが、なぜ同業界で会社を探しているのか?
- 会社を変えてどんなキャリアを描きたいか?
のような形で漠然とした動機だと、ざっくり掘るだけでもそれなりに質問ができてしまいます。
うまく動機が言語化できていないと、深掘りされた時に支離滅裂になってしまったり、イメージを言語化できずあやふやになってしまいます。
自分自身も自己理解が深まるまではこの辺りがあやふやでした…。
「なぜ転職するのか?」という質問には
- 転職することで次の職場に何を期待しているのか?
- その人の考え方と会社の志向がマッチしているか?
- 会社はその期待していることを提供できるか?
といった会社と転職者の考え方の方向性があっているか見たいという意識があると思います。
漠然としていると会社とマッチしている人かどうかが不透明となり残念な結果になる傾向あるのではないかなあと推測しています。
これを明確にするためには、
自分の興味関心将来のキャリア像現状と理想のギャップ
この辺りを言語化できると、深掘りに耐えれるようになりますし、軸を持って転職活動に取り組めるので自分が求めている環境を探しやすくなります。
ちなみに自分は
- 興味関心
- 将来のキャリア像
- エンジニアチームでメンバーのやりたいことを引き出したり、仕事と関連付けたりするようなポジションに興味がある
- キャリアに困っている人を助けられるような仕事に興味がある
- いずれの方向性に進むにしてもエンジニアという仕事をベースにしたいので技術スキルを固める必要がある
- ギャップ
- 現職だとサービスの性質上システム開発はクリティカルではなく、開発スキルをもりもり身につけていくことが難しそう
- 色々な人に使ってもらえるものを作りたいが、スクール事業で今作っている受講生管理システムは最大でも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/javascriptとjavascriptしか使えないん?という感じのディレクトリ名なので、わかりやすいディレクトリ名に変更します。
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/stylesheetsとapp/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_tagをstylesheet_pack_tag、javascript_include_tagをjavascript_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.jsとapp/frontend/stylesheets/application.scssを編集してみます。
alert('テスト'); // 追記
// 追記 h1 { color: red; }
すると画面にアラートが表示されタイトルが赤く表示されると思います。

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();
ここまで設定することでモダンなJavaScriptをRailsで扱えるようになります。
最後に
これで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>
ここまでやると、こんな感じになります。
投稿画面

一覧画面

という感じですごく簡単に画像アップロードが実装できてしまいます!
S3にアップロードできるようにする
S3でバケットを作る
せっかくなのでS3にアップロードできるようにしてみます。
まずはAWS S3で適当な名前のバケットを作成します。
(わかりやすくactive-storage-sampleというバケットを作りました)

作成したら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のawsのaccess_key_idを取得するという記載になります。
ここまで設定できれば画像を保存した際にローカルではなくS3にファイルが格納されるようになっています。
クラウドストレージへのアップロードも少ない手順で実現できてしまうのはお手軽で素晴らしいですね。
ちなみに
config/master.keyやRAILS_MASTER_KEYの取り扱い間違えて消してしまったりすると、credentialsの複合ができなくなり詰んでしまうので注意しましょう。
詰んでしまった場合はconfig/credentials.yml.encを削除してrails credentials:editで1から設定し直すと持ち直せる可能性があります(個人開発に限る。チーム開発だとハラキリしかないかもしれない)
最後に
ActiveStorage手軽で便利なのですが、バリデーションやキャッシュの機能を持ち合わせていないとどこかでみたのでアップロード時にファイルチェックが必要な要件があったりすると扱いにくいかもしれません。
ただ厳密さが求められないような状況であれば素早く実装できるので検討してみても良さそうです!
Rails5.2が出たし、このタイミングでActionCableを使う
こんにちは!Rails5.2がリリースされましたね! ということで今回はActionCableを試してみましょう。
…ActiveStorageの間違いじゃないかって?
振り返ってみると個人的にActionCable使った実装ってやったことなかったり、そもそも必要性なくて触ってなかったという方も多いのではないか(直感)ということで、このタイミングであえてActionCableに触れます!
作るもの
今回作るのは簡単なチャットアプリです!
イメージ的にはこんな感じ

複数のブラウザを立ち上げて、一つのブラウザで投稿したらリアルタイムで別のブラウザにも反映されるようなものを作りたいと思います!
ともあれ導入
とりあえず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()を実行してみます。

app/assets/javascripts/channels/chat_room_channel.jsでApp.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にでも触れよう
【Vue】Vue.Draggableを使ってサクッとTrelloっぽいものを作る
お久しぶりです。超久しぶりです。
ブログ書くのめっちゃさぼっていました…
久々にちょっと時間があったのと、お勉強で触ったVue.Draggableがとってもお手軽便利だったので紹介します!
Vue.Draggableとは
Vue.Draggableはドラッグ&ドロップでリストを並び替えすることをお手軽に実装できるライブラリです!
Sortable.jsをVueコンポーネントで扱えるようにしたライブラリのようです。
これを使うことでサクッと並び替えのできるリストが実装できます!
導入
まずはVueプロジェクトを作ります。
vue-cliを使ってサクッと作ります。
プロジェクトの名前は任意で問題ありません。(今回はvuedraggable-sandboxとします)
$ vue create vuedraggable-sandbox
プロジェクトができたらVue.Draggableを導入します。
(今回はyarnを使用します)
$ yarn add vuedraggable
とりあえずサクッと試したいのでsrc/App.vueにVue.Draggableをimportしてリストを作ってしまいます。
使用しないのでHelloworld系のものは消してます。
// src/App.vue <template> <div id="app"> <draggable element="ul"> <li v-for="task in tasks">{{ task }}</li> </draggable> </div> </template> <script> import draggable from 'vuedraggable'; export default { name: 'app', components: { draggable, }, data() { return { tasks: [ 'task1', 'task2', 'task3', 'task4', ] } } } </script>
importしたvuedraggableはcomponentsに配置します。
また、リストのデータとしてdataにtasksという配列を設定しておきます。
templateの部分で記載している
<draggable element="ul"> <li v-for="task in tasks">{{ task }}</li> </draggable>
の部分がVue.Draggableを使用している箇所です。
draggableタグで指定しているelementはdraggableの部分をなんのタグにするかを指定しています.(デフォルトはdiv)
draggableで囲って並び替えのしたい要素をv-forで出力するだけで並び替えの仕組みは実装されます。

わかりやすくするために少しCSSを調整しています。
たったこれだけでドラッグ&ドロップで並び替えできるリストが作れます。
Trelloに近づける
これだけだとまだTrelloっぽさからは少し遠いですね。
なので列を増やして、縦の移動だけではなく横の移動もできるようにします。
列を表現するためにtasksを二次元配列にします。
data() {
return {
tasks: [
['task1-1', 'task1-2', 'task1-3', 'task1-4'],
['task2-1', 'task2-2', 'task2-3', 'task2-4'],
['task3-1', 'task3-2', 'task3-3', 'task3-4']
]
}
}
またdraggableの部分を以下のように修正します。
<draggable :options="{ group: 'tasks' }" element="ul" v-for="list in tasks"> <li v-for="item in list">{{ item }}</li> </draggable>
optionsでgroupにtasksを設定することで、tasksの中にある配列間での要素移動ができるようになります。
またdraggableのところでtasksをv-forで回すようにします。
これだけで列間での移動もできるようになります。

実際にTrelloっぽいものを作るとなるとAPI連携があったり、タスクの追加ができたりという機能も必要ですが並び替えについてはたったこれだけでできるようになってしまいます!
世の中末恐ろしいです…
今回のブログを書くのに使用したサンプルは以下になります!
さいごに
世の中便利なものがいっぱいです
どう道具を使うかを考えることがとりあえずものを作る上では重要なのかもしれません
【副業】会社勤めだけどはじめての確定申告に行ってきた
お久しぶりのブログになります。。。笑
ほんとだったら技術ブログをかけって話なんですが、今日は生まれて初めて確定申告に行ってきたので書いていきます
気持ち
このエントリーを書こうと思ったのは、初めて確定申告に行ってきたというのもありますが、会社員とかで確定申告に行ったことがない人って割とこのイベントにハードルを感じているのではないかなあと思っているので割と簡単にできちゃうよってのを知って欲しさがあったためです!
注意
とはいえ、簡単にできちゃうのはちょっとした副業とか仮想通貨でちょっと儲かちゃったって人限定のお話かもしれません。。。
フリーランスの人や副業が本業上回る勢いで稼ぎでているとかの人だとえらい大変なイベントなのかなあと思います。(収支の記録を辿るのが辛そうなイメージ)
自分の状況
去年の自分の状況として
- 仮想通貨でそれなりの額で利確をした
- 知人からちょっと仕事を引き受けて副業的に取り組んだ
ということがあり見事に副収入が20万円を超えてしまい、晴れて確定申告の対象に。。。
※ 会社勤めの場合、副収入が20万円になると確定申告の対象になってしまいます。
詳しくは
https://www.freee.co.jp/kb/kb-kakuteishinkoku/necessary-case/
確定申告に当たって準備するもの
必要な書類
※ 通知カードと運転免許証はマイナンバーカードがあればそれで代用できる
確定申告書を作るのにあると便利なもの
- PC
- あとで紹介する会計サービスをつかうため
- プリンター、コピー機
確定申告のやり方
確定申告書類の作成はfreeeを使うとめっちゃ簡単でした!
月額980円がかかってしまうのですが、手軽に確定申告書類ができてしまうので払う価値は十分にあります。
詳しい操作はfreeeの指示に従っていけば大体完了しちゃいます!
会計freeeで行う確定申告の流れ – freee ヘルプセンター
僕の場合は副業の収入を記録する必要があったため収支の欄に雑収入として収入を入力しまくりました。
この収入の額については銀行通帳見ながら副業の収入の部分を手動で入力していきました。(自分の記憶力が試されます)
仮想通貨分の申告
今年の確定申告で結構肝になるのがこの部分の申告だと思います。
僕は以下のサービスを使って損益の計算を行いました。
幸運にも某国内仮想通貨取引所しか使っていなかったため、このサービスに従って必要なデータをアップロードしただけで損益計算が終了しました。
ここで出てきた損益をfreeeの仮想通貨所得を入力する欄にコピペするだけでした。
仕上げ
あとはfreeeで確定申告書を作り切ってPDFとして出力するだけでした。
便利サービスを使うことで確定申告の知識が1ミリもない状態でも確定申告書類を作成することができます。
雑所得だと書類添付の義務はないみたいなので作成した確定申告書と必要書類だけ持って堂々と税務署に乗り込めばすんなり確定申告は終わってしまいます。
個人的な感想ですが、確定申告ってもっと仰々しいものだと思っていたのですが、結構あっさり終わった印象でした。
確定申告の流れまとめ
- 必要書類を用意します
- freeeを使って確定申告書を作ります
- 仮想通貨の収入がある人はcryptactなど使って仮想通貨の損益計算を行って、計算結果をfreeeに記載
- 作成した確定申告書を印刷します
- 押印とマイナンバーの記載が必要な箇所があるのでそこは手書きで埋める
- 税務署にいきます
- 提出します
- 優勝
といった流れになります。
最後に
注意して欲しいのですが、僕は税に関する知識などかなり薄いのでこの方法が正しい方法なのかは定かではありません。。。
実際に確定申告を行う際は自己責任でお願いいたします(ごめんなさい)
ただ確定申告って思いの外、あっさりしたイベントだよってのを確定申告をやってこなかった会社員の方などに知って欲しいという思いでこのエントリーを書きました。
確定申告が怖くて副業するのを踏みとどまったりしている人はもったいないのでガンガン副業しちゃった方がいいと思います!
あとちょっとだけ稼ぎが出てしまって確定申告の対象にはなってしまった人は少額なら大丈夫だろーと思わずにきちんと納税した方が良いと思います。
納税は国民の義務というのもありますが、このいっときのめんどくささに負けてやるべきことやらずに後から脱税が発覚して罰則で遅延料払わせられたりするのは馬鹿らしいと思うので。。。
とりあえず今回の確定申告で、収支の記録(領収書など)をこまめにつけておくのが非常に重要なんだろうなーと感じました。
もしかしたらフリーランスに挑戦したりすることがあるかもしれないので、いい教訓になりそうです。
確定申告期間は残り2週間です!!
バシッとめんどいことを終わらせて清々しい気持ちで来年度を迎えましょう