Rails7.1でRailsチュートリアルを進める上での変更点
ひさしぶりにRailsチュートリアルをやろうと思い、どうせならgem等は最新のもの、使い慣れているものを使おうということですすめていました。
まだ3章しかやっていないのですが、小さくない変更点があったのでまとめます。
RenderのruntimeのデフォルトがDockerに
Renderのデプロイ設定を入れる際のruntimeのデフォルトが、rubyではなくDockerになっています。Rails7.1よりproduction向けのDockerfileがrails new時に作成されるようになりました。Renderのランタイムの判定方法としてはDockerfileがあればdockerで起動するアプリケーションだと判断し、なければその他…としているようです。
Dockerのままでも、以前のようにRubyに変更しても問題なくデプロイされました。
テストが落ちたときに詳細なエラーメッセージが出ない
例えばviewテンプレートが存在しない場合に、以前だと「missing a template
」というような結果がテストで表示されていたのがステータスコードのみの表示になります。
Rails7.0
ActionController::MissingExactTemplate: StaticPagesController#about is missing a template for request formats: text/html
Rails7.1
Expected response to be a <2XX: success>, but was a <406: Not Acceptable>
要因としては、Rails7.1よりRAILS_ENV=testのときのデフォルト設定だと、本番により近いエラーレスポンスが返されるようになりました。
https://github.com/rails/rails/pull/45867
週刊Railsウォッチ: Arel::Nodes::Cteが追加、html_escape_onceの修正ほか(20230613前編)|TechRacho by BPS株式会社
デフォルト設定のままだと、ステータスコードから何がまずいのか推測する必要がありそうです。この設定はconfig/environments/test.rbで変更可能です。
他にも気づいたところは随時記載していきます。
サーバーレス風味のRails
手抜きしつつそこそこいい感じにRailsアプリケーションを構築する方法を整理しています。
要求としては以下のようなものを考えています。
一般的なwebアプリケーションの要求としてはよくあるものです。
AWSでこれを実現する場合に、雑になりすぎず、また頑張りすぎることもなく実現するにはどうしたらいいかを色々と模索していました。最終的には以下のような構成になりました。
リソース
- App Runner(APIサーバー)
- Event Bridge→Lambda(スケジュール処理)
- App Runner→SQS→Lambda(非同期ジョブ)
Lambdaはコンテナイメージを使ってデプロイします。使うコンテナイメージはApp Runnerと同じものを使います。これによりイメージのビルドなどをシンプルに保つ事ができます。
push時にやっていること
- mainブランチマージでリソースの更新
- ECRにpush
- ECR更新をフックにApp Runner更新
- Lambdaの更新
- Event Bridge Scheduleの更新
- ECRにpush
全てGithub Actionsで実施しています。
できないこと
- 15分以上かかるスケジュール、非同期処理
- Lambdaが高稼働する場合のRDBコネクションがかさむ問題への対応
一定このあたりを許容できるようなサービス限定となります。許容できない場合はなんらか対応する必要がありますが、一定この構成であれば部品を他のものに置き換えることができるかと思います。
まとめ
AWSでRails環境を構築する場合に手をかけずそこそこいい感じに構築する方法をまとめました。いろいろ調べつつアップデートしていければいいなと思います。
Ruby1.8.7の動く環境を探す&構築する
久しぶりにるびまのRubyコード添削回を読んでいて、コードを手元で動かしたくなった。
Ruby3.2で動かしてみたところエラーになったり明らかに想定していない挙動になったりという感じで挙動を確かめられなかったので、当時の環境を再現してコードを動かしたくなった。
Rubyバージョンの特定
記事の初稿は2005年とある。「ruby 2005」と調べるとruby-lang.orgのニュースのアーカイブページが出てきた。
2005/12にRuby 1.8.4がリリースされたようだ。ひとまずパッチバージョンまではこだわらないことにして(この頃のRubyだとこだわったほうがいいかもと言うのが一瞬頭をよぎったが)Ruby 1.8.7が動く環境を得ることを目標にした。
rbenvを用いたmacosへのインストール
(エラー内容をコピーするのを忘れたが)よくわからないエラーがでた。もともとmacのローカル環境でシステムライブラリをいじりたくはなかったので早々にmacローカルへのインストールはあきらめた。
dockerイメージを探す
次に思いついたのはdockerによる環境構築だ。しかしながらdockerの公式のイメージにRuby2.6以前のものは置いていない。
ぐぐってみたところ以下のようなdocker imageやDockerfileがヒットしたので動作をみてみることにする。
okyada/dockerhub-ruby
FROM centos:7 RUN yum update -y RUN yum install -y mariadb-devel make gcc gcc-c++ openssl-devel readline-devel libcurl-devel libxml2-devel libxslt-devel ENV INSTALL_PATH /app RUN mkdir -p $INSTALL_PATH WORKDIR $INSTALL_PATH RUN yum install -y wget patchutils patch RUN wget https://cache.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p374.tar.gz RUN tar zxvf ruby-1.8.7-p374.tar.gz RUN cd ruby-1.8.7-p374 && \ wget -O - "https://github.com/ruby/ruby/commit/0d58bb55985e787364b0235e5e69278d0f0ad4b0.patch" | sed -e '1,/Remove unused variable/d;/test_pkey_ec.rb /,$d' | patch -p1 && \ ./configure && make && make install WORKDIR $INSTALL_PATH RUN (echo 'gem: --no-document' ; echo 'install: --no-document --no-ri --no-rdoc' ; echo 'update: --no-document --no-ri --no-rdoc') > ~/.gemrc RUN wget https://rubygems.org/rubygems/rubygems-2.6.12.tgz RUN tar zxvf rubygems-2.6.12.tgz RUN cd rubygems-2.6.12 && ruby setup.rb RUN gem install bundler -v 1.8.7 RUN rm -rf $INSTALL_PATH
なんとbuildしてみたところ動いた!gem install bundlerのところでもともとはバージョン指定してなかったが、エラーになったのでバージョン指定する。
centos7というかそもそもdockerのベースイメージにcentosを使っているのが少し気になり、もう一方も試してみる。
silvioqdockers/ruby-1.8.7
FROM debian:jessie RUN DEBIAN_FRONTEND=noninteractive apt-get update \ && apt-get -y -q install \ autoconf \ bison \ build-essential \ curl \ git-core \ imagemagick \ libsqlite3-dev \ libcurl4-gnutls-dev \ libmagickwand-dev \ libmysqlclient-dev \ libreadline6-dev \ libssl-dev \ libxml2 \ libxslt1-dev \ libyaml-dev \ memcached \ mysql-client \ subversion \ wget \ zlib1g \ zlib1g-dev \ && rm -rf /var/lib/apt/lists/* \ && wget -q -O ruby-1.8.7-p374.tar.gz http://cache.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p374.tar.gz \ && tar xf ruby-1.8.7-p374.tar.gz \ && cd ruby-1.8.7-p374 \ && ./configure \ && make \ && make install \ && ldconfig \ && cd - \ && rm -fr ruby-1.8.7-p374.tar.gz ruby-1.8.7-p374 \ && ruby -v \ && git clone https://github.com/rubygems/rubygems.git \ && cd rubygems \ && git pull origin --tags \ && git checkout v1.8.30 \ && ruby setup.rb \ && cd - \ && rm -fr rubygems
こちらも問題なくうごいてしまった。
ただこちらも、debianではあるもののjessieを使っていて古い。しかしながらstretchに上げてみたところエラーとなってしまった。ライブラリが存在しないエラーを一通り解消したらRubyのコンパイルまではすすんだが、openssl系のエラーで落ちてしまった。おそらくokyada/dockerhub-rubyにあるようになんらかpatchを当てないといけないのだが、全く同じようにしてやってみてもだめだった。
成果
- Ruby 1.8.7がなんとなく動く環境を手に入れた。
- 最新のOSにRuby 1.8.7を入れるのは難しい事を知った。rbenvを入れたほうが近道だったかも。
- 自分がDockerfileを雰囲気で書いていることを知れた。
おまけ
Ruby1.8のころはString#mapというのがあったことを知りました。
TypeScriptで関数のthisの型注釈をする
はじめに
vueを使ってTypeScriptに入門しているときに以下の問題にあたった。
forum.vuejs.org stackoverflow.com
そもそもthisの型注釈の機能を知らなかったので、公式ドキュメントを読みながらthisの型注釈についてインプットすることにした。
- 型注釈によって関数のthisの型を指定することができる
- thisの型注釈が必要なケース
型注釈によって関数のthisの型を指定することができる
以下のようなコードを考える。
class C1 { name: string; constructor(name: string) { this.name = name; } say() { console.log(this.name) } }
say
メソッドの中で呼ばれているthis
の型はthis
になり、C1
のサブクラスでも辻褄が合うような扱いになる。
ただし、以下のような形でthis
の型を明示することができる。
class C1 { // ... say(this: C1) { console.log(this.name) } }
C1
を指定した場合は挙動は問題なさそうだが、void
などを指定するとコンパイルエラーになる。
なぜこのような機能があるのか。
thisの型注釈が必要なケース
noImplicitThisを有効にしている場合に必要になることがある。 以下のようなコードを考える。
const execCallback = (fn: () => void) => { fn() } class C1 { name: string; constructor(name: string) { this.name = name; } say() { execCallback(function() { console.log(this.name) }) } }
say
メソッドの中で console.log(this.name)
を呼ぶ関数を execCallback
に渡しているが、関数式で定義した関数のthis
は実行時に決まるため、say
メソッド内で見ているthis
はany型になってしまう。結果としてnoImplicitThisに引っかかるのである。警告を外す方法としてはsay
メソッドの中のfunction() { ... }
をfunction(this: any) { ... }
とすれば警告を解除できるが、残念ながら実行時に落ちてしまう。。。結局 function
は使わず。アロー関数を使うのが今回の正解だ。
ただしアロー関数を使えないケースもある。「はじめに」の中で書いたvueのmethod内で _.debounce
を使う例がわかりやすい。(この例もアロー関数を使えるのかもしれない。)
vueのforumにもあるように、このケースは妥協してany
を使うのも良さそうだ。
まとめ
TypeScriptに入門していたところ早速本に出ていない内容が出てきたが、ちゃんとvueのforumやstackoverflow、そして何より公式ドキュメントにthisの型注釈について書いてあったのが良かった。
私の考えるスーパーエンジニア
はじめに
これはポエムです。自分が目指すエンジニアとはなんなのか向き合いたいと思い書いてみました。殴り書きです。
スーパーエンジニアの振る舞い
- スーパーエンジニアは誰よりも早くリリースができる。機能のヒアリング、要件定義、設計、開発などひっくるめて誰よりも早い。
- スーパーエンジニアはプロダクトを作るための技術を知っている。インフラ、DB、サーバサイド、フロントエンド、モバイルを、完全なできではないものの一通り一人で作ることができる。
- スーパーエンジニアはビジネスサイドの人間と会話できる。作りたいものを一緒に考えられる。
- スーパーエンジニアはネガティブでない。常に自分の力で状況を前に進められる。
- スーパーエンジニアは最新技術をキャッチアップしている。枯れた技術と最新技術の選定のバランスが良い。
- スーパーエンジニアは適切な設計ができる。場合によってそれなりな設計ができる。変な設計や必要以上に凝った設計をしない。
- スーパーエンジニアは体力がある。いざというときにハードワークできる。
- スーパーエンジニアは家族を大切にする。それによって自分が仕事に集中できる状況を作ることができる。
- スーパーエンジニアは人に仕事を任せることができる。人を信頼し、エンパワーし、適切なフィードバックを与える事ができる。
- スーパーエンジニアは問題解決をする。やり方は問わない。
参考
自分の尊敬するエンジニアの振る舞いを元に、以下の記事をみながら書きました。
まとめ
スーパーエンジニアになるため、1歩1歩進んでいきたい。
ブログ名変更&https対応した
内容
長らく迷っていたブログ名を「ITの勉強をいろいろやってみたブログ」から「blog.waterlow.work」に変更しました。
はじめは資格試験の勉強などをアウトプットしていく予定でしたが、2014年転職したりなんやかんやで方向性が変わりました。
それから長らく名前は放置していましたが、この度思い切って。
ブログ名はurlっぽいけど、叩いても何も出ません。
(https://waterlow.work/ は今はHetlifyでGatsbyをうごかしてます。)
ついでにurlをhttps化しました。混在コンテンツも全部https対応or削除しました。
最近いろいろもんもんとかんがえていることがあって、いろいろ吐き出していきたい。
今年触った技術
はじめに
もう10月末となり、今年触ってきた技術を列挙してみようと思います。
結論言うと、思った以上にいろいろ触ってきたものの、あんまり身になっている実感がないという感想。
基本的に趣味で、本番投入はしていません。
(普段のおしごとではrailsのサーバサイドを担当しています。)
インフラ編
docker, Kubernetes
railsをk8s化しました。特にこれといったことはありません。。。社内勉強会と自宅学習を合わせるとかなりの時間触っていると思う。
GitHub - waterlow/docker_sandbox_qdqgrstwtz
ミドルウェア編
opencv
名刺サービスに携わっていて、多少なりとも画像処理ができるようになりたいと思ったため。
docker向けにコンパイルするのがひたすら難しく、結局挫折してしまいました。。。
vpsのcentosでpython(flusk)画像の矩形を切り取るサーバーを書くところまで。
GitHub - waterlow/opencv-sandbox
mongo, spark
「ビッグデータを支える技術」の本の中でバックエンドとして扱われており、dotinstallをやってからsparkをさわりだけつかってみました
PAAS編
Netlify
技術書店で本を買っていろいろやってみました。かなり高機能。
NetlifyCMS、hosting、CIを試しました。
Firebase
主にfirestoreとfunctionを触っています。railsに続く自分の武器になる予定。予定。 firestoreの設計(というかNoSQL)にはRDBとまたちがった感覚があり、苦戦中。
AWS Lambda
cloud watch eventと合わせるとcronをサーバレスで実現できるということで、試してみた。 serverless frameworkでやろうとしたけど、functionだけ書いてcronは手で入れちゃっている。
ssh接続を許可するipリストの管理をするのにも使用。
slackからのwebhookを受けられるようにAPI Gatewayと連携している。
IFTTT
これは含めていいのかわからないけど、会社の勤怠を自動化するために、GPSで会社の出勤退勤をspreadsheetに記録するために使用。
Amazon Athena
友達にデータ分析を試してみたいと相談され、まず一番手軽なところからということで使ってみる。
都道府県ごとの郵便番号のデータをzipのままS3において、そこに対してSQLで集計をかけられるという体験はすごい。
後述のredashにも接続できる。
インストール系
redash
データ分析の文脈で、athenaのデータをビジュアライズ。docker化したい。
wordpress
友人の相談でメディアサイトを作りたいと言われ、ちょっとだけ触ってみる。
docker-composeで立ち上げられるようにしてみた。
webアプリとセッション共有をしたいと言われるも、php詳しくなく断念。。。
フロントエンド編
mobx
reactの状態管理のライブラリ。reduxよりもライトに使えるというか、ルールがきつくない。 reduxのサイトにあったtodoをmobx& firebaseで作ってみた。
vue
rebuild.fmのshownoteをフィルタリングするwebアプリをvue2系&webpackerで書き直した。
GitHub - waterlow/rebuild-search
nuxt
勉強中。firebaseと合わせてtwitterみたいなものを作っている。まだ理解できていない。
GitHub - waterlow/nuxt-sandbox
gatsby
Netlify文脈でさわってみた。とりあえずデプロイしてみた程度。
JAMStack
Javascript、API、Markupの略
SSRするHTMLを先に生成してCDNに乗せておけば、SSRより爆速になるという考え方。
技術的にはあまり触っていないものの技術書典の本は1冊読んだ。
ReactNative
WEBDBに載っていたお天気アプリをつくってみた。
(やったと言えるのか。。。)
まとめ
いろいろやりすぎ!!!と思った。
深掘りというか、ちゃんと手に馴染むところまで持っていけてないのが残念。
nuxt, firebase, redashあたりは手に馴染むところまで持っていきたい。