こころがホッコリー

ただイカしたRubyistになりたい人生だった。

paizaで破壊的メソッドの返り値を期待するコードが通るようになっていた

以前、自分のブログの中で、下記の記事を書いていました。

muramurasan.hatenablog.jp

かいつまんで説明します。
paizaという、与えられた問題を解きながらコードを書くことができるサービスがあります。

paiza.jp

paizaのRubyで通らないコードがあった

その中でバグ(仕様?)と思われていたものがありました。
「破壊的メソッドの返り値を期待するコードを書くと、提出時にテストケースが通らない」
というものです。ローカル環境では通るのに、paizaで提出すると通らない....と当時、初学者として頭を悩ませていました。

input = gets.to_s
puts input.chomp![0..-5]

バグ(仕様?)が直っている!

先ほど、たまたま破壊的メソッドの返り値を期待するコードを書いて提出してしまい、
「やってしまった.... orz」
と凹んでいたのですが、なんと、このバグ(仕様?)が修正されていました!!
たまたまかもしれない、と思い、過去記事執筆時の検証に使った問題でも試してみましたが、結果は合格。

paizaの中の方が、本ブログを見ていただいていたかは定かではありませんが、
日々、洗練され続けているサービスは利用していて清々しいものですね。
今後とも使わせていただこうと思います。

Rubyで alias method をチェーンしてフックメソッドを書いてみた(※ ActiveSupport未使用)

しばらくブログを書いていませんでした。 まず最初に近況を3行で書きます。

  • 某TDDBCに参加し、TDD力を付与してもらいました
  • mbed祭りで登壇しました
  • Railsエンジニアになって半年が経ちました

転職して半年経って思うことは、別エントリーで書きます。

Rubyで alias method をチェーンしてフックメソッドを書いてみた

本題です。

実システム運用における使われないメソッド

Ruby(Rails)で実際に使われるシステムを開発をしていて、
「このメソッド、消せると思うんだけど、確信が持てないんだよな〜......」
というのは、よくあるシチュエーションではないでしょうか?

C++のような静的型付け言語では、そのようなメソッドコンパイラが検知してくれるので、気にする必要はありません。
動的型付け言語である Ruby は、このような悩みには目を瞑るしかないのでしょうか? 地道にgrepと目視レビューをしていくしかないのでしょうか?
このあるあるについて、クラウドワークス社のブログで、「方法3. 未使用な何かの削除」として触れられています。

engineer.crowdworks.jp

上記記事では、ActiveSupportalias_method_chain を用いて、任意のメソッドが呼ばれた際にロギングする仕組みを実現しています。
本記事では敢えて、というよりも私の知識不足により、ActiveSupportに頼らずにフックメソッドの実現に挑戦してみます。(alias_methodを駆使しているので、発想的にはalias_method_chainと同じかと思います)

コード

本コードの作成にあたって、下記の記事を参考にさせていただいています。
Ruby でメソッド呼び出しのフック処理を実行する - blog.kymmt.com
Rubyでメソッドの呼び出し直後と終了直後をhookしてログを出力したい - miyohide's blog

実行結果

✗ ruby define_hook_method.rb
hello, world
hook message
foobar
hook message
bar
hook message

既にあるコードを参考にしてとはいえ、初めてメタプログラミングを自分で書きました。

補足

今回の方法はフックメソッドを指定したいクラス内で、モジュールのincludeを必要とする手間があります。
実はActiveSupportを用いると、今回のやり方よりも、もっとスマートに、かつモジュールincludeのコードが不要でやりたいことを実現することができます。
そのコードは、作者が私ではないので本記事では触れませんが、興味のある方は prepentedprepend あたりを使って検討してみてください。

緯度経度を入力値に、2地点間の距離計測をしてくれるAPI(国土地理院提供)をRubyで叩いてみた

GPSで取得した緯度・経度情報から、2点間の距離を割り出したい……」 こんなこと考えたことありませんか?

2点間の距離を計算するための計算式は、検索すれば色々と出てくるのですが、
正直、それを1から実装するのは骨が折れるものです。もっと簡単にできないものでしょうか?

色々調べてみたところ、測量に関する様々なAPI国土地理院から提供されていることがわかりました。
測量計算サイト トップページ

引用:提供されているAPI
①緯度・経度と地心直交座標の相互換算
②距離と方位角の計算
③距離と方向角の計算
④平面直角座標への換算
⑤緯度・経度への換算
世界測地系座標変換(TKY2JGD)
⑦PatchJGD
⑧PatchJGD(標高版)
⑨SemiDynaEXE
ジオイド

今回は、「2地点の緯度経度情報」から「2点間の距離」を割り出したいので、②距離と方位角の計算を使ってみました。 API説明:測量計算プログラム API使用法

書いてみた

Rubyで以下のようなコードを書きました。 レスポンスは、xmlも選択できるのですが、今回はjsonを採用しています。 新宿駅と、渋谷駅の座標を入力値に実験してみましょう。

require 'json'
require 'open-uri'

DISTANCE_API = "http://vldb.gsi.go.jp/sokuchi/surveycalc/surveycalc/bl2st_calc.pl?"

def distance(lat1, lng1, lat2, lng2)
  req_params = {
    outputType: "json",    # 出力タイプ
    ellipsoid:  "bessel",  # 楕円体
    latitude1:  lat1,      # 出発点緯度
    longitude1: lng1,      # 出発点経度
    latitude2:  lat2,      # 到着点緯度
    longitude2: lng2       # 到着点経度
  }
  req_param = req_params.map { |k, v| "#{k}=#{v}" }.join("&")
  result = JSON.parse(open(DISTANCE_API + req_param).read)
  result["OutputData"]["geoLength"]
end

p distance(35.689166, 139.704444, 35.654444, 139.706666)

結果

$ ruby dist.rb
"3857.347"

単位はメートルで返ってきます。以上です!

Mac OS X のターミナルで、矩形選択をする

割と有名な話なのかもしれませんが、Mac OS X のターミナルでは、デフォルトで矩形選択がサポートされています。(筆者の環境、yosemiteで確認)

矩形選択を行うには、commandoption を押しっぱなしにします。
すると、カーソルが長方形選択ツールの形状に変化するので、矩形選択したい部分を指定します。
後は、クリップボードにコピーして、よしなに。

f:id:muramurasan:20160131202230p:plain

SQLのselect文実行結果等で、地味に重宝するので、知っておいて損はないはず。

yieldをミニマムな例で理解しようとしてみた

Rubyを始めて間もない頃、 「yieldが全然わからん……」 という壁にぶち当たることがありました。

当時、親切な同僚から懇切丁寧な説明をいただいたんですが、
いかんせん自分の基礎能力が低すぎて理解が追いつかず、申し訳なさすぎる……。

同僚曰く、 「自分で実装して理解するのが一番早いですよ」
ということで、当時、お題をいただき、見よう見真似で実装してみたものを晒します。

お題

def foo
  # 処理A
  # 処理B
  # 処理C
end

def bar
  # 処理A
  # 処理D
  # 処理C
end  

自分の実装

class YieldSample
  def foo
    common { puts "Label B" }
  end

  def bar
    common { puts "Label D" }
  end

  private
  def common
    puts "Label A"
    yield
    puts "Label C"
  end
end

obj = YieldSample.new
obj.foo
obj.bar

出力結果

Label A
Label B
Label C
Label A
Label D
Label C

考察

上記例は、yield の動きがわかるよう、わざとらしい実装にしています。
コードと出力結果から読み取れるよう、yieldは、
「呼び出し元から渡されたブロックを実行する」
という振る舞いをします。
何を期待するかは、呼び出し元にすべて委ねるんですね。

もっとちゃんと解説している方がいるので、yieldとしっかり向き合いたい方には下記の記事をオススメします。

d.hatena.ne.jp

で、yield使って何が嬉しいの?

「実践的な事例がないとわからないよ!」
「結局、yieldを使って嬉しいことって何があるの?」

という方は、リファクタリングRubyという本の中に登場する、
「6.12 サンドイッチメソッドの抽出」という実例にあたってみて欲しいです。
設計の負債(クローンコード)を、yieldを使って華麗に解決しており、大変勉強になります。

www.amazon.co.jp

本を買うのはちょっと……という方は、下記の記事でも「サンドイッチメソッドの抽出」について触れられているので、どうぞ。

d.hatena.ne.jp