宝石
ruby 1.9.3
rails 3.2.11
devise 2.2.3
acts_as_tenant 0.2.9
コード
私のすべてのモデルは、domain_id によってスコープが設定されています。
class User < ActiveRecord::Base
acts_as_tenant(:domain)
#...
end
次に、application_controller で、ドメインから現在のテナントを設定します。
class ApplicationController < ActionController::Base
set_current_tenant_through_filter
before_filter :set_tenant
protect_from_forgery
#...
def set_tenant
#...
@domain = Domain.find_or_create_by_name(request.host)
set_current_tenant(@domain)
end
end
セッションを除くすべてのモデルですべてがうまく機能します。ページが読み込まれるたびに、別のテナントでページを読み込んだ最初のユーザーがログアウトされます。このページを読み込むと、[...など] に最初にログインしたユーザーがログアウトされます。
仮説: Alice がドメインにアクセスすると、Rails は current_tenant=alice_domain を読み込みます (OK)。ボブが別のドメインにアクセスするまで、すべてが期待どおりに機能し、current_tenant=bob_domain をロードします。Alice がページを更新すると、Rails にはまだ current_tenant==bob_domain があります。Rails はセッションをチェックします: Alice は bob_domain スコープで存在しないため、Devise は Alice を強制的にログアウトさせます。次に、application_controller が current_tenant=alice_domain を設定し、Bob をログアウトします。
汚い回避策:ユーザーモデルでacts_as_tenantを使用せず、すべてのコントローラーで自分自身をドメインでユーザーをスコープし、ドメインでログインと登録をスコープするようにdeviseを上書きします。また、Devise にセッション内の現在のドメインを認識させる方法がわかりません。ちなみに、acts_as_tenant を user で手動の default_scope に置き換えると、同じ奇妙なバグに陥ります。この道を行くのはとても汚いようです。
私は何日もの間、きれいな解決策を探しています。どんな助けにもとても感謝しています。