エンジニアの越川です。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に貢献していきたいエンジニアを募集しています。 みなさまのご応募お待ちしております!