Ruboty を使ってみた
Ruboty 作者の r7kamura さんのエントリを読んで使ってみました。
動かしてみる
gem install ruboty ruboty --generate cd ruboty bundle install
ここまでで Ruboty が動作する状態になります。
bundle exec ruboty
を実行することで、シェル上で動作確認ができます。
bundle exec ruboty Type `exit` or `quit` to end the session. >
ruboty help
を実行すると コマンド一覧が出てくるので、試しに ruboty ping
を実行してみます。
> ruboty help ruboty /help( me)?(?: (?<filter>.+))?\z/i - Show this help message ruboty /ping\z/i - Return PONG to PING ruboty /who am i\?/i - Answer who you are > ruboty ping pong >
pong
が返ってくることが確認できました。
拡張してみる
以下のように、ruboty hello
を実行すると world!!!
が返ってくるように拡張してみます。
Type `exit` or `quit` to end the session. > ruboty hello world!!! >
クラスの追加
Ruboty::Handlers::Base を継承したクラスを作ることで拡張していくことができます。
# ruboty/test.rb module Ruboty module Handlers class Test < Base on( /hello/, # トリガー name: 'say_world', # 実行するメソッド description: 'return "world" to "hello"' # ruboty help で表示される説明文 ) # world!!! を返すメソッド def say_world(message) message.reply('world!!!') end end end end
動作確認
-l ファイル名
をつけることで指定したファイルを読み込ませることができます。
ruboty help
を実行してみると、先ほどのコマンドが追加されていることが確認できます。
bundle exec ruboty -l test.rb Type `exit` or `quit` to end the session. > ruboty help ruboty /hello/ - return "world" to "hello" ruboty /help( me)?(?: (?<filter>.+))?\z/i - Show this help message ruboty /ping\z/i - Return PONG to PING ruboty /who am i\?/i - Answer who you are >
ruboty hello
を実行すると world!!!
が返ってきます。
> ruboty hello world!!! >
RSpec の expect_any_instance_of でハマった
class Test def say_hoge hoge1 = Hoge.new hoge2 = Hoge.new hoge1.say hoge2.say end end class Hoge def say puts 'hoge' end end
こんな感じのクラスがあったとして、 Test#say_hoge で Hoge インスタンスが Hoge#say を1回ずつ実行していることをテストしたいとなったときに、以下のようなテストを書きました。
describe 'Test' do describe '#say_hoge' do it 'Hoge インスタンス は Hoge#say を1回ずつ実行する' do expect_any_instance_of(Hoge).to receive(:say).once test = Test.new test.say_hoge end end end
これを実行してみたところ、落ちてしまいました。
ああ、呼ばれている回数は全インスタンスの合計になるのか、なるほどね!とか思って、以下のように once を twice に変えてみました。
describe 'Test' do describe '#say_hoge' do it 'Hoge インスタンス は Hoge#say を1回ずつ実行する' do expect_any_instance_of(Hoge).to receive(:say).twice # 合計2回実行されるので twice に変えてみた test = Test.new test.say_hoge end end end
これを実行してみたところ、またまた落ちてしまいました。
なぜだと思ってエラーを見てみると、「Hoge#say を hoge2 が実行したんだけど、 hoge1 でもう実行されてるよ」 的なことが書いてありました。
1) Test #say_hoge Hoge instance call Hoge#say once Failure/Error: hoge2.say The message 'say' was received by #<Hoge:70248456891000 > but has already been received by #<Hoge:0x007fc7fca35518>
ためしに、以下のように hoge2.say を消して、 twice を once に戻してみました。
class Test def say_hoge hoge1 = Hoge.new hoge2 = Hoge.new hoge1.say # hoge2.say end end
describe 'Test' do describe '#say_hoge' do it 'Hoge インスタンス は Hoge#say を1回ずつ実行する' do expect_any_instance_of(Hoge).to receive(:say).once test = Test.new test.say_hoge end end end
これを実行すると、ちゃんと通りました。
わかったこと
おそらく、 expect_any_instance_of はどのインスタンスも対象にとるが、対象のインスタンスは1つに限るということなのだと思います。
どうするか
そのため、stub を使って Hoge.new でつくられるインスタンスを同じにして、そのインスタンスの Hoge#say が合計2回呼ばれるということをテストすることにしました。
class Test def say_hoge hoge1 = Hoge.new hoge2 = Hoge.new hoge1.say hoge2.say end end
describe 'Test' do describe '#say_hoge' do it 'Hoge インスタンス は Hoge#say を1回ずつ実行する (合計2回) ' do hoge = Hoge.new allow(Hoge).to receive(:new).and_return(hoge) expect(hoge).to receive(:say).twice test = Test.new test.say_hoge end end end
これを実行したところ無事通りました。
Finished in 0.01246 seconds (files took 0.42959 seconds to load) 1 example, 0 failures
入社してから早くも1年
先日は入社式があり、一緒に働く新しい仲間がたくさん増えました。
ということは、自分が入社してから早くも1年が経ったということです。
この1年は、とてもとてもあっという間でした。が、とても濃い1年でした。
ちょっと振り返る
自分が入社した時はどんな気持ちだったかなーと思い出してみると、やってやるぞ!!という気持ち半分、不安半分でした。
社会人としてやっていけるかなという、初めての環境に対する当然の不安もありましたが、そもそもエンジニアとしてやっていけるのかなという不安もありました。
自分は、技術的にとても未熟で未熟すぎて未熟で、自信がありませんでした。
どれくらい未熟だったかというと、社長に「技術的に不安だったよ〜」と直接言っていただけるくらいです。
いざ入社してみると、会社の先輩はもちろんなのですが、同期がとても優秀だったので焦りました。
エンジニア研修で一番最初に、すでに支給されていた PC の開発環境をいろいろ整えといてと言われたのですが、自分はどういったことをすれば良いのか全くわからない中、同期は空き時間に既に終わらせていたのは衝撃は忘れられません。
ちなみにこのときは、研修担当のエンジニアの方に自分だけみっちり教えていただきました。(同期が優秀な話をしようと思ったのに、自分がただただ未熟だったことしか伝わらないですね...)
その後、長い長い充実した研修を通して、技術的なこともたくさん学びましたし、エンジニアのチームでの働き方もたくさん学びました。
そのおかげで、当たり前なのですが、1年前に比べて見違える程になり、現在は先輩エンジニアの方にたくさん教えてもらいながらですが、日々楽しく開発を行えています。
自分で言うのもなんなのですが、めちゃくちゃ成長しました。
本当にこれだけは胸張って言えます。
2年目として
新しく入ったエンジニアの人たちは優秀なので、自分と同じような不安はあまりないとは思いますが、もしそういった不安を抱いているのであれば、
「大丈夫だよ、こんな自分でもちゃんとやっていけているんだから!(良い意味で)」
ということを伝えていけたらなあと思っています。
そんなことを伝えていきつつも、いるだけで成長のできる素晴らしい環境を存分に活かして、これからもどんどん成長していきたいです!
curl のオプション小まとめ
Web API の動作検証をするときに curl を使っているのですが、 そのときに使うオプションについて少しだけ書きます。
本当に少しだけです。
認証ユーザの指定
-u user_name:password
サーバの認証に使用するユーザ名とパスワードを指定できます。
デフォルトでは Basic 認証なのですが、--digest
をつけることで Digest 認証にすることもできます。
リクエストメソッドの指定
-X method
リクエストメソッドを指定できます。
デフォルトは GET
なので、 POST
や DELETE
等を指定したい場合に使用できます。
リクエストパラメータの指定
-d data
リクエストパラメータを渡すことがきます。
このオプションを指定するとリクエストメソッドが POST
として扱われるので、 それ以外を指定したい場合は -X
で指定する必要があります。
data の指定方法
-d "name=don&age=20"
key=value
のように指定します。
&
で区切ることで複数のパラメータを渡すことができます。
-d "user[name]=don&user[age]=20"
のように指定することで、入れ子になったパラメータを渡すこともできます。
Rubyのブロックをメソッド間で受け渡す
ブロックとは
ブロックについてはこちらの記事が分かりやすかったです。
ブロックを引数にとるメソッドの定義
定義方法は、ブロックを引数にとることを明示する or しないの2通りがあります。
メソッドを呼び出したときの実行結果は同じです。
明示する
# 定義 def hoge_method(&block) block.call # ブロックの実行 end # 呼び出し hoge_method do puts 'hello world' end => hello world
明示しない
# 定義 def fuga_method yield # ブロックの実行 end # 呼び出し fuga_method do puts 'hello world' end => hello world
以下では明示する方法で記述していきます。
引数をとるブロックを渡す
ブロックを受け取るメソッドの中でいろいろ処理を行い、その結果をブロックで使用したい場合があると思います。
そういったときには、ブロックが引数をとるようにし、ブロックの実行時に処理結果を渡すようにします。
# 定義 def sample_method(&block) result = 'hello' # 処理 result << ' world' # 処理 block.call(result) # ブロックに result が渡される end # 呼び出し sample_method do |message| puts message # result の中身が message に入る end => hello world
ブロックを引数にとるメソッドを 別のメソッドで呼び出す
こういったことをしたい場合には以下のようにします。
少し複雑な気がしますが、ブロックを受け取って下へ下へと渡すだけです。
# 定義 def hoge_method(&block) # ブロックを引数にとるメソッドを呼び出すメソッド fuga_method(&block) # ブロックを渡す end def fuga_method(&block) # ブロックを引数にとるメソッド result = 'hello' result << ' world' block.call(result) end # 呼び出し hoge_method do |message| puts message end => hello world
この場合には yield
を使った方法では記述できないと思います。
( hoge_method
が受け取ったブロックを fuga_method
の呼び出し時に渡すことを明示する必要があるため。 )
間違ってたらごめんなさい。
ちなみに、
&block
の &
がブロックを Proc オブジェクトに変換しているようなので、 fuga_method
に Proc オブジェクトを渡すようにしても書けます。
Proc オブジェクトに変換されていることの確認
irb(main):001:0> def hoge_method(&block) irb(main):002:1> puts block.class irb(main):003:1> end => :hoge_method irb(main):004:0> hoge_method {} Proc => nil
Proc オブジェクトを渡すようにする
# 定義 def hoge_method(&block) # Proc オブジェクトを引数にとるメソッドを呼び出すメソッド fuga_method(block) # Proc オブジェクトを渡す end def fuga_method(block) # Proc オブジェクトを引数にとるメソッド message = 'hello' message << ' world' block.call(message) end # 呼び出し hoge_method do |message| puts message end => hello world
プルリクのコメントは大事
先日投稿した 大きいプルリクはつらい というエントリで、レビュー側の負担を少なする術を書きましたが、その続編を書きます。これも自戒の意を込めています。
コメントを残す
PR を見ればコードの diff が分かるので、どんな変更を加えられたのか、その変更によりサービスの挙動がどのように変更されたのかが分かります。
ですが、その内容によっては、なぜその変更が必要なのか、その変更により何が幸せになるのか分かりづらいことがあります。一般的な機能の追加等であれば、そりゃ便利になるよねと理解できるかもしれませんが、そうでないことがあることをを意識する必要があります。
また、コードを書いたものにしか分かりづらい情報、例えば、マジックナンバを使用した際には、何故マジックナンバで良いのかといった情報もコメントとして残すべきです。
PR での変更点以外のコードをいろいろ探ったり、PR を出した人に聞けば分かることかもしれませんが、コードの調査には時間がかかりますし、聞く場合も遠距離で開発している場合にはなかなか難しいこともあります。
さらに、分かりづらい PR の場合は、レビュー側も「分かりづらいから時間のあるときにレビューしよう」というように考えてしまうと思うので、開発自体のスピードが低下してしまうかもしれません。
そのため、あらかじめコメントを記述しておくようにしておくべきです。
コミットメッセージには意味を持たせる
コミットメッセージは、変更点の記述にしないようにすべきです。
コミットの diff を見ればどんな変更が加えられたのかは分かるので、XXXの変更 というメッセージは意味のない情報になってしまいます。
こちらも、コメント同様に、なぜその変更をしたのかや、その変更でどうなるのかを記述するようにすべきです。
最近これらができていないことがあったりしたので書きました。
こういったことを意識して、円滑に開発を進めたい!!
大きいプルリクはつらい
チームで開発をする場合、 GitHub 等のサービスを利用してコードを管理することが多いと思います。 既存のコードを変更する際は、GitHub であればプルリクを出して、他の開発者にレビューをしてもらい OK が出ればマージするといったフローが生じます。 レビューにより、複数の視点からコードが吟味され、一人では気づかなかった点に気づくことができます。
つまり、この「他の開発者にレビューをもらい OK が出れば」 を経ることで、コードの品質が悪くなることを防ぎやすくなります。 さらに、レビューを受ける側の成長にもつながります。
そのため、開発においてレビューはとても大事な存在です。
レビューは大変
レビューには時間がかかるし、見落としもしてはいけないので集中力も必要になり、大変と思う方が多いと思います。
小さいプルリクであればまだ良いのですが、大きいプルリクの場合は、変更点が複雑になり全体を把握しづらくなりますし、集中力が持たずにつらくなってしまいます。
そのため、レビューする側の負担が大きくならないようにする工夫が必要です。
小さいプルリクを出す
工夫としては、変更点が小さくなるように気をつけてプルリクを出すことが効果的かと思います。
そのようにプルリクを出すことで、何を変更したかを把握しやすくなりますし、一回のレビューにかかる時間が短くなり負担を抑えることができます。
気をつけることの例としては、以下が挙げられます。
- ついでの変更をしない。
- 大きくなりそうな場合は、開発まとめブランチを用意する。
- レビューにより修正点が多くなる場合は、再度適した粒度でプルリクを出しなおす。
偉そうに述べましたが、自分もできていなかったので自分への戒めとして書きました。