• 57
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

Rails Advent Calendar 4 日目の記事です。前の日は yaotti さんの rails-shを使って高速railsサブコマンド & rakeタスク実行 でした。こんなんあったんだ。すげぇ、便利。

目次

  1. 素のプラグインを作る
  2. ちょこちょこいじってみる
  3. RSpec でテストしたい
  4. RSpec でテスト(2週目)

素のプラグインを作る

なにはともあれとりあえず簡単なのはひな形を作ってしまうことです。

$ rails plugin new test_plugin

何も動きませんが、とにかくものは出来ました。テストもすでにできています。

$ cd test_plugin
$ bundle exec rake test
Run options: 

# Running tests:

.

Finished tests in 0.577092s, 1.7328 tests/s, 1.7328 assertions/s.

1 tests, 1 assertions, 0 failures, 0 errors, 0 skips

テストが1つ通っています。

あとは基本的に普通の gem と同じように開発していくだけです。

ActiveRecord の拡張や、 ActiveSupport の拡張などは公式の Ruby on Rails Guides: The Basics of Creating Rails Plugins が参考になります。

ちょこちょこいじってみる

さて、せっかくなので何か作ってみようかとも思うのですが、なにを作ったものか……

うまく思いつかなかったので、自作の mount_doc(Github) という簡単な Rails Plugin を参考に話を進めます。

とはいえ、いろいろやっているので、簡単に解説……というのは難しいのですが、さっくり言ってしまえば Rails::Engine をいじっているというしかありません。

実際の Rails アプリケーションも Rails::Engine を継承した Rails::Application クラスになっていたりするのですが、Rails::Engine を継承したクラスを用意することで、 Rails アプリケーションにマウントできるようになります。

結構フィーリングで書いたり、作った時に調べた資料を失念していたりで詳しく解説出来ないので、ここはまた今度、 Rails::Engine の歩き方とでも題してブログにまとめようかとおもいます。

RSpec でテストしたい

標準のテストは TestUnit でできており、RSpec のぬるま湯になれきった僕にはちょっと辛いものがあります。

標準のテストは test/dummy 以下にダミーの Rails アプリケーションが配置されており、便利にテストをすることが出来るのですが、今回は RSpec を使いたいので使いません。

TestUnit を使わずに RSpec でテストをする場合は、プラグインを作成する際にコマンドライン引数を足します。

$ rails plugin new rspec_test_plugin -T

これで TestUnit を含まないプラグインのひな形が完成します。

次は Gemfile いじり。RSpec を追加します。

diff --git rspec_test_plugin.gemspec rspec_test_plugin.gemspec
index b5933ad..a9653bf 100644
--- rspec_test_plugin.gemspec
+++ rspec_test_plugin.gemspec
@@ -18,4 +18,5 @@ Gem::Specification.new do |s|
   s.add_dependency "rails", "~> 3.2.8"

   s.add_development_dependency "sqlite3"
+  s.add_development_dependency "rspec"
 end

編集したら次のコマンド

$ bundle install
$ bundle exec rspec --init

これで spec/spec_helper.rb.rspec が出来ました。あとはいつもするようにテストを書くだけです。

RSpec でテストしたい(2週目)

標準の TestUnit には Rails アプリがついてるのに RSpec だとついてない!テストしづらい!というあなた向け。

何のことはない、普通の Rails アプリケーションをテストするくらいの気楽さでやればいいのです。

どんどん行きましょう。

$ mkdir -p spec/dummy
$ cd spec/dummy
$ rails new "app_$(bundle exec rails -v | sed -e 's/Rails //')" -T

さて、これで app_3.2.8 というフォルダの中にテストがない Rails アプリができたはずです(3.2.8 はお使いの Rails のバージョンに適宜読み替えてください)。

なぜ Rails のバージョンをわざわざつけたかは後で解説します。

お次は rspec_test_plugin.gemspec です。

diff --git a/rspec_test_plugin.gemspec b/rspec_test_plugin.gemspec
index b5933ad..fe455db 100644
--- a/rspec_test_plugin.gemspec
+++ b/rspec_test_plugin.gemspec
@@ -18,4 +18,6 @@ Gem::Specification.new do |s|
   s.add_dependency "rails", "~> 3.2.8"

   s.add_development_dependency "sqlite3"
   s.add_development_dependency "rspec"
+  s.add_development_dependency "rspec-rails"
 end

足したら

$ bundle install

次は spec/spec_helper.rb を編集します。

diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index dbc4f1a..d54b6ba 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -4,6 +4,17 @@
 # loaded once.
 #
 # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
+
+ENV['RAILS_VERSION'] ||= `bundle exec rails -v | sed -e 's/Rails //g'`.strip
+ENV['RAILS_VERSION']
+
+ENV['RAILS_ENV'] ||= 'test'
+require File.expand_path(
+  "../dummy/app_#{ENV['RAILS_VERSION']}/config/environment",
+  __FILE__)
+require 'rspec/rails'
+require 'rspec/autorun'
+
 RSpec.configure do |config|
   config.treat_symbols_as_metadata_keys_with_true_values = true
   config.run_all_when_everything_filtered = true
@@ -14,4 +25,6 @@ RSpec.configure do |config|
   # the seed, which is printed after each run.
   #     --seed 1234
   config.order = 'random'
+
+  config.include ActiveSupport::Testing::Assertions
 end

こうしておくことで環境変数 RAILS_VERSION を切り替えれば複数の Rails でテストを動かす、といった器用な真似ができるようになります。 Travis-CI などで動かすときによいと思います。

最後に spec/dummy/app_3.2.8/Gemfile の編集です。

diff --git a/spec/dummy/app_3.2.8/Gemfile b/spec/dummy/app_3.2.8/Gemfile
index 5367a9a..f186f3c 100644
--- a/spec/dummy/app_3.2.8/Gemfile
+++ b/spec/dummy/app_3.2.8/Gemfile
@@ -2,6 +2,8 @@ source 'https://rubygems.org'

 gem 'rails', '3.2.8'

+gemspec path: File.expand_path('../../../../', __FILE__)
+
 # Bundle edge Rails instead:
 # gem 'rails', :git => 'git://github.com/rails/rails.git'

開発中の gem を読み込ませます。手っ取り早いので gemspec を食わせています。

あとは普通の Rails アプリケーションを RSpec でテストするように書けば万事オーライです。

おわりに

Rails のモンキーパッチを当てたり、共通化できそうな機能や、アウトポートできそうな便利ヘルパーの開発などもあるかとは思います。そんな時に Gem にして公開してしまうのはいいことですし、公開しなくてもこれで Rails Plugin に興味を持っていただいて、

「もしや、これは Rails Plugin 化可能なのでは……?」

などと、常日頃から虎視眈々と機会を探してコードを書くことで、分離しやすい疎結合なコードが書けるようになったりしないかなぁ、などと楽観的なことを考える次第です。

日本人作の Rails Plugin は結構少ない(僕観測)ので、今作れば一躍スターの座に踊り出ることが出来るかもしれません!そうでなくとも会社で Rails を使っているなら、複雑怪奇な Rails::Engine を読み解いた人は重宝されるはずです!

しあわせな Rails Plugin タイムを!