| @技術/プログラミング

自戒エントリー。

自分は Mongoid を使って開発してるんですけど、時間の境界値のテストが不十分で問題に遭遇したのでメモっておきます。

Mongoid には Date 型や DateTime 型があるけど、データベースにデータを保存するときには Time 型に変換されます(MongoDB に Date とか DateTime がないから?)。Mongo Shell で DB の中の値を見ると Time 型の値が入ってる。

だからクエリを生成するときに Date.today はなるべく使わない方がいい。Date.today では時間を 00:00:00 として扱い、月末のデータの取得に失敗する可能性が高いから。Rails console で確認すると、以下のようになります。

pry(1.9.3-p194)> 1.month.ago.end_of_month
# => Fri, 31 Aug 2012 23:59:59 JST +09:00
pry(1.9.3-p194)> Date.today.prev_month.end_of_month.to_time
# => 2012-08-31 00:00:00 +0900

上記は二つとも「先月末の月の終わり」を検索していますが、後者では時間が 00:00:00 になっています。例えば以下のような Mongoid でのクエリでは、8月31日の午前0時0分1秒以降に作成された Document を取得することが出来ません。ナンテコッタイ!!!

Model.where(:created_at.lte => Date.today.prev_month.end_of_month)

Date.today を時刻の生成の起点にしたとしても、to_time してあげればいいのでは?」と思う方もいるでしょう。確認してみましょう。

pry(1.9.3-p194)> Date.today.prev_month.end_of_month.to_datetime
# => Fri, 31 Aug 2012 00:00:00 +0000

#prev_month メソッドが呼び出された時点のオブジェクトの型は Date 型なので、Date 型に対して時間の操作を行って最後に DateTime 型に

結論

時刻まで考慮した時間の範囲でクエリを作るときは以下に留意すると良いでしょう。

  • Date.today は使わない
  • DateTime.now1.month.ago などを使う

| @技術/プログラミング

今年の3月くらいから、寿限無の和田さんが発起人になって Fukuoka.rb という勉強会をやってる。毎週木曜の 19:30 からで、ペ社は会場を提供している。勉強会と言ってもやってることは技術書の輪読で、最初は『メタプログラミング Ruby』を読んだ。メタプログラミング Ruby は中級者以上向けの本でなかなかレベルが高く、当初は 30人ちかくいた参加者が回を重ねるごとに減っていき、最後は5, 6人くらいしか参加者がいなかったけれども、歯を食いしばって出席し続けた。簡潔に書ける、美しいコードが書ける、という以上のことができる Ruby の側面を学んだと思う。いまは二冊目の課題図書として洋書の『Eloquent Ruby』を読んでいる。

福岡でやってる Ruby の勉強会、何回か出たことあるけど、Rails ハンズオンみたいな初心者向けの内容だったり技術より精神面を重視した内容だったりで個人的には消化不良な感じがあった。また開催が不定期で、プログラマ同士の情報交換がしにくいと感じていた。

Fukuoka.rb は原則的に毎週開催で、扱う内容も初心者よりというよりは中上級者向けで、本を読みながら喧々諤々とした議論も繰り広げられるし、自分はあまり参加しないのだけど勉強会の後はみんなで飲みに行ったりもする。業務で感じていた疑問を詳しい人に尋ねたり情報交換しやすい。

個人的には、中学生の頃に通っていた隣町の塾を思い出す。自分は田舎に住んでいたので、都会の塾に行くだけでレベルの高さに驚くとともに刺激を受けて、都会っ子に追いつこうと勉強を頑張った。Fukuoka.rb は参加者のレベルが高く、なかなかついて行くのが大変なのだけど、確実に Ruby 力が高まっていると思うし、出てて良かったと感じる。

Asakusa.rb や Yokohama.rb のような Ruby コミュニティをずっとうらやましく思っていたけど、これらに近い Ruby コミュニティが福岡にできつつあると思う。時々は Ruby コミッターの @nagachika さんも参加している。福岡在住の Ruby プログラマで腕に覚えがある人は、是非毎週木曜日に天神プライムビル8階で開催されている Fukuoka.rb にお越しください。面白くしていきましょう。

| @労働

hsbt さんが会社に入ってから大きく雰囲気変わった。hsbt さんは並の寿司を上にぎりとかにランクアップするパワーがあると思う。IRC とか Ustream ごしにその存在感を感じる。こういう人がメンターだなんて今年ペ社に入った新卒エンジニアはとてつもなくラッキーだったと思う。世の中には訳のわからない Java の研修を延々受けさせられてる新卒 SE さんもいるのに、ペ社の新卒エンジニアは WEB+DB PRESS に寄稿するような人から最新シャレオツ Rails 開発事情をたたき込まれたのだ。下手をすると中途で入って実サービスに投入されてる経歴不詳の怪しい30過ぎのおっさんよりも良いコーディングマナーを身につけているかもしれない。新卒エンジニア氏一名が自分の部署に配属されることになったので、来月自分は戦力外通告を受けて気がついたらハローワークに日参しているかもしれない。

なんか hsbt さんばかり持ち上げてしまったけど antipop さんも Webistrano をさくっと Rails 3.2.5 で動くようにしたりとかすごい。技術力ある人は技術力に比例して行動力が高い気がする。やらなきゃと思ったこと、読まなきゃと思った技術書を一晩とかでさくっと実装・読破してしまう。そういうところが並のエンジニアと大きく異なる点だと思う。

| @技術/プログラミング

あるモデルがあって、#save が実行されたときに同一モデル内で複製したインスタンスも一緒に保存したかった。一個目の #save が走る前にコールバックメソッドを使って複製したインスタンスを保存するようにした。コードだと以下のような感じ。

class Model
  before_validation :method_one
  before_create :method_two

  def method_one
    ...
  end

  def mothod_two
    Model.reset_callbacks(:validation)
    Model.reset_callbacks(:create)

    @model = Model.new
    @model.save
  end
end

なんで reset_callbacks 呼んでるのかというと二回コールバックメソッドを走らせないため。一回目の #save (コントローラーから呼ばれる)が呼ばれたときだけコールバックメソッドを実行して、二回目の #save (モデルのコールバックメソッド内で呼ばれる)では実行したくないから。

しかしここではまってしまった。なんとコールバックメソッドで複製したドキュメントを DB 内で確認すると created_at が空になっている。なんじゃこりゃ。

どうも reset_callbacks(:create) がいかんかったみたい。ORM が実行する create 周辺のコールバックメソッドも軒並みリセットされてしまう模様。

そういうわけで以下の様にして解決した。

class Model
  before_validation :method_one
  before_create :method_two

  def method_one
    ...
  end

  def hoge
    Model.skip_callback :create, :before, :sell
    Model.skip_callback :create, :after, :send_notification
    Model.reset_callbacks(:validation)

    @model = Model.new
    @model.save
  end
end

callback、便利だけど奥が深い。ちなみにこれら skipp_callback とか reset_callbacks とかは ActiveModel や ActiveRecord (僕はMongoidで開発してます)などの OR マッパーのメソッドではなく、 ActiveSupport::Callbacks のメソッドだったりします。ActiveSupport も奥が深い。

| @技術/プログラミング

Unicorn の設定をミスって(たと思ってけど実はそうじゃなかった)ポータルシットが12月の半ば頃から死んだままになってた。きっかけは Capistrano の導入で、仕事で Capistrano 使っていて大変便利なので、これをポータルシットでも使おうとした。

Unicorn で便利なのが、 kill -USR2 `cat tmp/pids/unicorn.pid` とかやることで、ダウンタイム無しに Rails アプリケーションを再起動できるとこだ。これを Sinatra 製の Lokka でも実現したかった。Capistrano と併せて運用することで、サーバーに SSH で接続せずとも

$ bundle exec cap deploy:restart

とかで Lokka を再起動できるようになる。

これまで Lokka の database.yml に DB への接続情報をべた書きしていたのをやめ、起動時にはシェルで以下のコマンドを実行するようにした。

$ env DATABASE_URL=path/to/db bundle exec unicorn -c config/unicorn.rb -D -E production

Capistrano の deploy.rb に書くと以下のようになる。

namespace :deploy do
  task :start do
    run "cd #{current_path}; env DATABASE_URL=#{db_path} bundle exec unicorn -c config/unicorn.rb -D -E production"
  end
end

| @技術/プログラミング

Railsで画面を作っていて、DBを参照せずにselect -> option なHTML(ドロップダウンリスト)を出力したいと思った。DBに入ってない値をドロップダウンリストとして表示する方法。ググったらこういうやり方がヒットした。

このやりが方がかっちょいいのかバッドノウハウなのか判別つかないけど、モデルに定数を書いてそこにいろいろ入れてしまうらしい。以下のような感じ。

class Event < ActiveRecord::Base
  DAYS = ['Monday', 'Tuesday', 'Wednesday', ...]
end

でこれをモデルから参照するときは以下のようにする。

<%= select(:event, :day, Event::DAYS) %>

これでうまいことドロップダウンリストを表示できる。

ところが一点問題があって、このドロップダウンリストで表示したい値が "(ダブルクオーテーション)を含んでいたとする。ダブルクオーテーションはRailsによって自動的にエスケープ処理されてしまうので、 " と表示させたいのに &quot; とか表示されてしまう。Form系のヘルパーメソッドで text_area_tag なら :escape => false とか出来るんだけど、select でそれをやるのは不可能だった。

Railsで文字列のエスケープをせずに出力する方法は一般的に

<%= raw("文字列") %>

とか

<%= "文字列".html_safe %>

だけど、「まさかそれをモデルの中でやっちゃってもエラー出るよね?」と思いながらやってみたらちゃんとエスケープせずにHTMLを出力できた。

モデルクラスのなかにヘルパーメソッドを書くのは気持ち悪いと思うけど、それ以外ではビューの中でイテレータを書いて一個一個エスケープしない処理を書くか、独自のヘルパーメソッドを書くしかない。なんかまどろっこしい気がするのでとりあえずこのやり方で行ってみることにします。

| @労働

荒れた砂浜

いまの会社は労働環境よいんだけど、前働いていた会社がとてもつらかった。どのくらいつらかったかというと、もう辞めてしばらく経つのに、いまだに前の会社にいたころの夢を見てうなされて夜中に目が覚めるくらいつらかった。ある意味トラウマになってしまっている。

つらかった頃のことをここに書いても意味がないことは分かっているし、ネガティブな感情をインターネット上に発露するのは個人的な信条に反するんだけど、セルフヒーリングのために前勤めていた会社のことを書いてみる。

無限サービス残業

  • 22時に帰るときも日報に「本日私用のためお先に失礼します」と書かなきゃいけない雰囲気だった。
  • 「23時に佐川が来るので申し訳ありませんがお先に失礼します」と日報に書いてる女の子とかいた。
  • 社長が「震災のおかげで仕事が減って早く帰れてうれしい、とか言ってるやつは許さない」とか言ってた。
  • みんなサービス残業してるので会社の飲み会に開始時間通りに現れる人はほとんどいなかった。
  • 週末だからと会社のメンバーで飲みに行くなんてことはなく、金曜の夜は2時くらいまで仕事するのが普通だった。

前の会社でまずつらかったのが労働時間の長さだった。もちろん残業代は出ない。完全に違法なんだけど、雇用主と労働者が対立する時代は終わったとか、不満があるなら辞めろとかいうような内容のメールを総務担当者が月に一回くらい送ってよこしていた。自分は弱いから会社に待遇を改善するよう申し出ることなんてできず、短期間働いて辞めることであの環境から脱した。

軍隊っぽさ

  • 上長にメールを送るときには宛名に「様」とつけなければならなかった。
  • 毎晩2時まで働いてたせいで心身を病んだ人が二人いたけど、二人とも「体調管理は自己責任」といって休職中に辞めさせられてた。ちなみに休職中に辞めさせるのは労働基準法違反らしい。
  • 細かく職位が分かれていて社内に軍隊のような階級制度があった。職位によって届くメールやグループウェア上で閲覧することのできるファイルが細かく分かれていた。たとえば上長の書いた日報は部下は読むことができなかった。

全体的に戦時中の日本みたいな会社だった(「欲しがりません 勝つまでは」的な感じ)。ライバルに勝つため・家族を守るために自分を犠牲にしろとか、そんな感じのことを経営陣が言ってた。

職位ごとに権限が異なっていて閲覧可能なファイルに違いがあるのはよその会社でも普通にやってると思うけど、それが露骨かつ過剰に行われている感じだった。Active Directory が Windows Server の外にもやってきて従業員をコントロールしている感じだった。

離職率の高さ

  • 入社してから二ヶ月以内に辞める人が多かった。いわゆるバックレも多かった。
  • 入社一年も経ってないのに入社時期で降順ソートしたとき真ん中くらいになってた。

自分の歓迎会開いてもらったときにすでに入社してから半年経ってた。すぐ辞める人が多いので新人の歓迎会とかはなかなか開いてもらえない。なんか先月入った人最近見かけないなー、と思ったらいつの間にか辞めてたということが日常茶飯事だった。

待遇の悪さ

  • 試用期間の二ヶ月間は各種保険に加入させてもらえなかった。
  • 内定の時に伝えられた年俸と全然違う給料だった。

全体的に、社長に気に入られないと昇級も出世も望めなかった。まぁどこの会社でも多かれ少なかれそうなのかもしれないけど、給与の等級表とかなかったし、どうすればどのくらいの給料をもらえるというような明確な指標がなかった。

労働基準監督署に届けてある就業規則はあるにはあったけど、偉い人の机の前にあって簡単に読める雰囲気じゃなかったし、そんなことしてる暇あったら仕事しろと注意される感じだった。ボーナスが支払われるのはいつか、基準額はいくらなのか、など労働契約に関する諸々のことを知らされない状態で働いていた。

技術力よりも人間力

  • 技術について熱っぽく語るとめんどくさいやつみたいな扱いを受けた。
  • 出世するにはエンジニアをやめてプロジェクトマネージャーにならないといけなかった。
  • テストコードとかなかった。テストは全部手動だった。
  • 勤務時間のうちコード書いてたのは25%くらい。あとは全部ドキュメント作成だった。

これらの開発カルチャーに加えて、会社が依拠する技術が Microsoft や Adobe などプロプライエタリなものが中心であり、UNIX/Linux 系の開発が好きな自分には大変つらかった。Capistrano とか使えば20秒くらいで終わりそうなことを手動・目視確認で行っていて、技術面のアナクロニズムに耐えられなかった。

インターネットのことを好きな人がいなかったのも辛かった。はてなとか誰も見てなかったし、 Twitter アカウントはみんな隠してた。そもそも Twitter よりも Facebook な感じだった。ソーシャルネットワークはプロモーションのツールとしてしか認知されていなかった。Twitter なんて技術的には大したことない、が社長の口癖だった。エンジニアも誰も GitHub とか使ってなかった。

不用意に転職したのが間違いだった

一番の間違いは、Web制作の会社に入ってしまったことだと思う。Twitter で見かける楽しそうに仕事してる人たちはだいたいみんなWeb系のベンチャー企業とかで働いてた。制作会社とWeb系ベンチャーでは全然雰囲気が違うと思う。制作会社にはクライアントがあり、その人たちの言うことは絶対だから、アホみたいなリクエストにも全力で答えなければならない。

Aという企業があってその会社のユーザーのためのサイトをWeb制作会社が作っているとする。すると要求の流れが以下のようになる。

A社製品のユーザー -> A社(顧客) -> 営業担当 -> プロジェクトマネージャー -> エンジニア・デザイナー

エンジニア・デザイナーはこのサイトの制作に携わるプレーヤーの中で最下層にある。顧客の要望を営業担当が聞いてきて、それをプロジェクトマネージャーが伝え聞き、エンジニアとデザイナーに指示を出す。このメカニズムのなかで軍隊的な階級構造ができる上がるのではないかと感じる。良くない仕組みだと思う。

近況

前の会社には一年近くいたけど、何か身についたかと問われると何も身についてない。自分の人生の中で最低最悪の暗黒時代だった。がんで入院していた頃の方がまだ良かったような感じさえする。

この記事のような愚痴というか後悔の塊みたいな文章をネットにのっけても何の得にもならないんだけど、職探しは本当に真剣にやった方がいいと身をもって思った。確かに結局のところ会社に入るまでその会社が自分に合っているのかどうかはわからない。しかしだからといって適当に就職活動して就職するとものすごく後悔することになる。時間がかかってもいいから就職・転職先はじっくり見極めてから決めた方がいいと思う。

実は前の会社に入って二ヶ月経たないくらいのときに、入った会社を間違ったと思って転職活動を行った。在福岡の良さそうなベンチャー企業を見つけたので面接を受けに行った。技術的には面白そうなことやってそうだったが、外に向かって社内のことを明らかにしていない会社で、中のことが全然わからなかった。なので結局内定を辞退した。面白そうだけど社員のブログやTwitterが読めないとなるとものすごく不安になる。

ペパボに入ったのは、アラタナ研究所所長の rytich さんのかつての職場で、rytich さんに声かけてもらってペパボの人と一回酒飲んだことあったし、かぶりものの社長とか創業者の家入さんとか何となく知ってて安心感があったから。とはいえどんなことやってるかよくわかんなくて不安がないわけじゃなかった。そういうよくわかんなさを吹き飛ばしてくれたのは刺身☆ブーメランさんのブログだった。

これ読んで「あ、なんか大丈夫そう」と思ったから面接受けに行った。

刺身さんにはペパボに入ってからもRailsのこととか教えてもらって世話になってるけど、あの記事読まなかったらペパボ受けようと思わなかったかもしれないと思うと何とも言いようのない感謝の念がわいてくる。ありがとうございます。もちろん rytich さんも、もうペパボ退職されたけど taketin さんもありがとうございます。

雑然とした感じの日記になったけど、自分はいま楽しく働いてます。

追記 2019/05/13