2014/01/26

Update rails-flog to v1.3.0

rails-flog(github, RubyGems.org) をバージョン 1.3.0 にあげた。

  • バージョン 1.2.0
    一時的にフォーマットを無効にする機能をパラメータとSQL個別に行えるようにした。
    どっちかのフォーマットだけ欲しい人も安心。
  • バージョン 1.3.0
    いくつかのフォーマットを行わないための条件を設定できるようにした。 「キャッシュされたクエリはフォーマットしたくない」とか「時間のかかるクエリだけ調査したいからフォーマットしてほしい」とか「キーが一つしかないパラメータをフォーマットすんなよ。行数増えて余計見づらいわ」みたいな人もニンマリ。
    ただし、デフォルトの挙動が変わっているので注意。

issue や pull request もお気軽にどうぞ

2013/12/29

今開いているファイルの *** をレジスタに

.vimrc にこんなのを書いておくと結構便利だった。
クリップボードと連携しておけば、さらに捗る。

2013/12/08

Redmineのプラグインで既存の文言を上書きする

この情報は Redmine 2.5 で不要になりました。→ tail -f pinzo.log: Redmine 2.5.0 からプラグインでの文言上書きが復活しています

Redmine のプラグインで本体の文言を上書きすることが出来ません。
昔はできたようなのですが、バージョンが違うのか I18n の仕様が変わったのか現在は出来ません。

ja:
  project_module_documents: ドキュメント
  project_module_calendar: 日程表

プラグインの ja.yml にこんな記述をしても画面はかわりません。

通常、プラグインをロードすると、I18n.load_path はこんな状態になります。

$REDMINE_HOME/vendor/bundle/ruby/2.0.0/gems/activesupport-3.2.15/lib/active_support/locale/en.yml
$REDMINE_HOME/vendor/bundle/ruby/2.0.0/gems/activemodel-3.2.15/lib/active_model/locale/en.yml
$REDMINE_HOME/vendor/bundle/ruby/2.0.0/gems/activerecord-3.2.15/lib/active_record/locale/en.yml
$REDMINE_HOME/vendor/bundle/ruby/2.0.0/gems/actionpack-3.2.15/lib/action_view/locale/en.yml
$REDMINE_HOME/plugins/<plugin_name>/config/locales/en.yml
$REDMINE_HOME/plugins/<plugin_name>/config/locales/ja.yml
$REDMINE_HOME/config/locales/ar.yml
$REDMINE_HOME/config/locales/az.yml
$REDMINE_HOME/config/locales/bg.yml
--- 延々と Redmine 本体の言語ファイルが列挙
$REDMINE_HOME/config/locales/vi.yml
$REDMINE_HOME/config/locales/zh-TW.yml
$REDMINE_HOME/config/locales/zh.yml

rails/railties/lib/rails/engine.rb at 3-2-stable · rails/rails にあるように、I18n.load_path の後ろのほうが優先度が高いので、本体の言語ファイルのほうが優先されてしまいプラグイン側で上書きすることができません。 プラグインの登録は config/initializers/30-redmine.rb で行われていて、その際にプラグインの辞書ファイルが I18n.load_path に登録されるのですが、この時点ではアプリケーション本来の辞書ファイルが登録されていないからでしょう。

じゃあどうすればいいのかというと、どこかで I18n.load_path を調整して、プラグインの辞書ファイルを後ろの方にもっていくのがいいのかなと。
確実に行うなら、初期化完了時がよさげですね。
Rails::Engine には after_initialize という目的そのままの機能があるのでこれが使えそうです。

こんなコードを lib あたりに突っ込んでおいて、init.rbrequire すればOK。
I18n.load_path はこんな感じになります。

$REDMINE_HOME/vendor/bundle/ruby/2.0.0/gems/activesupport-3.2.15/lib/active_support/locale/en.yml
$REDMINE_HOME/vendor/bundle/ruby/2.0.0/gems/activemodel-3.2.15/lib/active_model/locale/en.yml
$REDMINE_HOME/vendor/bundle/ruby/2.0.0/gems/activerecord-3.2.15/lib/active_record/locale/en.yml
$REDMINE_HOME/vendor/bundle/ruby/2.0.0/gems/actionpack-3.2.15/lib/action_view/locale/en.yml
$REDMINE_HOME/config/locales/ar.yml
$REDMINE_HOME/config/locales/az.yml
$REDMINE_HOME/config/locales/bg.yml
--- 延々と Redmine 本体の言語ファイルが列挙
$REDMINE_HOME/config/locales/vi.yml
$REDMINE_HOME/config/locales/zh-TW.yml
$REDMINE_HOME/config/locales/zh.yml
$REDMINE_HOME/plugins/<plugin_name>/config/locales/en.yml
$REDMINE_HOME/plugins/<plugin_name>/config/locales/ja.yml

これで、本体の辞書ファイルをプラグインの辞書ファイルで上書きすることができました。

2013/12/07

Railsのログに出力されるパラメータとSQLを整形するgemを作った

最初に

この記事は Ruby on Rails Advent Calendar 2013 - Qiita [キータ] の7日目の記事です。
前日は a_suenami さんの Railsでサービスとフォームを導入してみる話 - assertInstanceOf('Engineer', $a_suenami) です。

本題

こういう gem を作りました。

pinzolo/rails-flog - Github
rails-flog - RubyGems.org

Gemfile に下記を追加して bundle install するだけで、ログに出力されるパラメータとSQLが整形して出力されるようになります。

gem 'rails-flog', :require => 'flog'

Redmine でのスクリーンショットはこんな感じ。

使用前

使用後

Railsアプリケーションに tmp/no-flog.txt を配置すれば一時的に整形をやめることもできます。

残念なところ

  • 実装が結構強引。二重の特異メソッドとかどうなんでしょうね。完全に元の実装依存だし。
  • パラメータはスペース整形だけど、SQLはタブ整形。こいつ のせい。

作った経緯

  1. 先日、西脇.rb & 東灘.rb 合同もくもく会 7th - 西脇.rb & 東灘.rb に参加した時に、@jnchito さんが、色々と awesome_print で出力するWebサービスを作成されてて、その際にログに出力される複雑なパラメータを手作業で整形するのがタルいみたいな事をおっしゃってまして、「あるある」と思っていた。
  2. んで、複雑なSQLもタルいよなー、整形してログに出力させるぐらいならできんじゃね?
  3. anbt-sql-formatter てのがあるじゃない。イケそう。
  4. 誰か作ってんじゃない?と調べてみると Railsのログに出力されるパラメータやSQLを整形する - ( ꒪⌓꒪) ゆるよろ日記 というそのものなものが見つかる。しかも自分でブクマ済み。
  5. もう少し調べてみるとどうやら同等の機能をもつ gem は存在していないみたい。
  6. 作ってみるか。

思うところ

我々エンジニアは誰しも素晴らしいプロダクトやサービスを作りたいと思っていると思います。
そして多くの人が時間、技術力、アイデア、ビジョン等々の不足であきらめているのでしょう。
でもエンジニアの本質は「素晴らしい物を生み出す」よりも、「一歩進める」ことだと思っています。
ひとが考えもしない方向へ一歩進められたり、一歩がとっても大きい人が素晴らしいプロダクトやサービスを生み出せるのでしょう。
出来なかったことをできるようにしたり、自動化したり、簡略化したり、みんな一歩進めた結果です。
rails-flogも、アイデアも実装手段も他の巨人に乗っかったものですが、gemにするという一歩だけ進めることが出来ました。
一歩進めるだけなら誰にでもできるでしょう、さああなたも身近なものを一歩進めてみてください。

Next

明日は znz さんです。

2013/11/28

Coverallsで特定のファイルのみ集計対象にする

なにか作って Github に置く場合、基本的に Travis と Coveralls を利用している。
Coveralls を利用するのは簡単で、基本的には下記の手順で問題ない。

  1. coveralls の gem をインストールする
  2. .coveralls.yml を作成
  3. spec_helper などの最初に require "coveralls" して Coveralls.wear! する
  4. push する

とはいえ、これだとテストでロードされた全てのファイルが対象になってしまう。
全てのファイルが対象になるとスペックファイルの fail とか、lib に突っ込んだ外部ライブラリとかも対象になってしまい、永久に 100% にならない。

それは困るので調べてみたら、ちゃんと公式に書いてあった
なるほど、フォーマッタだけ Coveralls のを使用すればいいのね。

こんな感じ。

ちょっと、個人的に直感的じゃないなと思うのは、add_filter の引数がパスに含まれているファイルやブロックにて true を返すファイルを除外するというところ。
フィルタなんだから、マッチするものだけを対象にするかと思ったら逆なんだな。

2013/11/23

Redmine のプラグインを Travis で CI してみた

Redmine のプラグインの場合、プラグイン本体のみ Github に登録しているので、そのままでは Travis で CI することができない。
諦めていたんだけど、.travis.yml のオプションとにらめっこしたらなんとなく出来そうな気がしたので試してみた。
10数回の試行を経て、なんとか出来たのでスクリプトを紹介します。

  • .travis.yml
    before_install があるので、after_install があるかと思ったらなかった。

  • before_install.sh
    gem インストール前に実行させるスクリプト。
    Travis では bundle install 前に直下の GemfileBUNDLE_GEMFILE 環境変数に登録されてしまう。
    しかし、指定したいのはプラグインの Gemfile ではなく、Redmine のものなのである。
    なので、mv しまくりでなんとかディレクトリ構成を整えた。苦労した。
    Redmine のダウンロード URL がバージョンだけに依存してくれないのが少し残念。

  • exec_test.sh
    テスト実行用スクリプト。
    前述のとおり after_install がなかったので、bundle install 後の処理(Redmineの初期化など)とテストの実行を同時にすることにした。
    こちらはそんなに苦労しなかった。

これで、プラグインを複数バージョンの Ruby でテストすることができるようになった。
でも、複数バージョンの Redmine でテストすることは当然できない。
複数バージョンの Redmine を対象にテストするなら Jenkins 使うのがいいんだろうな。

2013/11/06

OS X Mavericks にすると gcc-4.2 がなくなるらしい

bundle installしたらエラーになった。

pinzolo@ileach [master] % bundle install --path vendor/bundle
Fetching gem metadata from https://rubygems.org/......... Fetching gem metadata>from https://rubygems.org/.. Resolving dependencies... Using rake (10.1.0) Using i18n (0.6.5) Using minitest (4.7.5) Using multi_json (1.8.2) Installing atomic (1.1.14) Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension. /Users/pinzolo/.rbenv/versions/2.0.0-p195/bin/ruby extconf.rb *** extconf.rb failed *** Could not create Makefile due to some reason, probably lack of necessary libraries and/or headers. Check the mkmf.log file for more details. You may need configuration options. Provided configuration options: --with-opt-dir --without-opt-dir --with-opt-include --without-opt-include=${opt-dir}/include --with-opt-lib --without-opt-lib=${opt-dir}/lib --with-make-prog --without-make-prog --srcdir=. --curdir --ruby=/Users/pinzolo/.rbenv/versions/2.0.0-p195/bin/ruby --with-atomic_reference-dir --without-atomic_reference-dir --with-atomic_reference-include --without-atomic_reference-include=${atomic_reference-dir}/include --with-atomic_reference-lib --without-atomic_reference-lib=${atomic_reference-dir}/ /Users/pinzolo/.rbenv/versions/2.0.0-p195/lib/ruby/2.0.0/mkmf.rb:431:in `try_do': The compiler failed to generate an executable file. (RuntimeError) You have to install development tools first. from /Users/pinzolo/.rbenv/versions/2.0.0-p195/lib/ruby/2.0.0/mkmf.rb:516:in `try_link0' from /Users/pinzolo/.rbenv/versions/2.0.0-p195/lib/ruby/2.0.0/mkmf.rb:814:in `try_run' from extconf.rb:26:in `
' Gem files will remain installed in /Users/pinzolo/projects/detox/vendor/bundle/ruby/2.0.0/gems/atomic-1.1.14 for inspection. Results logged to /Users/pinzolo/projects/detox/vendor/bundle/ruby/2.0.0/gems/atomic-1.1.14/ext/gem_make.out An error occurred while installing atomic (1.1.14), and Bundler cannot continue. Make sure that `gem install atomic -v '1.1.14'` succeeds before bundling.

mkmf.log見ろって言われたので見てみる。

pinzolo@ileach [master] % cat vendor/bundle/ruby/2.0.0/gems/atomic-1.1.14/ext/mkmf.log
"gcc-4.2 -o conftest -I/Users/pinzolo/.rbenv/versions/2.0.0-p195/include/ruby-2.0.0/x86_64-darwin12.4.0 -I/Users/pinzolo/.rbenv/versions/2.0.0-p195/include/ruby-2.0.0/ruby/backward -I/Users/pinzolo/.rbenv/versions/2.0.0-p195/include/ruby-2.0.0 -I. -I'/Users/pinzolo/.rbenv/versions/2.0.0-p195/include' -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -Wno-error=shorten-64-to-32 -fno-common -pipe conftest.c -L. -L/Users/pinzolo/.rbenv/versions/2.0.0-p195/lib -L. -L'/Users/pinzolo/.rbenv/versions/2.0.0-p195/lib' -lruby.2.0.0 -lpthread -ldl -lobjc " sh: gcc-4.2: command not found checked program was: /* begin */ 1: #include "ruby.h" 2: 3: int main(int argc, char **argv) 4: { 5: return 0; 6: } /* end */
gcc-4.2がないらしい。

どうやら Mavericks にしたら、gcc-4.2gccになるらしい。

sudo ln -s /usr/bin/gcc /usr/bin/gcc-4.2したら、解決した。

2013/09/08

RedmineのプラグインをRSpecでテストする

Redmineは基本的にはxUnitなコードでテストが書かれています。
今のところ例に習いxUnit形式でテスト書いていたんだけど、RSpecで書きたいなという欲求は当然あるわけです。
なので今回RSpecを導入してみた。

まずは、$REDMINE/plugins/<plugin_name>/Gemfile を作成して、bundle install

# Gemfile
group :development, :test do
  gem "rspec-rails", ">= 2.8.1"
end

$REDMINE/plugins/<plugin_name>/spec/spec_helper.rbを作成し、設定を記述。

require File.expand_path(File.dirname(__FILE__) + '/../../../spec/spec_helper')
RSpec.configure do |config|
  config.mock_with :mocha
  config.fixture_path = "#{::Rails.root}/test/fixtures"
end

各種specファイルの冒頭で spec_helper をrequireする。

require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
# require 'spec_helper' ではダメだった。

基本的にはこれで設定はいいはずだけど、なぜかspecタスクで実行できない。
実行できないというよりspecファイルが見つけられないらしい。
rspec コマンドを指定しても不可能。
ベースディレクトリを指定してやれば実行できた。

$ bundle exec rake spec                             # ダメ
$ bundle exec rspec                                 # これもダメ
$ bundle exec rake spec plugins/<plugin_name>/spec  # これでもダメ
$ bundle exec rspec plugins/<plugin_name>/spec      # これはOK

2013/08/20

[#nshgrb]西脇.rb & 東灘.rb もくもく会 6th と Kobe Rubyist Meetup に参加してきました

8/17に西脇.rb & 東灘.rb もくもく会 6th と Kobe Rubyist Meetup に続けて参加してきました。
いつも Kyoto.rb に参加してくださってる @spring_aki さんから、宣伝があったのと、SonicGarden の人が来るというのと、コードレビューつきもくもく会に興味があったので、新快速で一時間ほど揺られて行ってきました。

作ったもの

redmine_yare という簡単な Redmine のプラグインを作りました。
最近プライベートで Redmine のプラグインを作っているので、勉強がてらということととりあえず今回はもくもく会の中で完結するものを作りたかったので、シンプルなものにした。
画面遷移する度に今日が期限のチケットをダイアログ表示する非常に迷惑なプラグインです。

苦労したところ

フックのロジックとビューを分離するところが苦労した。
コレについてのまとめは後日に別エントリであげます。

もくもく会の感想

意外と3時間というのは短くて思ったより実装が進まなかった。調査に時間がかかったというのもあるけれど。結構時間を無駄に使っていたと思う。その都度しっかり意思決定していればもっと効率的な進め方が出来たと思う。
コードレビューでは、自分のコードはコード量自体が少なくてあまり突っ込まれなかった。(スペルミスしたけど)
気になったのは、レビューイと限られた人がメインでしゃべっている感じだったので、もっと全員でコードレビューしている感じがでるといいなと思う。(一人15分だし、スキルや経験の差があるのでしかたのないこととは思うが)

Meetup

懇親会はやっているけど、規模を拡大して Meetup は初の試みだったそうだ。
やっぱり酒が入って話しやすくなってくると濃い話が自然発生するのが楽しい。
正規表現の話や、Railsのコントリビュータの体験談などの話を酒を聞けるのは貴重な機会だった。

今後

特性上、大人数で行えないタイプの勉強会なので毎回参加というのは難しいとは思うが、また参加したいなと思う。
今回の ProMotion のお話のように、他者に新しい体験を提供できるようなネタがあればいいんだけど、しばらくは難しいかもな。Redmine のプラグインを頑張らねば。

西脇.rb と東灘.rb の皆様お疲れ様でした。

2013/08/01

Redmine plugin にて自動ロード対象のディレクトリを追加するには

どうやら Redmine はプラグインの lib は自動的にロードパスに登録するが、app 以下は controllers, models, helpers のみを autoload の対象にするようだ。
lib/redmine/plugin.rb にこんな記述があった。

例えば、フォームクラスを作って app/forms に配置したい場合は、init.rb に処理を追加してやる必要がある。 一つしか追加しないなら simple の方でいいだろうし、複数追加するなら plugin.rb をパクって multiple で書くのがいいんじゃないかな。