ikaruby

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

Railsで未使用のメソッド削除を支援するEngine(gem)を作った

はじめに

先日のエントリーで、任意のメソッド呼出を監視し、任意のコードを実行するgem「Okuribito」の作成を報告しました。

muramurasan.hatenablog.jp

OkuribitoはRuby単体で動くgemで、元々は未使用のメソッドを安全に削除することを目的に作成したgemです。
が、大抵はRuby単体ではなく、Railsプロジェクトに適用されることが多いのではないかと思います。
そこで、Okuribitoを利用したRails Engineを作れば、メソッド呼出状況の一覧表示・検索などの機能もWebUIで提供できるのではないかと考え、実際に作成してみました。

github.com

このエントリでは、このRails Engineの紹介および使い方の説明をしたいと思います。

OkuribitoRailsとは

OkuribitoRailsはRailsアプリケーションにおけるメソッド呼出状況を監視し、管理(閲覧)できるようにする Rails Engine(gem) です。
言い換えれば、まだ一度も呼び出されていないメソッドを炙り出すことができ、安全にコードからメソッドを削除できるようになると言えます。

その仕組みを実現するため、コア部分の実装は Okuribito を利用しています。
なお、使い方を簡単に説明すると、次のようになっています。

  1. 監視したいメソッドを登録する(yamlを記述し、配置する)
  2. Railsアプリケーションを起動し、運用する。監視対象のメソッド呼出が行われると、DBに情報が格納される
  3. 現在のメソッド呼出状況、メソッド呼出履歴を閲覧する

ひとたび監視したいメソッドを登録すれば、2はgem側でやってくれるので、開発者は 「監視メソッドの設定 → 呼出状況のチェック」というループに注力することができます。

使い方

以下に、Railsチュートリアルのサンプルアプリにおけるメソッド呼出を監視する、という例を通じて、OkuribitoRailsの使い方を説明していきたいと思います。

インストール

まず、Gemfileに次の記述を追加してbundle installします。

gem 'okuribito_rails'

次に、各種設定ファイル配置・書き換えのためのインストールコマンドを実行します。

rails generate okuribito_rails:install

実行すると、以下のタスクが展開されます。

  • OkuribitoRailsが使うmigrationファイルの配置(db/migrate以下)
  • OkuribitoRailsのルーティング追加(config/routes.rbに自動的に追加される)
  • 設定ファイルの配置(config/initializers/okuribito_rails.rb)

migrationの実行

インストールコマンドで追加された分のmigrationを実行します。

rake db:migrate

監視したいメソッドの記述

監視したいメソッドをyamlファイルに記述していきます。(デフォルトの設定では、config/okuribito.ymlにて配置する必要があります)
以下のように、クラス名にネストしてメソッド名を記述していきます。
メソッド名を記述する際は、クオテーションで囲み、それがクラスメソッドなのかインスタンスメソッドなのかのシンボルを記述する必要があります。

User:
  - '#feed'
  - '#profile'
Micropost:
  - '.from_users_followed_by'

設定ファイルの変更(任意)

config/initializers/okuribito_rails.rbはデフォルトで以下の設定になっているので、必要に応じて変更します。

OkuribitoRails.configure do |config|
  config.setting_path = "config/okuribito.yml"
  config.once_detect = true
  config.prohibit_webui = ["test"]
  config.prohibit_observe = ["test"]
end
  • setting_path
    • 監視したいメソッドを記述したyamlのパスを書きます。
  • once_detect
    • trueにすると、メソッド呼び出し検出時の、呼出履歴の登録をRailsアプリケーション起動中に一度だけにします。(DBへinsertするオーバーヘッドを軽減させることができます)
  • prohibit_webui
    • 配列で指定した環境下で、WebUI(メソッド呼び出し状況の閲覧 等)を一切見れなくします。production環境ではWebUIを閉じたい、といった場合に対応することができます。
  • prohibit_observe
    • 配列で指定した環境下で、メソッド呼び出しの監視をしなくなります。staging環境やtest環境ではメソッド呼び出しの監視をしたくない、といった場合に対応することができます。

運用

OkuribitoRailsをインストールしているRailsアプリケーションは、以下の動作をするようになります。

  1. アプリケーション起動時、yamlファイルに記述した監視メソッドをDBに登録する。
  2. アプリケーション実行中、監視メソッドが呼び出されると、その情報をDBに登録する。

こうして蓄積された情報は、WebUIを通じて、それぞれ以下の通り閲覧することができます。

メソッド呼び出し状況の閲覧

(root)/okuribito_rails/method_call_situations にアクセスすると、以下の通り、現在のメソッド呼び出し状況を閲覧することができます。

f:id:muramurasan:20161211194554p:plain

監視中のメソッド一覧が表示され、監視開始日時と、呼出日時を確認することができます。
この例では、User#profileがまだ呼び出されていないことがわかり、今後も未呼出が続くようであれば、コードからメソッドを削除しても良いだろうと判断するこができます。

メソッド呼び出し履歴の閲覧

(root)/okuribito_rails/method_call_logs にアクセスすると、以下の通り、これまでのメソッド呼出履歴を閲覧することができます。

f:id:muramurasan:20161211194606p:plain

呼び出された日時と、その時に呼び出された箇所が記録されているため、どこのコードがまだメソッドを利用しているのか確認することができます。

課題

最低限の機能は作ることができたと思っていますが、使い勝手を良くするために、今後は以下の機能をリリースしたいと考えています。

  • 検索機能
    • メソッド名や、日時を条件に検索(絞り込み)できるようにする機能の提供。
  • メソッド監視日数の表示
    • メソッドの監視開始から経過した日数を表示・検索できるようにする機能の提供。
  • コード内未定義のメソッドを監視対象から排除
    • 上記の条件で、yamlファイルの内容を書き換えるコマンドの提供。
  • 呼出履歴のあるメソッドを監視対象から排除
    • 上記の条件で、yamlファイルの内容を書き換えるコマンドの提供。

おわりに

今回作ったOkuribitoRailsは、Railsアプリケーションにおけるコード整理を助けるRails Engine(gem)です。
コードが汚いのは、ただただ申し訳なさしかありませんが、機能的には有用なものが作れたのではないかと思っています。
使ってみて、もしもバグと思える動作が発生した際は、(詳細を添えて)是非、issue への登録をお願い致します!(もちろん、要望も歓迎します!)
また、機能やコードを改善するPull Requestもお待ちしています!

少しでも「いいね」と思っていただけた方は、是非、リポジトリにStarをつけていただけると幸いです \(^o^)/

LODGEはいいぞ

LODGEはいいぞ。

LODGEとは

東京ガーデンテラスにオープンしたコワーキングスペース
2016年11月にオープンしたばかり。

lodge.yahoo.co.jp

LODGEの何が良いのか

アクセスがいいぞ

最寄駅が永田町、赤坂見附という、東京のど真ん中に立地している。
コワーキングスペースといえば、渋谷や新宿に集中しているイメージがあるが、LODGEはコワーキングスペースがなかなか無いエリアに出現した。
人によっては、渋谷・新宿エリアよりもアクセスが良いのではなかろうか。

もくもくと集中できていいぞ

個人で来た人のために、パーティションで区切られたスペースがある。
この中に入ってしまえば、まさに「俺の基地」って感じがして、もくもくやるのに最高。

f:id:muramurasan:20161218103913j:plain

もちろん、グループで来た人のために、大小様々なテーブルが配置されており、ホワイトボードも豊富にあって、攻守ともにバッチリ。

f:id:muramurasan:20161218103932j:plain

写真は撮っていないが、大型ディスプレイが配置された(予約制の)スペースもあり、やろうと思えばdodosoftの輪読会もできそう。

眺めが良くていいぞ

こもった空間だと、どうしても疲れがたまりやすいもの。
その点、ロッジは開放的な作りになっており、18階という立地を活かした景色も最高。
集中するスペースと、気分を開放させるスペースが同居しており、攻守ともにバッチリ。

f:id:muramurasan:20161218103948j:plain

見ろ、人がゴミのようだ。

f:id:muramurasan:20161218104000j:plain

ハンモックなんかもある。(周りが集中して作業しているから、使うのに度胸が必要だけど)

ウォーターサーバが置いてあっていいぞ

ウォーターサーバが各所に置いてあったり、コーヒーを無料で提供していたりする。
もちろん、自動販売機も同じフロア内にあり、下まで降りればコンビニが向かいにあるので、攻守ともにバッチリ。

おわりに

LODGEはいいぞ。

Rubyで任意のメソッド呼出を検出し、任意のコードを実行できるgemを作った

はじめに

今年8月のエントリーで、任意のメソッド呼出を監視し、任意のコードを実行するgem「Okuribito」の作成を報告しました。

muramurasan.hatenablog.jp

その後、gemの機能や、使われ方の思想が結構変わったので、改めて「Okuribito」の使い方を紹介したいと思います。

Okuribitoとは

Okuribitoは任意のメソッド呼出を監視し、任意のコード実行をできるようにするRubyのgemです。
このgemを使えば、例えば、メソッド呼び出しが行われた際にログファイルに書き出すことや、Slack通知を行えるようにするということができるようになります。
また、yamlファイルによって外から監視メソッドを指定するため、コードをほぼ(※)汚すことがない、というのも本gemの目玉となっております。

※ 監視開始を指示する部分と、任意のコードを記述するブロック部分は、どうしてもコーディングする必要があります

使い方

以下のようなコードにOkuribitoを適用する例を通じて、使い方を説明していきたいと思います。

class TestTarget
  def self.deprecated_self_method
    puts "deprecated_self_method"
  end

  def deprecated_method
    puts "deprecated_method"
  end
end

TestTarget.deprecated_self_method
TestTarget.deprecated_self_method
test1 = TestTarget.new
test2 = TestTarget.new
test1.deprecated_method
test2.deprecated_method

インストール

まず、Gemfileに次の記述を追加してbundle installします。

gem 'okuribito'

監視したいメソッドの記述

監視したいメソッドをyamlファイルに記述し、配置します。
以下のように、クラス名にネストしてメソッド名を記述していきます。
メソッド名を記述する際は、クオテーションで囲み、それがクラスメソッドなのかインスタンスメソッドなのかのシンボルを記述する必要があります。

TestTarget:
  - ".deprecated_self_method"
  - "#deprecated_method"

requireの追加

以下を追記し、コードからOkuribitoを使えるようにしましょう。

require "okuribito"

Okuribitoの適用を記述

以下のように、Okuribitoのインスタンス生成時に、メソッド呼び出し検出時に実行したいコードを記述します。
applyした以降は、Okuribitoによるメソッド呼び出し監視が有効になります。

okuribito = Okuribito::OkuribitoPatch.new(once_detect: true) do |method_name, obj_name, caller_info|
  puts "#{obj_name} #{method_name} #{caller_info[0]}"
end
okuribito.apply("okuribito.yml")

渡す仮引数は以下をサポートしています。

  • method_name:メソッド名を取得できます
  • obj_name:オブジェクトを文字列に変換したものを取得できます
  • caller_info:バックトレース(メソッドの呼び出し履歴)を取得できます
  • class_name:クラス名を取得できます
  • method_symbol:クラスメソッド(.)かインスタンスメソッド(#)かの文字を取得できます

また、Okuribitoのインスタンスを生成する際、以下のオプションをハッシュで指定することができます。

  • once_detect:true の場合、Okuribitoは同じメソッドの2回目以降の呼び出しを無視してくれるようになります

運用

Okuribitoを適用した最終的なコードは以下のようになっているとします。

require "okuribito"

class TestTarget
  def self.deprecated_self_method
    puts "deprecated_self_method"
  end

  def deprecated_method
    puts "deprecated_method"
  end
end

okuribito = Okuribito::OkuribitoPatch.new(once_detect: true) do |method_name, obj_name, caller_info|
  puts "#{obj_name} #{method_name} #{caller_info[0]}"
end
okuribito.apply("okuribito.yml")

TestTarget.deprecated_self_method
TestTarget.deprecated_self_method
test1 = TestTarget.new
test2 = TestTarget.new
test1.deprecated_method
test2.deprecated_method

プログラムを実行すると、TestTarget.deprecated_self_methodTestTarget#deprecated_method の呼び出しがそれぞれ一度だけ検出され、結果、以下のような標準出力が得られます。

TestTarget deprecated_self_method okuribito.rb:18:in `<main>'
deprecated_self_method
deprecated_self_method
#<TestTarget:0x007f9c61c96080> deprecated_method okuribito.rb:22:in `<main>'
deprecated_method
deprecated_method

課題

一通り、欲しい機能は作れたかなと思っています。
が、現状、名前空間に対応していないのが課題です。
後、(自分が把握している範囲で)誰かに使ってもらった訳ではないので、バグがまだあるかもしれない、というのが悩みです。

何で Okuribito って名前なの?

元々、未使用のメソッドを安全に削除するのを支援する目的で作ったgemだからです。
メソッドの最後を看取る......という想いを込めて、Okuribito。

おわりに

周囲に「どんなgemがあると嬉しいか?」というのをヒアリングしながら作ったので、コードの汚さはともかく、機能的には良いモノができたと思っています。
使ってみて、もしもバグと思える動作が発生した際は、issue の登録をお願い致します!(もちろん、要望も歓迎します!)
また、機能やコードを改善するPull Requestもお待ちしています!

少しでも「いいね」と思っていただけた方は、リポジトリにStarをつけていただけると幸いです \(^o^)/

エンジニアの妻と結婚して良かったことと、気をつけていること

本記事は、「妻・夫を愛してるITエンジニア Advent Calendar 2016」の16日目です。

www.adventar.org

惚気話をしていいAdvent Calendarなので、本記事ではエンジニアの妻と結婚して良かったことと、気をつけていることを書いていきたいと思います。

夫婦略歴

  • 夫婦ともに転職を経てのサーバーサイドエンジニア。新卒5年目
  • 出会いはソフトウェア工学の勉強会
  • 結婚して3年目に突入
  • 都内在住だが、お互い実家が遠い(妻:岐阜、夫:北海道)

良かったこと

生活や仕事に理解がある

これが一番大きいかなと思っています。
エンジニアとしての生活は、忙しい時期に波があったり、急な障害対応で遅くまで残らないといけなかったり、そもそも業務外で勉強しないとついていけない世界だったりと、傍目から見るとよくわからない世界です。
そんな生活を、深い説明なしに理解してくれ、時に支えてくれるのは、精神面で大変助けられるものです。
また、業界が一緒ですから、仕事についての相談を互いにすることができます。
今、どんな技術トレンドがあるのか、妻から情報を得られることも少なくありません。

自分の時間と、妻と一緒に過ごす時間を両立できる

休日に異性と出かけるとなると、「楽しいところに連れていかないと....」という脅迫観念が少なからずあると思うのですが、
少なくとも私の妻の場合、「今日は気分転換にコワーキングスペースでもくもく作業やろう!」というのが通じます。
これは「自分の時間を持ちたい」「なるべく妻と一緒の時間を作りたい」という相反する要求が同時に満たせるのですから、何ていうかオススメです。
でも、妻が本当に気分転換したい、と思っている時は、空気を読んで楽しいところに出かけましょう。

やる気スイッチがONされる機会が増える

やる気スイッチとは人それぞれなものですが、私の場合、誰かが近くで頑張っていると「自分も頑張ろう」とスイッチが入ります。
一方、私は本来、さぼることに対して自制の効かない人間なものですから、休日は一日中ごろごろして過ごす、というのが一人暮らし時代はしょっちゅうでした。
それが結婚して二人になると、妻が勉強しようとすると私が触発され、私が勉強しようとすると妻が触発されるという、やる気スイッチの押し合いがなされるようになりました。
もちろん、二人揃ってごろごろ過ごしていることもありますが、そこは逆らわずに休んだ方が良いのかなと思っています。

気をつけていること

できたことを褒める

これは私の妻限定の話かもしれませんが、褒めると喜び、何事に対しても良い結果を出してくれます。(技術的なことに限らず、家事なんかもそうです)
褒めることで妻が成長し、自分にまた良い刺激を与えてくれる。
そんな良い循環が築けているのではないかと思っています。

異性との接触(食事など)に寛容になる

この業界は男性社会ですので、誰かと情報交換しようとすると、その人が男性である、ということがほとんどです。
ですから、男性との接触は、情報交換をする場として必要なものと考えています。
それが彼女にとって必要なものであると信じていますので、異性と食事や飲み会に行くことを私が咎めることはありません。
こう書くと重たい感じに受け取られるかもしれませんが、実際はもっと軽い感じで「いってらっしゃい」としています。

親族との関係を大切にする

親元離れて周囲から理解されにくい生活をしているので、何も意識せずに過ごしていると「大丈夫だろうか?」と心配されることがあります。
(そもそも、もくもく作業デートとか言っている時点で、頭がおかしい)
なので、定期的に実家に帰る、電話をかけるなど、無用なところで心配をかけないような行動が大切だと思っています。
そうしておかないと、せっかくの里帰りの時、私生活について小言をたくさん言われて水を差されるかもしれません。

おわりに

惚気話になったような、なっていないような、よくわからない記事になってしまいましたが、私が言いたいのは「エンジニア夫婦はいいぞ」ということに尽きます。

f:id:muramurasan:20150922114204j:plain

私の妻に限らず、エンジニアは素直な性格の人が多いので、男女問わず、パートナーとしてオススメします。

妻・夫を愛してるITエンジニア Advent Calendar 2016。明日は、masanori_msl さんです。

RailsERDをラップして、yamlファイルに従ってER図を出力するgemを作ってみた

松村 Advent Calendar 2016 の15日目です。 @muramurasan です。

RailsERD

RailsERDという、出力したいModelをオプションで指定して、コマンドラインでER図を出力できるgemがあります。

github.com

Perfect Ruby On Rails という本でも紹介されているgemで、ささっとER図を出力するには非常に強力なgemです。

そんな RailsERD ですが、利用する上で欲しくなってきた機能がありました。
それが、「yamlファイルに記述したModelに従ってER図を出力する」という機能です。

RailsERD単体だと何が困るか

というのも、このRailsERD、毎回コマンドラインでModelを指定して出力するのですが、繰り返し出力することを考えると、手間を感じるのです。
書き捨てのER図ならば、コマンドラインでも良いんですが、実運用を考えると任意のモデル群の図を、複数枚出力したい、モデルが更新されるたびに......ということが想定できます。
例えば、「決済」「カート」「検索」など、ドメイン毎に図を出力したい、かつ、変更があればER図を出力し直したい......といった感じです。

そこで、RailsERDをラップして「yamlファイルに記述したModelに従ってER図を出力する」というgemを作成しました。

FreshERD

前段の説明通り、yamlファイルに記述したModelに従ってER図を出力する、というgemです。
コアの機能は本家RailsERDに依存しており、例えば、最新の rails-erd 1.5 を利用すれば、Railsプロジェクト以外にも適用できたりします。

github.com

前置きはこの辺で、使い方と、実際に使ってみた例を紹介します。

インストール

Gemfileに下記の記述を追加して、bundle install してください。

gem 'fresh_erd'

yamlの記述

Rails Tutorialのプロジェクトを例にyamlを記述してみます。

diagrams:
  tweet:
    - User
    - Micropost
  all:
    - User
    - Micropost
    - Relationship

tweetall の単位でER図が出力されることになります。
このファイルを適当な名前、例えば、fresh_erd.yml という名称で保存しておきます。

実際に使ってみた

以下のように、--inputオプションでyamlのパスを指定し、--outputオプションでER図を出力するフォルダを指定し、コマンドを叩きます。

$ bundle exec fresh_erd --input="fresh_erd.yml" --output="./"

以下が実行結果です。

--- Generate ERD : tweet
Loading application in 'sample_app_rails_4'...
Generating entity-relationship diagram for 4 models...
Diagram saved to './tweet.png'.
--- Generate ERD : all
Loading application in 'sample_app_rails_4'...
Generating entity-relationship diagram for 4 models...
Diagram saved to './all.png'.

以下のようなER図が取得できます。

f:id:muramurasan:20161126192547p:plain

f:id:muramurasan:20161126192553p:plain

以上です!

ちなみにgitのフックと連携して、最新のER図が常にpushされるように......とか妄想しましたが、
やりすぎ感あるのでこの辺に留めておきました。(FreshERDという名前は、この妄想が由来です)