Ich lerne Ruby on Rails for Africa

Railsとアフリカで苦戦するブログ

「君は自分の人生を生きているか」

あんまり強い言葉を使うのは嫌なんだけども、30歳を迎え現実に対峙するにもパワーが必要になって来た今、現在考えていることをどうしても文章にしていないとこれから先に同じように自分に問いかけることを避けてしまいそうなので自分自身に問いかける意味も含めて文章にしておきたいと思う(こういうような言い訳を書かないとこういう文章を書けなくなってきたあたり老いてきたのでは、と思ったりもする)。

10歳、20歳の自分にきちんと説明ができるか

区切り自体はどこでもいいんだけども、小学生、中学生、高校生、大学生、大学院生、新社会人と年齢とともにいろんな環境に身を置いてきたし、その都度色々なことを学び色々なことを考えていたと思う。もちろん、今思うと「青臭いなー」とか「バカだったなー」と思うことはたくさんある。が、しかし知らないということは一つの力である、というのはやっぱり思う。で、5年、10年、20年前の自分ともし話ができるのなら、彼らに対して胸を張れるような選択が今できているだろうか。「遊べるのは学生のうちだから」なんてクソみたいなセリフを吐かないだろうか。彼らをワクワクさせるほど熱狂しているものはあるだろうか。

今の自分は楽をしていないだろうか

正直いって少し楽をしていると思う。本当にこれはダサい。今すぐ変えないといけないが、傾向として自分ができる範囲でなるべくことを済ませようとする。ある程度までは多分これで良い。でも、これだと自分の100%を超えない。新しいものを取り入れることを外部環境に任せてしまっている。必要に迫られることがあるなら・・・そうじゃない。本当にやらないといけないのは、集中する場所は決めるべきだが、積極的にいろんなことを取り入れないといけない。CTOという立場だと、どうしても自分がキャップ(上限)になる瞬間が来てしまうので、そこまでには自分がキャップにならないか、キャップになっても良いぐらいきちんと伸びてないといけない。掛け算が大事だ、とか言い訳を最近しがちだけども、掛け算する2要素あれば両方とも伸ばすことをサボって楽をしてはいけない。楽をせず、自分の伸びを楽しんで、それをチームや会社の伸びに転換するという視点を持つべきだと思う。自分で留めないからこそ得られるフィードバックや経験というのもあるはず。

40歳、50歳の自分が振り返っても恥ずかしくないか

どうなるかはわからないけど、10年、20年後には自分はもっともっとすごいやつになっていて欲しい。どういう物差しですごいやつかは正直わからない。でも、30歳の今の自分が羨むような生き方をしていて欲しい。そんな未来の自分が見て、現在サボっていないか、全力を出してなかったんじゃないか、視野が狭かったんじゃないか、と思わないような最善を尽くしたい。今の仕事はすごく楽しいし、特異な環境だし、今の選択だとベストだと思う。思うが故に、本当にベストなんだろうか、情報をシャットアウトしてるだけでは?ということをもしかしたら考えるべきかもしれない。

生きていることを忘れていないか

「生きていることを忘れていないか」

実は「生きている」というのがどういうことかは分からない。精神的な話。何年か前、目の前にある仕様書に沿って本当に世の中のためになるかも分からない、誰の幸せにつながっているのかも分からない、自分が熱狂できるわけでもないシステムを作っていた時は、多分「生きている」とは言えなかった気がする。適当に仕事をして、給料をもらって、友達と適当に飲み会をして・・・楽しかったけど、考えることから逃げて楽をしていたのだと思う。他の人がどうかは知らないが、少なくとも"今の"自分にとっては、誰の幸せを作ってるかも分からないシステムを作ることはもしかしたら良いことかもしれないけど、その状態は非常にカッコ悪いと思うし、本当に自分がやりたいことなの?熱狂してる?という問いを投げかけたいと思う。

常にかっこいい自分に

やっぱり年齢とともに体力的にも落ちてくるし、奥さんも子供もいるといわゆる守るべき存在というのもいるし、どうしても保守的な行動をとりがちになるし思考もそうなりがちだが、何歳になっても謎の万能感に包まれていた小学生高学年〜中学生の自分が憧れるような、60〜70歳だろうが死ぬ直前だろうが常に自分がカッコよく生きるために全力を尽くしてきたよな、と未来の自分が振り返れるように今を全力で生きたい。

30歳の自分は今。

25歳の年で社会に出たので多分社会人5年目。半年以上関わった会社でいうと正社員・業務委託で6社ぐらい。今は2015年7月からジョインしたアフリカインキュベーターという会社でCTOをしている。

「MAKE EVERYDAY PURCHASES CONVENIENT」

これを旗印にアフリカの流通にITでどうやって食い込んでいくか、僕らがやらなくてもいつか時代がアフリカを押し上げるとしても、僕らの会社がどれだけそれを加速させられるか、というところが面白いと思ってやっている。どうしてもBtoBを支える部分になるが、日本でやるよりももっと効果があるし、ワイヤレスからインターネットが始まる彼らの社会にどうやってフィットしたものを作るかというのは日本とは別の課題だ。ここら辺を本当に解決できた先にある社会の礎になるような商習慣を作る手助けになれば、流通の基礎を作られるなら、それはどれだけ素晴らしいことだろう。まぁ、しかしながら当たり前を作った人は感謝されない。でも、作ったと胸を張れるだけの適切な自意識があればいいんじゃないかな、とも思う。

あと、うちの会社に関わってくれてる人が大好きだ。社長はいわゆるスーパーエリートなんだけども、本当に賢くてぜってー追いつかねーって思ったりもするが人間的なとこも十二分にあったり、こういう人と仕事をできるというのは本当に幸せで、偶然だったし、2年前の自分にこのチャンスを逃さなかったのはGood Job!って親指を立ててやりたい。リモートでエンジニアしてくれてる人も、現地でゴリゴリ営業してる人も、限られた時間を使って現地にいったインターンの人たちも、本当に尊敬のできる人ばかりで幸せな環境に偶然身を置くことができてるんだな、と思うとやっぱりこの人たちに恩返しをしないといけないと思うし、できれば杉山と働いたこの時間は本当に価値があった、とか幸せだった、みたいに10年後に語れるようにしたいな、と思う。

綴ってみて思ったけど、今のところしんどいこともあるが全体評価としてはすごく楽しいが、少し楽してる部分もあるので、10年後の自分に「あの時の自分はダメだったな〜」なんて語らせないように頑張ろうと思う。と、書き始めると無限に続くので、先の謎の表明で終わることにする。

OS X El Capitanでrailsを再インストールしようとしたらeventmachineでエラーが出て原因がopensslっぽい

rbenv install 2.1.8
bundle install

みたいな感じで進めてたら

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

(中略)

compiling binder.cpp
In file included from binder.cpp:20:
./project.h:116:10: fatal error: 'openssl/ssl.h' file not found
#include <openssl/ssl.h>
         ^
1 error generated.
make: *** [binder.o] Error 1

make failed, exit code 2

(中略)

An error occurred while installing eventmachine (1.0.8), and Bundler cannot continue.
Make sure that `gem install eventmachine -v '1.0.8'` succeeds before bundling.


こんな感じのエラーが出て、何やらopensslがダメらしい。

> El CapitanではOpenSSLヘッダが提供されなくなっている

という話が合って何やらこれが原因らしい。

qiita.com

opensslからlibresslに乗り換えようかな、と思って乗り換えてみたけど、あんまり問題としては解決しない。

export PATH=/usr/local/opt/openssl/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/opt/openssl/lib:$LD_LIBRARY_PATH
export CPATH=/usr/local/opt/openssl/include:$LD_LIBRARY_PATH

qiita.com



結局のところ、.bach_profileに上記のPATHを通すことでなんとか動くようになりました!
あー、かれこれ5-6時間詰まってた気がする。

DateRangePickerでRangeでなく単日、時間を選べるようにするときのオプションメモ

  $(selector).daterangepicker(
    "singleDatePicker": true,
    "timePicker": true,
    "timePickerIncrement": 5,
    "autoUpdateInput": false,
    locale: {
      format: 'MMMM D, YYYY HH:mm'
    },
    (datetime) ->
      $(selector).val(datetime.format('MMMM D, YYYY HH:mm'))
  )

空欄も許可するような場合には、autoUpdateInputをfalseにしておかないといけないが、falseにするとカレンダーを表示してApplyを押しても反映されないので、callback部分でセットするようにした。

今回ここで引っかかったのは、フォーマットを結構変えているので、フォームに事前にvalueがセットされている場合にdaterangepickerでセットしているformatに従わない場合、「Invalid date」みたいな感じになるので、

dateTimePicker = (selector) ->
  unless $(selector).val() == ''
    datetime = moment($(selector).val()).format('MMMM D, YYYY HH:mm')
    $(selector).val(datetime)

  $(selector).daterangepicker(
    "singleDatePicker": true,
    "timePicker": true,
    "timePickerIncrement": 5,
    "autoUpdateInput": false,
    locale: {
      format: 'MMMM D, YYYY HH:mm'
    },
    (datetime) ->
      $(selector).val(datetime.format('MMMM D, YYYY HH:mm'))
  )

こんな感じにしておいた。
こういう感じにしておくと、1ページに複数のカレンダーUIが必要になっても、dateTimePickerに突っ込んでOKになるので割と便利。

Railsでmigrationする時にundefined method `to_sym'

出たエラーはこんな感じ

NoMethodError: undefined method `to_sym' for {:default=>true, :null=>false}:Hash

migrationはこうしているだけ。defaultをfalseからtrueにするだけ。

  def up
    change_column :questions, :enabled, default: true, null: false
  end
||<    

と思ったけど、ただのケアレスミスで、:booleanって書くの忘れてただけだった。

>||
  def up
    change_column :questions, :enabled, :boolean, default: false, null: false
  end


change_column_defaultを使えば良いケースだ。
change_column - リファレンス - - Railsドキュメント

MySQLでNOT NULLからNULL許可する時

MySQLでNOT NULLからNULL許可する時のALTER文。

ALTER TABLE `table_name` MODIFY `column_name` varchar(255); <<<

めっちゃでかいリリース(の作業)が終わった

昨年のこの時期もリリース前でバタバタしていた。この1年で結構でかい新規機能投入を含むリリースを少なくとも6回はしている。それでも、まだまだ機能が足りない、ここがバグがある、通信が遅い、データの同期の問題がある、などなど仕方ないものも含め、お客さんに提供は出来ているものの、僕ら自身が目指す世界を実現するためにはソフトウェアとしてまだまだだった。

さっき、ここ1年の中で一番大きいリリースを終えたばかり。日本は夜中の2時だけど、アフリカだと20時頃。ログは全く動いてなかったし、日本とは違って土曜の夜にもなると業務アプリケーションいじってる人は誰もいないんだなーとか思いながら、Enterを押して、アプリケーションのデプロイにDBのmigrationを走らせて、必要なrakeタスクも実行してデプロイ完了。

今回のリリースは、ホントにハードだった。事の発端は4-5月ぐらいで、結構なハイペースでリリースを繰り返していたがアフリカの通信の状況、現地スタッフのアプリケーションの想定のしない使い方、通信が遅過ぎてどうにもならないとか、ソフトウェアとして限界を迎えようとしていた。毎日起こる問題にデバッグをして再現性を見つけて潰しては、また新たなissueが発見される・・・。1年弱走り続けて負債もたくさんあるし、継ぎ接ぎで作って来たアプリケーションなので仕方ないと言ってはいけないのかもしれないが、仕方ないことだと思ったし、いつかどうにかしないといけないけども日に日に積まれていく新機能の提案に対して立ち止まって負債を返済するなんてなかなか意思決定はできなかった。

5月に入ったぐらいかな。代表と話していて、結局ソフトウェア的にはゼロから再度開発をして、必要であればDBや通信を扱うライブラリごと変えてしまうぐらいのことが必要だと思う、という話をして、一旦新規機能の開発や営業を止めてもらって、ゼロから開発し直すことになった。本当に、あのタイミングで良かったと思うし、代表の胆力を見た気がした。カッコいいよね。

そこから、データの同期のアルゴリズムを試行したり、DBのライブラリとの相性を試したりと色々しながらまた新機能も載せながら、かれこれ3-4ヶ月もかかってしまったけど良い物が出来たと思う。ホント、みんなありがとう。Web側も、今回ので色々な機能が乗っかったし、複雑さも増したけども、テストもある程度書けるようになってきたし、それによる恩恵も受け始めてるので、完璧であることは求めないけども、勘所は押さえつつ開発を進めていけたら良いなぁ。とはいえ、やや開発者としてレベルアップが求められている感じがしているので、色んなことを吸収して組織に戻して、さらにそれを共有してとSECIモデルを良い感じに回して行きたいよね。

「あのタイミングでの意思決定で良かった!」と言えるようにするには、ソフトウェアだけではないけども、そう言えるだけの材料は揃ったと思うので、ここからはエンジニアも含めてどんどんと事業を進めていって、ふと後ろを振り返った時にそう言えるだけの結果を出せるように頑張っていこう。

Develop the future of Africa with technology and strategic management

あふりか童貞エンジニア、あふりかに行く。

アフリカインキュベーターにジョインしてから1年ちょっと。今更ながら、アフリカに2週間行ってきました。もともと事業を始めたウガンダカンパラと今年に入ってオフィスを開いたケニアのナイロビにそれぞれ1週間ずつでした。

ずっとリモートで日本からソフトウェアの開発をしているので、どうしてもお客さんの顔も見えないし、どういう人がどういう風に触ってどういう風に使っているかというのも、現地にいるメンバーから聞くというふうになってしまうのでなかなか意図を掴みきれなかったり難しいことがありました(とは言っても、現地にいるメンバーが優秀なので助かってます)。というのもあって、今回アフリカに行くことになりました。後、「お前は本当にアフリカで使われるソフトウェアを愛せるのか」という副題もありました(これはまた別記事で書こう)。

カタール航空で成田からドーハ経由でナイロビ(ケニア)までだいたい丸1日(24時間弱)かけて行きました。早いと18時間ぐらいなんですけどね。この辺は、航空券の安さと乗り換えのスムーズさによるところではあります。日程的には、初めにナイロビに入って1週間。その後、LCCウガンダカンパラに移動して1週間の合計2週間です。

初めの1週間はナイロビで代表とお客さんとこ回ったりミーティングに参加したりしてました。ナイロビではアプリを使う現場の人とは会えなかったのですが、マネージャーの人や経営者の方と会ってどういうところに課題があるかとかどういうことを期待してるかなどを聞けて良かったです。

僕の移動していた範囲がそうなんだとは思いますが、道路も綺麗だしビルも結構あるし、建設中の建物とかもたくさんあってすごく伸びてるんだなーという感じがしました。その一方で、やっぱり裏道に入ったりするとちょっと危険そうな感じがするし、まだまだ貧富の差とかも結構あるんだなって思いました。やはり、ナイロビは危険らしく基本的にUberで移動してました。めっちゃ便利!でも、地図読めないのかだいたい電話して「○○センターの前だよ」とか教えないといけないのはめんどくさい。

ケニアでのご飯は、代表含む現地メンバーが良しとするレストランは全部美味しかったし高くないし、オフィス兼住居での自炊をしてたこともあって全然困りませんでした。大きいスーパーとかに行くとアジアンなコーナーもあるし、ある程度お金さえ出せば生活でストレスを感じることなく生きていけそうだなって思いました。ただ、街中の渋滞だけは勘弁してほしいけど、これは他の国でも同じように抱えている問題だろうしどうしようもないのかなーって感じでした。

着いてから1週間後にナイロビからウガンダカンパラへ移動。
ウガンダの方にはだいたい5人ぐらいのメンバーが居て、あとウガンダ人スタッフが2人。1年間で大きくなったなーという謎の感動をしてました。ウガンダでも、お客さんのとこに同行して話を聞いたりしてたんですが、こちらもマネージャーとかも居たんですが、最終日には実際にアプリ使ってるユーザー(営業スタッフ)と話せる機会があったので大きな収穫。ウガンダで話を聞いててびっくりしたのが、結構な頻度で従業員が入れ替わること。僕らのアプリを使ってもらうために導入の時とかはスタッフが行って使い方とかを教えたりしてるんですが、それを受けた従業員がいなくなったり、営業スタッフが上手くアプリを使ってくれるように面倒を見てくれてたリーダー、マネージャーのような人が居なくなったり・・・とこういうことが結構起こったりするので、より簡単でより使いやすいものを作ることがかなり求められているよなーとより実感しました。当たり前でしょ!と思われるかもしれないですが、スマホというものに初めて出会うような人も結構まだいるそうなので、スマホ慣れしたユーザーでない人にも直観的に使えるようにしないといけないので、これは結構難しいし課題かなーと思います。

あとね、すごく難しいなーって思うのが、徐々にスマホが広がりつつあるも、あんまり良いモデルじゃないとバッテリーが持たない、とか自分でインターネットを100MBとかの単位で購入してたり、インターネットが激おそだったり、そもそも入らなかったり、GPSが精度悪かったり、もーーーーアプリケーションに行く前に色んな課題は山積みだったりします。なので、カスタマーサポートとかでも「えー?そんな質問まで来るんですか笑」みたいなのもあるけど、それも丸っと仕方ないけどそれを包容してなお使いやすいようなものを作れたら最強じゃない?なんて思ったりします。


ウガンダでは、夜はUberを使うけど、昼はだいたいボダ(ボダボダ?)というバイクタクシーを使ってました。ナイロビよりも車移動すると渋滞にひっかかるので、バイクだとその隙間をすいすいすいーっと行ってくれるので結構楽でした。ただ、事故ったら死ぬよなみたいなスピードを出してくれるのでたまにちょっと怖くなりますw料金は結構安いけど、自分で交渉しないといけないのでそこら辺はちょっと面倒だしどうしても外国人なので高めに言われたりするっぽいです(多分)。


この2週間色んなお客さんのとこ行ったり、こっちで人を見たりしてて思ったのは、ウガンダとかケニア特有の問題と途上国特有の問題とがあるのかもなーと思いました。後者の方は、昔の日本だったり他の国でもあるような組織の問題とか雇用の問題とかに結びついてるのかもなーと思っているのでここら辺は時間のある時に調べたりしていきたい。

Anyway, 僕らの作ってる物がいきなり必ずまるごとフィットするわけでもないし、会社によってはコストとして高いのかもしれないけど、この地域で、国で、恐らく必要とされてるもの(シーズもニーズも)を作っているし、少しずつそこに向かっていってるんだろうな、とすごく感じた。このソフトウェアをしっかりと良い物にして、まずは期待してくれてるお客さんを満足させて、口コミで良かったよ、というのが広まるぐらいにしたいな、と思うし出来そうなイメージは出来る。ふたつの国をまたいでいるというだけでもしんどいし、これからどんどんと国の中でも地域にも広がっていったりして僕らはより大変になるけど、それでも売りたい、と思ってもらえる物を作りたいし作れる組織を作るのが僕の仕事だし、その上で色んな人から使いたい、と思ってもらえるものを考えられる、作れる、届けられる、組織にしたいな、と思った。

今回はすごく短かったし、全然現地のことも分からないままにうろうろして、そこまでローカルに染まれずに帰ってしまうぐらい薄い滞在っぽいけども、得たものとしては、未だ小さな物かもしれないけどこれから少しずつ大きくなっていきそうな感じ。法人化して1年、色々がむしゃらに進んで来た1年だしこれからもそうかもしれないけど、後ろを振り返るとしっかり道は出来てるし、これから進めそうな道もうっすらとではありますが見えて来てる感じはします。とはいえ、今のメンバーだけではすぐに限界が来ると思いますので色んな人に頼ってお願いして、一緒に何かできたら良いな、と思ってますので僕から助けを求められたらスッと助けてくれると非常に嬉しいし、限られたリソースかもしんないけど「何かやろうか?」なんて声を掛けてくれると感謝感謝です。僕の会員権使って美味い肉を個室とか割安で行きましょう(僕が行きたいだけなんですが)

刺激的で最高に楽しい滞在の1割も書けてない気はしますが、ここで発散しておかないとこの感覚は薄まっていくので、一旦これで。

とりあえず、これからのAfri-incに乞うご期待ということでより一層励んでいきますので、どうぞよろしくお願いします₍⁽⁽(ી(*´ω`*)ʃ)₎₎⁾⁾