1

私は持ってgem devisegem apartmentて、各デバイスのユーザーアカウント用に個別のスキーマを作成するために使用しています。

その号のアパートのドキュメントアドバイスでは、 Rack ミドルウェアを使用してテナントを切り替えることを提案しています。その場合、リクエストに依存するのではなくユーザーに依存するため、(私が知る限り)不可能です。

私のRSpecテストを除いて、すべてうまくいきます。問題は、すべてのテスト データベースが適切にクリーンアップされていないことです (新しく作成されたユーザーのスキーマが削除されません)。少数のテストを実行するとすべてのテストに合格しますが、多くのテストを実行するとFaker::Internet.first_name、既に使用されているユーザー名が生成されます (これは有効ではありません)。

これが私がやった方法です:

アプリ/コントローラー/application_controller.rb

def scope_tenant
  Apartment::Database.switch(current_user.username)
end

app/controllers/albums_controller.rb (アルバムモデルbelong_to :user)

class AlbumsController < ApplicationController
  before_action :authenticate_user! # devise magic
  before_action :scope_tenant

アプリ/モデル/user.rb

after_create :create_schema

private

  def create_schema    
    Apartment::Database.create(self.username)
  end  

これは私が仕様に追加したものです:

仕様/工場/user.rb

FactoryGirl.define do
  factory :user do
    username { Faker::Name.first_name }
    email { Faker::Internet.email("#{username}") }
    password "login_as will not use it anyway"
  end
end

仕様/サポート/auth_helpers.rb

Warden.test_mode!

def login_and_switch_schema(user)
 login_as(user)
 Apartment::Database.switch(user.username)    # for some reason `login_as()` didn't do that by itself
end

仕様/機能/アルバム_spec.rb

feature "Album Pages" do

  given(:user) { create(:user) }
  given(:album) { create(:album) }

  around :each do
    login_and_switch_schema user
  end

  scenario...

私はそれよりもいくつかのテストをjs: true持っているので:

仕様/サポート/database_cleaner.rb

RSpec.configure do |config|

  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
  end

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each, js: true) do
    DatabaseCleaner.strategy = :truncation
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

end

すべてのソースの現在のコミットは、こちらの github で入手できます。

だから..主な質問は、テスト後に各ユーザーのデータベースで作成されたスキーマをきれいにする方法ですか? 他のコメントもよろしくお願いします。よろしくお願いします。

4

2 に答える 2

5

これは、Apartment に固有のものではなく、DatabaseCleaner がデータベースをクリーンアップする方法に関連しています。トランザクションを使用する場合、そのトランザクション内で作成されたスキーマもロールバックされます。残念ながら、トランザクションが機能しないため、機能仕様のために切り詰める必要があります (共有接続の「解決策」を試さないでください。競合状態によるランダムな障害が発生します)。したがって、切り捨てはテーブルを切り捨てるだけで、スキーマをクリーンアップしないため、機能仕様のために、作成されたスキーマが確実に削除されるようにする方法が必要です。

マルチテナントの動作を具体的にテストする機能仕様を分離して、希望どおりに機能することを確認し、それらの仕様で作成されたスキーマを手動でクリーンアップすることをお勧めします。次に、残りの機能仕様については、1 つのテナント内、またはこの場合は 1 つのユーザー内でテストしていると想定します。

Companyこれは、新しいモデルが新しい を作成するテスト スイートで行いますtenant。そのため、複数のテナントに対してその動作をテストし、次に 1 つの会社内で動作する残りの機能についてテストします。そのため、クリーンアップについて心配する必要がなくなり、その 1 つのテナント内のテーブルを切り詰めることができます。Truncate は、持っていない限り、常に現在のテナントのテーブルを切り捨てますexcluded_models

それは役に立ちますか?

于 2014-05-20T00:38:55.570 に答える