詳しくはブログ記事の「Rails4でエンタープライズなActiveRecordモデルを作るための6のステップ」にまとめたので、Qiitaには要約(というかほとんどコード)をまとめておきます。
くわしくはブログ記事の方をご覧ください。
1. モデルは階層化する
$ rails g model Blog::User name:string profile:text
$ rails g model Blog::Post user:references permalink:string title:string content:text
2. DB制約を追加する
class CreateBlogPosts < ActiveRecord::Migration
def change
create_table :blog_posts do |t|
t.references :user, index: true, null: false
t.string :permalink, null: false, limit: 64
t.string :title, null: false, limit: 128
t.text :content, null: false
t.timestamps
end
add_index :blog_posts, :permalink, unique: true
add_foreign_key :blog_posts, :blog_users, column: :user_id
end
end
3. validationを追加する
class Blog::Post < ActiveRecord::Base
belongs_to :user
validates :permalink, presence: true, uniqueness: true, length: {maximum: 64}
validates :title, presence: true, length: {maximum: 128}
validates :content, presence: true
end
4. FactoryGirlを定義する
FactoryGirl.define do
factory :blog_post, class: 'Blog::Post' do
user
sequence(:permalink) { |n| "permalink_#{n}" }
title "title"
content "content"
end
end
5. カスタムマッチャを追加する
Rails4のモデル用カスタムマッチャの以下のカスタムマッチャを追加します。
have_not_null_constraint_onマッチャ
データベースのNOT NULL制約をテストします
have_unique_constraint_onマッチャ
データベースのUNIQUE制約をテストします
have_foreign_key_constraint_onマッチャ
データベースの外部キー制約をテストします
create_modelマッチャ
FactoryGirlでのモデル生成をテストします
safely_validate_uniqueness_ofマッチャ
InvalidForeignKeyエラーにならないようにuniqueness validationをテストします
6. FactorGirl, Association, Validation, DB制約をテストする
describe Blog::Post, type: :model do
subject { build(:blog_post) }
context 'with FactoryGirl' do
it { should create_model }
it { should create_model.for(2).times } #uniqueなオブジェクトを生成することを確認
end
context 'with associations' do
it { should belong_to(:user) }
end
context 'with validations' do
it { should validate_presence_of(:user_id) }
it { should validate_presence_of(:permalink) }
it { should validate_presence_of(:title) }
it { should validate_presence_of(:content) }
it { should ensure_length_of(:permalink).is_at_most(64) }
it { should ensure_length_of(:title).is_at_most(128) }
it { should safely_validate_uniqueness_of(:permalink) }
end
context 'with DB' do
it { should have_not_null_constraint_on(:user_id) }
it { should have_not_null_constraint_on(:permalink) }
it { should have_not_null_constraint_on(:title) }
it { should have_not_null_constraint_on(:content) }
it { should have_unique_constraint_on(:permalink) }
it { should have_foreign_key_constraint_on(:user_id) }
end
end