assert_validが欲しい

捨てる予定だったRails2.3プロジェクトをRails5まで上げることになり、 今Rails3でtest-unitとtest-unit-railsを使ってテストを書いています。 そして、test-unitにassert_validが欲しいのです。 内容としては

sub_test_case "#demand_complete" do
  setup do
    @user = User.find_by_id(1)
    login_as @user
  end

  sub_test_case "ご意見ご感想の送信成功" do
    test "ユーザのHOMEにリダイレクト" do
      post "demand_complete", :demand => {:comment => "感想です"}
      assert assigns[:demand].valid?
      assert_redirected_to top_path
    end
  end
end

この、assert assigns[:demand].valid?の部分なのですが、 結果がtrueかfalseしか出てこないので、わざわざerrorsの中身をみる必要がでてくるので テストに手間がかかるのです。こんな感じにしか見えません。 これではなぜvalidじゃないかがわからないのです。

Failure: <false> is not true.
test: ユーザのHOMEにリダイレクト(UsersControllerTest::#demand_complete::ご意見ご感想の送信成功)
test/functional/users_controller_test.rb:339:in `block (3 levels) in <class:UsersControllerTest>'
     336:     sub_test_case "ご意見ご感想の送信成功" do
     337:       test "ユーザのHOMEにリダイレクト" do
     338:         post "demand_complete", :demand => {:comment => ""}
  => 339:         assert assigns[:demand].valid?
     340:         assert_redirected_to top_path
     341:       end
     342:     end

今は知らないけど、昔のrspecには.should be_validとかあるようです。 まあ、rspecはおいといて、assert_validを用意して、validじゃない場合は errorsの中身を表示したい。というわけで、test_helperに定義してみます。 assert_nilあたりを参考にして、errorsの中身を表示するようにしてみます。

def assert_valid(object, message="")
  full_message = build_message(message, <<EOT, object.errors)
<?>
expected to be not valid.
EOT
  assert_block(full_message) { object.valid? }
end

このように定義しておいて、

test "ユーザのHOMEにリダイレクト" do
  post "demand_complete", :demand => {:comment => ""}
  assert_valid assigns[:demand]
  assert_redirected_to top_path
end

結果は

Failure:
  <#<ActiveModel::Errors:0x007fc49cc142c0
   @base=
    #<Demand id: nil, user_id: 1, name: "ラビックス タロウ1", email: "sample+0@example.com", comment: "", deleted_at: nil, created_at: nil, updated_at: nil>,
   @messages={:comment=>["を入力してください"]}>>
  expected to be not valid.
test: ユーザのHOMEにリダイレクト(UsersControllerTest::#demand_complete::ご意見ご感想の送信成功)
test/test_helper.rb:38:in `assert_valid'
test/functional/users_controller_test.rb:339:in `block (3 levels) in <class:UsersControllerTest>'
     336:     sub_test_case "ご意見ご感想の送信成功" do
     337:       test "ユーザのHOMEにリダイレクト" do
     338:         post "demand_complete", :demand => {:comment => ""}
  => 339:         assert_valid assigns[:demand]
     340:         assert_redirected_to top_path
     341:       end
     342:     end

こんな結果になりました。 test_helperの行が出てくるのですが、消し方を調べるのがめんどかったので、 とりあえず放置で。誰か知っていたら教えて下さい。

旅費comというサイトを作りました

先日、秋田で私が開発して管理している旅費comというサービスの紹介をしてきたので、 こちらでも紹介することにしました。

どこ?

旅費com になります。

なにこれ?

このサービスは旅費精算書を作成、それなりにきれいに印刷するシステムです。

f:id:xibbar:20170624121219p:plain

こんな感じで出てくるので、あとは印刷して、精算すればいいだけになります。

旅費精算書を作成するのが面倒だと感じている私こと id:xibbar が、出張の日当や宿泊費、交通費を、領収書ではなく、旅費精算書で精算するするための書類作りを助けてくれるツールです。

f:id:xibbar:20170624121630p:plain

こんな感じで入力した画面を印刷すると、先程の印刷になります。

どんなメリットがあるの?

日当や宿泊費、交通費の精算が楽になります。

f:id:xibbar:20170624122531p:plain

f:id:xibbar:20170624122537p:plain

どうやって使うの?

  • 法人しか使えません
  • 旅費規定を作ります
  • 旅費comで書類を作成します
  • 6名以上の場合は有料です

リンク

会社を15年続けた感想

5月末日にて、会社の15期が終わりました。 思い出しながら社長としての苦しさがどうなっていったかを書いてみます。

迷わなくなった

技術者 or 社長 ?

会社をやりはじめて、3年目に初めてのスタッフを雇いました。 これから、しばらく迷いました。

私が技術者としてやっていくのか、社長としてやっていくのか どっちもとれるのか、どっちつかずになってしまうんじゃないか。 迷いがありました。

さて、どうなったかというと、やっぱり両方とることにしました。 40歳になったし、好きに仕事をしていきたい。 やりたいことって何だんだろうと思うと、 自社サービスで、成功したいということがあります。 おそらく、社長じゃないとできないし、技術も持っていたい。 さくらインターネットの田中社長みたいな感じでしょうか。

結局、結論は変わらないのですが、これについては悩まなくなりました。

私が社長でいいのか?

似ているようで違う迷いもありました。 それは、社長として相応しいのかどうかです。 リーダーシップとは何なのでしょう。 少なくとも、私が自分でリーダーシップがあると思ったことは皆無で、 小学校の時に放送委員長をやったときが最後で、 それ以降、何かのリーダーたるものをやったことは一度もありませんでした。

さて、その結果、この迷いはどうなったのでしょうか。

私が思うには、こんな社長もいていいじゃないの。です。 とりあえず続いているということは、ダメ社長ではないんだろうと。 みんなスタッフはついてきてくれます。

自分では最高の社長だとは思っていないものの、 まあ、最低の社長じゃないんだろうからいいじゃないの。って感じです。

苦しさに慣れた

売上を上げ続けなければならない

社長というのはプレッシャーがあります。 会社を倒産させるわけにはいきません。 毎年それなりに売上をあげつづけなければなりません。 受託開発が売上の100%だったころは、来月からの仕事をどうするか すごく不安でした。今やっている仕事が終わったら 再来月からの売上がなくなってしまう不安です。

さて、どうしたのかというと、 ストック収入を増やすことにしました。 そのために、自社のサービスを作ることにしました。 現在、「e-安否」「You-OK」「学術集会JP」の3つがあります。 その他、保守の仕事もいくつかあります。 今は毎月の固定売上がそれなりのウェイトを占めます。 そうなると、来月の仕事がなくなったらどうしよう?という 不安はなくなりました。

どうやってお客さんを見つけたらいいかわからない

次に、お客さんの見つけ方がわからないという不安がありました。 私は営業なんて一度もやったことがありませんでした。

Linuxサーバづくりと、RubyPerlを使ったウェブアプリを ちょっとだけできる学生がいきなり会社を立ち上げたもので、 営業の仕方なんてわかりません。 また、飛び込み営業なんて絶対にやりたくありません。 起業してしばらくは人の紹介された仕事ばかりやっていました。 しかし、紹介されなくなったタイミングで会社が終わってしまいます。 最初はたまたまテンポよく仕事できたものの、 仕事が来なくなったらどうしよう。という不安をずっと抱えていました。

この状態を打開するためにどうやったかというと、 ビジネススクールに通ったのが大きかったです。といってもMBAとるようなやつじゃなくて、 もっと現実的なテクニックを学ぶスクールです。 ここで、セールスレターの書き方を学びました。 また、想像していた形とは全く違う営業の方法を学ぶことが出来ました。 飛び込みをしない営業の基本を学ぶことが出来ました。

結果、どうなったか

結果、ストック収入を増やし、営業の仕方を学び、 また受注の仕事も同じところから何度もくるようになり、 売上をあげつづけるプレッシャーも減っていきました。

もちろん、プレッシャーがなくなったということはないのですが、 半分はなくなり、半分は慣れてしまい、苦しさは減りました。

おわりに

今はみんな楽しい。でも、時間は足りなくて死にそうです。

15年というのはそれなりに修羅場をくぐって生き残った会社だけが 到達できる場所だと思っています。短くはありません。 大分走り続けてきた気がしますが、気がついたら15年でした。

15年も会社を続けさせてくれたみんなに感謝します。 40歳になった時はどういう人生なんだろうと想像していました。 そしたら、思っていたときよりも楽しい人生が待っていました。

おわり。

Sierraでruby-buildで1.8.7をビルドする

今更ながらrbenv使ってRuby-1.8.7をインストールすべく、 ruby-buildで1.8.7をインストールしようとしたところ、 次のようなエラーが出ました。

ERROR: This package must be compiled with GCC, but ruby-build couldn't
find a suitable `gcc` executable on your system. Please install GCC
and try again.

DETAILS: Apple no longer includes the official GCC compiler with Xcode
as of version 4.2. Instead, the `gcc` executable is a symlink to
`llvm-gcc`, a modified version of GCC which outputs LLVM bytecode.

For most programs the `llvm-gcc` compiler works fine. However,
versions of Ruby older than 1.9.3-p125 are incompatible with
`llvm-gcc`. To build older versions of Ruby you must have the official
GCC compiler installed on your system.

TO FIX THE PROBLEM: Install Homebrew's apple-gcc42 package with this
command: brew tap homebrew/dupes ; brew install apple-gcc42

You will need to install the official GCC compiler to build older
versions of Ruby even if you have installed Apple's Command Line Tools
for Xcode package. The Command Line Tools for Xcode package only
includes `llvm-gcc`.

BUILD FAILED (OS X 10.12.4 using ruby-build 20170405-2-g3b15693)

素直にbrewapple-gcc42を入れようとして、brew install apple-gcc42したところ、 今度は次のようなエラーになりました。

% brew install apple-gcc42
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (caskroom/cask).
No changes to formulae.

apple-gcc42: This formula either does not compile or function as expected on macOS
versions newer than Mavericks due to an upstream incompatibility.
Error: An unsatisfied requirement failed this build.

むーん、なんでこんな状態になっているんだろうと思いつつ、 Xcodegccで1.8.7-p374をコンパイルしてみたところ、 warningはたくさん出るものの、コンパイルできてしまいました。 なので、ruby-buildを改良してSierraだったらXcodegccを使って コンパイルするようにしたパッチが以下です。

--- a/bin/ruby-build
+++ b/bin/ruby-build
@@ -761,6 +761,12 @@ require_java7() {
 require_gcc() {
   local gcc="$(locate_gcc || true)"

+  local osx_version="$(osx_version)"
+  if [ $osx_version = "1012" ]; then
+    return 0
+  fi
+
+
   if [ -z "$gcc" ]; then
     { echo
       colorize 1 "ERROR"

この状態にして、opensslとreadlineとtkのオプションを渡してインストールします。 brewであらかじめopensslとreadlineを入れておいて、

% CONFIGURE_OPTS="--with-readline-dir=/usr/local --with-openssl-dir=`brew --prefix openssl`" RUBY_CONFIGURE_OPTS="--with-openssl-dir=`brew --prefix openssl`" rbenv install 1.8.7-p374

ふう。なんとかインストールできました。

Downloading ruby-1.8.7-p374.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p374.tar.bz2
Installing ruby-1.8.7-p374...

WARNING: ruby-1.8.7-p374 is past its end of life and is now unsupported.
It no longer receives bug fixes or critical security updates.

ruby-build: use readline from homebrew
Installed ruby-1.8.7-p374 to /Users/fujioka/.rbenv/versions/1.8.7-p374

Downloading rubygems-1.6.2.tgz...
-> https://dqw8nmjcqpjn7.cloudfront.net/cb5261818b931b5ea2cb54bc1d583c47823543fcf9682f0d6298849091c1cea7
Installing rubygems-1.6.2...
Installed rubygems-1.6.2 to /Users/fujioka/.rbenv/versions/1.8.7-p374

さくらのVPSの標準OSのubuntuにはファイアウォール設定が入っている

久しぶりにさくらのVPSを使うことになり、ubuntu 16.04を入れて、 apache2を入れてみたところ、ブラウザからアクセスできない。 これは変だと思って、次の手順で探ってみた。

  • apache2のログを見てみたところ、アクセスログはない。
  • tcpdump port 80で見たところ、パケットは到達している。

はて?何かデフォルトが変わったか。 ここまででネットワークかファイアウォールがあやしいと思った。 カスタムインストールを使ってubuntu16.04をインストールしてみたところ、 普通にアクセスできる。あれれれ? ここまでで、OSをなんとかすればつながるということがわかった。 というわけで元の標準OSのubuntu16.04を入れ直し、 iptables -Lを見たところ、ガッツリ入っている。これか。。。。

root@web3:~# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
f2b-sshd   tcp  --  anywhere             anywhere             multiport dports ssh
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain f2b-sshd (1 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere

なんでインストール直後なのにこんなに入っているの? と思い、ufwかと思ったら、ufwのChainではなかった。 次にiptables-persistentかと思ったら、インストールされていない。

grep -r iptables /etc | grep -v fail2ban

を実行してみたところ、

root@web3:~# grep -r iptables /etc | grep -v fail2ban
/etc/default/ufw:# only enable if using iptables backend
/etc/network/if-pre-up.d/iptables:iptables-restore < /etc/iptables/iptables.rules
/etc/init/ufw.conf:# The Uncomplicated Firewall is a front-end for iptables, to make managing a

むむむ。なんだこのif-pre-up.dの設定は。

dpkg -S /etc/network/if-pre-up.d/iptables

を実行しても、パッケージにないとおっしゃる。これはどこから湧いてきたのか。 さくらVPSのイメージで勝手にやっているのか??? /etc/iptables/iptables.rulesの中身は次のようになっていた。

root@web3:~# cat /etc/iptables/iptables.rules
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

とりあえず、改造しないとやっていけないので、設定を変更する。 せっかくなので削除せずに使うことにする。

-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT

この次の行に追加する。

-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT

これでapache2へのアクセスができるようになる。

sh /etc/network/if-pre-up.d/iptables

こちらのコマンドで再読込。 iptables -L で見てみると、

root@web3:~# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:http
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:https
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

となっていて、httpとhttpsが追加されていました。 これで良い方法なのかどうかはわかっていないのですが、とりあえずできました。

ポテンシャルがあるかどうかを判断する必要なんてないんじゃないか?

定期的に読んでいるブログに面白いことが書いてありました。

blog.tinect.jp

年末の12月、Windowsタブレットアプリを外注しました。 弊社、ソフトウェアの製作を外注したのははじめてです。 もちろんクラウドワークスを使いました。 そこで数名が手を上げてきたのですが、卒業間際の大学生がいて、 Unityで提案してきて、なかなか感心したのでこちらの学生に頼みました。

他の方と違ってgithubも普通に使うし、sqlite3を使うという条件も グダグダ言わなかったし、slackでの会話も問題なかったので気に入ったためです。 コミュニケーションのとり方をこちらに全部合わせてもらえるのは助かります。

卒論が重なっていて、こちらの準備不足もあって、 1月に完成予定が2月上旬になってしまったのですが、予定が延びたのはお互い様でしたし、 それ以外は全然問題もおきませんでした。 この学生さんにはトータル35万円の開発費を支払いました。 卒業前のアルバイトとしてはなかなか良いものではないでしょうかね。 彼はもうすでにUnityでゲームを作れるレベルでしたので、どこでもやっていけるでしょう。 とても感心しました。

さて、ポテンシャル採用から実績採用へというブログのタイトルです。 実は学生というのは遊びきる学生もいますが、そうじゃない学生もいます。 学生時代とは、なんらかの実績を積んでおくというのが 無限にできる期間でもあります。このような学生と出会えて、 ますますデキる人とデキない人の差が広がってきているんだなと痛感しました。 私も出来る人であり続けるように努力しないとと思った次第です。

先日、小学校卒業間際の息子に「パパ~、僕、パパみたいにプログラム作れるようになるかな〜?」 と聞かれたので、「ならないと思うよ。」とバッサリ返してしまいました。 「だって、お前、もう中学生だろ。作れる人はすでにもう作っているよ。」 プログラムを作れる人はそんな質問しないですね。 作りたい人はすでに本読んだりネット見たりして作り始めています。 その後、息子がiPhoneアプリの作り方の本が欲しいようだったので 買い与えたところ、ちょっとずつ作ってみているようです。

私に「お前はプログラムを作れるようにはならないよ。」と言われたのが大分ショックだったようで、 少しづつ目標に近づく努力をはじめたようです。 最初に「変数というのは何か?」みたいな質問が出てきて、おお!っと思いました。 何も動かずに、プログラムを将来作れるようになれるかと悩むより100倍増しです。

いつかなれると思っているだけの人は永遠になれない。 すでに目標に向かって動き始めている人しか望みを掴めないと思った次第でした。

さて、表題にもどってみると、技術職において、こいつは伸びそうだとか判断する必要なんて まったくなくて、会社が個人を教育してくれる時代なんてとっくに終わりました。 新卒も中途と同様に、何をしてきたかを見れば判断できます。 そういう意味で、ますます技術職の格差も広がってきているんだなと思いました。

イタリア旅行10日目

この日はもう帰国です。

ローマからは電車で空港まで移動します。チケットの買い方とかなかなか緊張したけど、 無事空港までつけました。全部ビジネスクラスなので、ラウンジが使えます。 とりあえず、食う。

f:id:xibbar:20161231081219j:plain

ルフトハンザもビジネスクラスなのでメシが出ます。しかし、短距離路線のビジネスクラスはマジでしょぼい。

f:id:xibbar:20161231153558j:plain

ローマからミュンヘンの便の中で日本時間の年越しを迎えました。その瞬間の記念撮影。

f:id:xibbar:20161231160000j:plain

ミュンヘンからはANA便です。やっぱりANAビジネスクラスは最高です。 メシもいいし。蕎麦がちょっとだけあったのが 年越しそばを食べていない私には嬉しかったなぁ。

f:id:xibbar:20161231225436j:plain f:id:xibbar:20161231230422j:plain

ってことで、だいぶ疲れましたが、イタリア旅行楽しかったです。

子どもが大きくなって時間に余裕ができたら夫婦で行きたいものです。

ちなみに、このあと羽田空港から小松行きに乗り換えて、 家内の実家に帰省するというまだ旅は終わらないみたいなことをしていました。

夜中に目が覚めて、朝の3時にクリーニングとか行ってましたよ。