エンジニアの越川です。ActiveRecordを拡張するgemを作りたい。そんなときテストで使うダミーのモデルのテーブルをどう作るかに悩みますね。
本格的なRails拡張ではrails pluginコマンドを用いて開発することが多いと思います。その際は自動で作成されるspec/dummy配下のダミーアプリでmigrationを書くのが楽です。
一方そこまで大きくないActiveRecordの拡張ではもっと手軽に書きたいですね。
例として、protectedカラムがtrueのとき、destroyが出来ないようにするActiveRecordの拡張を考えてみましょう。(今回作成したgemは、github.com/ppworks/kienaideに置いてあります。)
- gemの作成手順
- テストの書き方 <-本題はここです
- rubygemsにリリース
と言った流れを見て行きましょう。
gemの作成手順
gemの作成はbundle gemで行います。
bundle gem kienaide
出来上がったディレクトリ配下を見てみましょう。
cd kienaide/
自動的にgitのrepogitoryになっているので状態を確認してみます。
git status
このようなファイルが出来ています。
new file: .gitignore
new file: Gemfile
new file: LICENSE.txt
new file: README.md
new file: Rakefile
new file: kienaide.gemspec
new file: lib/kienaide.rb
new file: lib/kienaide/version.rb
お作法として、この時点でInitial Commitを作成しておきましょう。
git commit -m "Initial commit"
以降はステップごとに、git commitする想定です。
さて、さっそく今回作るgemの依存gemを記述します。ActiveRecordの拡張なのでactiverecordを追加しました。続いて、開発用にテストを書きたいのでrspecとテスト用のデータベースとしてsqlite3を追加しました。
kienaide.gemspec
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]
+ spec.add_dependency "activerecord", ["> 3.0", "< 5.0"]
+ spec.add_development_dependency "rspec", "~> 3.0"
+ spec.add_development_dependency "sqlite3", "~> 1.0"
spec.add_development_dependency "bundler", "~> 1.7"
spec.add_development_dependency "rake", "~> 10.0"
end
次にテスト用のディレクトリを用意します。
mkdir spec
spec_helperは最小限にこんな感じで書いてみました。
spec/spec_helper.rb
require 'bundler/setup' Bundler.require Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } RSpec.configure do end
テストの書き方
本題です。テスト用のデータベースの用意を書きます。ポイントはメモリ上にデータベースを用意することと、Railsのmigrationの仕組みを利用する事です。
spec/support/setup_database.rb
ActiveRecord::Base.configurations = {'test' => {adapter: 'sqlite3', database: ':memory:'}} ActiveRecord::Base.establish_connection :test class CreateAllTables < ActiveRecord::Migration def self.up create_table(:posts) do |t| t.text :content t.boolean :protected end end end ActiveRecord::Migration.verbose = false CreateAllTables.up
メモリ上にDatabaseを用意するところ
{'test' => {adapter: 'sqlite3', database: ':memory:'}}
migrationを実行するところ
ActiveRecord::Migration.verbose = false CreateAllTables.up
がポイントです。こうしたファイルを用意することで手軽に、 テストで使うダミーのモデルのテーブル を用意することが出来ました。
テスト用のデータベースの用意が出来ましたので、テストを書いていきましょう。
protectedカラムがtrueのとき、destroyが出来ないようにするActiveRecordの拡張を作ります。モデル定義に、kienaideと書いておくと、protectedカラムがtrueの場合、destroyをキャンセルするようにしてみます。
spec/kienaide_spec.rb
require 'spec_helper' class Post < ActiveRecord::Base kienaide end RSpec.describe Kienaide do let!(:post) { Post.create(content: 'demo', protected: protected) } after { Post.delete_all } describe '#destroyed?' do before { post.destroy } subject { post } context 'when not protected' do let(:protected) { false } it { is_expected.to be_destroyed } end context 'when protected' do let(:protected) { true } it { is_expected.not_to be_destroyed } end end end
テストを書くことで仕様が決まったので実装していきます。
lib/kienaide.rb
require "kienaide/version"
require "active_record"
module Kienaide
def kienaide
class_eval do
before_destroy do
false if self.protected
end
end
end
end
ActiveRecord::Base.extend Kienaide
テストを通してみましょう。
bundle exec rspec
Kienaide
#destroyed?
when not protected
should be destroyed
when protected
should not be destroyed
Finished in 0.01532 seconds (files took 0.37402 seconds to load)
2 examples, 0 failures
無事通りました。
rubygemsにリリース
リリースに備えて、TODOを書き換えます。
kienaide.gemspec
spec.version = Kienaide::VERSION spec.authors = ["koshikawa"] spec.email = ["koshikawa@ppworks.jp"] - spec.summary = %q{TODO: Write a short summary. Required.} - spec.description = %q{TODO: Write a longer description. Optional.} - spec.homepage = "" + spec.summary = %q{Protect your record} + spec.description = %q{Protect your record easily} + spec.homepage = "http://github.com/ppworks/kienaide" spec.license = "MIT" spec.files = `git ls-files -z`.split("\x0")
gemのパッケージを作成します。
gem build kienaide.gemspec
Successfully built RubyGem Name: kienaide Version: 0.0.1 File: kienaide-0.0.1.gem
rubygemsに登録します。アカウント。お持ちでない場合は、rubygemsの登録画面から登録しておきます。
リリースは以下のように行います。
gem push kienaide-0.0.1.gem
EmailとPasswordを求められたら登録したものを入力して下さい。
Pushing gem to https://rubygems.org... Successfully registered gem: kienaide (0.0.1)
これでgemがrubygemsに登録できました。
いかがだったでしょうか、ActiveRecordの拡張gemを書く際のテストの書き方に迷うこともあると思いますが今回のようなアプローチを使うと手軽にテスト用のデータベースを用意できるので開発が加速すると思います。
今回作成したgemは、github.com/ppworks/kienaideに置いてあります。Pull Requestもお待ちしております:)
最後に
マネーフォワードでは積極的にgemを開発してOSSに貢献していきたいエンジニアを募集しています。 みなさまのご応募お待ちしております!