blog.waterlow.work

Ruby, Rails, js, etc...

Ruby1.8.7の動く環境を探す&構築する

久しぶりにるびまRubyコード添削回を読んでいて、コードを手元で動かしたくなった。

magazine.rubyist.net

Ruby3.2で動かしてみたところエラーになったり明らかに想定していない挙動になったりという感じで挙動を確かめられなかったので、当時の環境を再現してコードを動かしたくなった。

Rubyバージョンの特定

記事の初稿は2005年とある。「ruby 2005」と調べるとruby-lang.orgのニュースのアーカイブページが出てきた。

2005年のアーカイブ

2005/12にRuby 1.8.4がリリースされたようだ。ひとまずパッチバージョンまではこだわらないことにして(この頃のRubyだとこだわったほうがいいかもと言うのが一瞬頭をよぎったが)Ruby 1.8.7が動く環境を得ることを目標にした。

rbenvを用いたmacosへのインストール

(エラー内容をコピーするのを忘れたが)よくわからないエラーがでた。もともとmacのローカル環境でシステムライブラリをいじりたくはなかったので早々にmacローカルへのインストールはあきらめた。

dockerイメージを探す

次に思いついたのはdockerによる環境構築だ。しかしながらdockerの公式のイメージにRuby2.6以前のものは置いていない。
ぐぐってみたところ以下のようなdocker imageやDockerfileがヒットしたので動作をみてみることにする。

github.com github.com

okyada/dockerhub-ruby

github.com

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

github.com

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の型を指定することができる

Functions · TypeScript

以下のようなコードを考える。

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、サーバサイド、フロントエンド、モバイルを、完全なできではないものの一通り一人で作ることができる。
  • スーパーエンジニアはビジネスサイドの人間と会話できる。作りたいものを一緒に考えられる。
  • スーパーエンジニアはネガティブでない。常に自分の力で状況を前に進められる。
  • スーパーエンジニアは最新技術をキャッチアップしている。枯れた技術と最新技術の選定のバランスが良い。
  • スーパーエンジニアは適切な設計ができる。場合によってそれなりな設計ができる。変な設計や必要以上に凝った設計をしない。
  • スーパーエンジニアは体力がある。いざというときにハードワークできる。
  • スーパーエンジニアは家族を大切にする。それによって自分が仕事に集中できる状況を作ることができる。
  • スーパーエンジニアは人に仕事を任せることができる。人を信頼し、エンパワーし、適切なフィードバックを与える事ができる。
  • スーパーエンジニアは問題解決をする。やり方は問わない。

参考

自分の尊敬するエンジニアの振る舞いを元に、以下の記事をみながら書きました。

medium.com

soudai.hatenablog.com

まとめ

スーパーエンジニアになるため、1歩1歩進んでいきたい。

ブログ名変更&https対応した

内容

長らく迷っていたブログ名を「ITの勉強をいろいろやってみたブログ」から「blog.waterlow.work」に変更しました。
はじめは資格試験の勉強などをアウトプットしていく予定でしたが、2014年転職したりなんやかんやで方向性が変わりました。
それから長らく名前は放置していましたが、この度思い切って。 ブログ名はurlっぽいけど、叩いても何も出ません。

https://waterlow.work/ は今はHetlifyでGatsbyをうごかしてます。)

ついでにurlをhttps化しました。混在コンテンツも全部https対応or削除しました。

最近いろいろもんもんとかんがえていることがあって、いろいろ吐き出していきたい。

今年触った技術

はじめに

もう10月末となり、今年触ってきた技術を列挙してみようと思います。
結論言うと、思った以上にいろいろ触ってきたものの、あんまり身になっている実感がないという感想。
基本的に趣味で、本番投入はしていません。
(普段のおしごとではrailsのサーバサイドを担当しています。)

インフラ編

docker, Kubernetes

railsk8s化しました。特にこれといったことはありません。。。社内勉強会と自宅学習を合わせるとかなりの時間触っていると思う。

GitHub - waterlow/docker_sandbox_qdqgrstwtz

ミドルウェア

opencv

名刺サービスに携わっていて、多少なりとも画像処理ができるようになりたいと思ったため。
docker向けにコンパイルするのがひたすら難しく、結局挫折してしまいました。。。
vpscentospython(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は手で入れちゃっている。

GitHub - waterlow/cron-job

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で作ってみた。

GitHub - waterlow/mobx-todo

vue

rebuild.fmのshownoteをフィルタリングするwebアプリをvue2系&webpackerで書き直した。

GitHub - waterlow/rebuild-search

nuxt

勉強中。firebaseと合わせてtwitterみたいなものを作っている。まだ理解できていない。

GitHub - waterlow/nuxt-sandbox

gatsby

Netlify文脈でさわってみた。とりあえずデプロイしてみた程度。

JAMStack

JavascriptAPI、Markupの略
SSRするHTMLを先に生成してCDNに乗せておけば、SSRより爆速になるという考え方。
技術的にはあまり触っていないものの技術書典の本は1冊読んだ。

ReactNative

WEBDBに載っていたお天気アプリをつくってみた。
(やったと言えるのか。。。)

まとめ

いろいろやりすぎ!!!と思った。
深掘りというか、ちゃんと手に馴染むところまで持っていけてないのが残念。
nuxt, firebase, redashあたりは手に馴染むところまで持っていきたい。

OKR本を読んだ

はじめに

OKR(オーケーアール) シリコンバレー式で大胆な目標を達成する方法

OKR(オーケーアール) シリコンバレー式で大胆な目標を達成する方法

OKRの本を会社から支給されました。大事なことは原典を読んでいただくのが良いですが、気になったところを書いてみます。

スタートアップでもミッションを掲げるべき

どんなに夢のあるようなビジネスでも、マネタイズしなければ意味がないというのが自分の考えでした。しかし「お金がほしいなら、ウォール街コンサルティング企業に入社するほうが遥かに安全だ。」という言葉をみてなるほどとおもいました。マネタイズは大事だけど、同じくらいミッションというか使命みたいなものが大事だと思います。

自信度の変化のトラック

今の会社でもOKRを取り入れていますが、自信度の変化をトラックしていません。はじめは50%でも自信度は刻々と変化していくため、OKRを振り返るためにも自信度の変化は重要であると考えました。

健康、健全性

これは、「利益に走りすぎて、エンゲージメントを失う」とか「締切を守るあまり、メンテナンス性の低いコードをリリースしてしまう」といった状況への抑止になると感じました。KRを達成さえすればそれでいいというような状況はなくなりそうです。

まとめ

OKRについて、まだまだ知らないことがあるなということと、これを遂行するにはメンバーのメンタリティも重要のように思いました。 あと、これとは別に「仕事はたのしいかね?」という本も読んでいてうーーーんという感じでした。

そもそもRailsでカスタム例外を定義すべき機会は少ない

はじめに

今仕事でRailsアプリケーションの運用をやっているのですが、いろいろなところで例外が定義されていて「これ必要なくね…」となんとなく思ったことが多々ありました。 しかし、effective rubyには「raiseにはただの文字列ではなくカスタム例外を渡そう」という章もあり、この違いはなんだろうと思いました。 なんでそう思ったのか整理して、今後自分のプログラミングに生かして行こうと思います。まとめると以下になります。

  • カスタム例外を自分でraiseしてrescueするな。戻り値で判断しろ。

よく見るコード

Resourceモデル

class Resource
  Error = Class.new(StandardError)
  def write
    # 何かの処理
    result = false # 何かの処理の結果falseだったと仮定
    raise Error, '保存時にエラーが発生しました。'
  end
end

Resourcesコントローラ

class ResourcesController < ApplicationController
  def create
    Resource.new.write
    redirect_to '/', flash: { notice: '作成されました' }
  rescue Resource::Error => e
    redirect_to '/', flash: { error: e.message }
  end
end

よく見るコードがあまり良くない理由

汎用性も可読性も低い。一般的でもないということですね…。

どうすればいいか

Resourceモデル

class Resource
  def write
    # 何かの処理
    false # 何かの処理の結果falseだったと仮定
  end
end

Resourcesコントローラ

class ResourcesController < ApplicationController
  def create
    if Resource.new.write
      redirect_to '/', flash: { notice: '作成されました' }
    else
      redirect_to '/', flash: { error: '作成されませんでした' }
    end
  end
end

カスタム例外は必要なくなりましたし、表示用のメッセージがモデルに縛られなくなりました。

結局カスタム例外は必要ないの?

必要ないとは言いませんが、単体のRailsアプリケーションを書いている場合、自分でraiseしようとしている例外はそもそもシステムエラーではなく業務エラー(日常的におこりうる)であることが多いように思いました。 もしそれがシステムエラーならば、rescueして握りつぶしては検知できないですし、そうなるとrescueしないんだからカスタム例外ではなくてもいいよねという話になると思い、最終的に独自例外いらないよねということになるんじゃないかなと思います。。。

gemなど不特定多数の人が使うものに関しては積極的に定義していくべきだと思います。gemから返ってくる例外がRuntimeErrorだとつらいですしね。

まとめ

やっぱりRailsでカスタム例外を定義すべき機会は少ないし、少なくとも自分はめったにやらないかなと思いました。