2012 年 8 月 8 日更新
問題を少し絞り込みました...
この行は機能します
ActiveRecord::Base.connection.schema_search_path = ["11", "public"].join(",")
しかし、この行はそうではありません
ActiveRecord::Base.connection.schema_search_path = [workspace.id.to_s, "public"].join(",")
workspace.id == 11 の場合でも
明確にするために、「workspace.id」はループの反復ごとに更新されません。これは ActiveRecord::Base.connection.schema_search_path コマンドにのみ適用されることに注意してください
何か案は?
元の投稿
長々とした投稿で申し訳ありませんが、私は本当に立ち往生しています。
バックグラウンド
PostGreSQL を使用して、Rails でマルチテナント アプリを開発しています。テナントは PG スキーマによって分離されます。テナントが所有する「ワークスペース」の概念があり、「パブリック」スキーマに関連付けられたレコードがあります。
個々のスキーマ (ワークスペース) には、"Projects" テーブルがあります。
すべてのページで、現在のユーザーがアクセスできるワークスペースとプロジェクトのドロップダウン リストを表示したいと考えています。ドロップダウンの簡略版は次のようになります。
Workspace 1
- Project 1a
- Project 1b
Workspace 2
- Project 2a
- Project 2b
- Project 2c
...
...
Workspace 8
Project 8a
lib/PgTools.rb に次のメソッドがあります
def self.current_search_path
ActiveRecord::Base.connection.select_value "SHOW search_path"
end
def self.set_search_path(name, include_public = true)
path_parts = [name.to_s, ("public" if include_public)].compact
ActiveRecord::Base.connection.schema_search_path = path_parts.join(",")
end
これらのメソッドは、Rails コンソールから使用すると正常に機能するようです。
問題
ドロップダウンを作成するために、application_helper.rb にヘルパー メソッドを記述しました。すべてのページに表示する必要があるため、これを配置するのに適していると考えました。このヘルパー メソッド内で、PG 検索パスを (PgTools.set_search_path を使用して) 設定し、適切なワークスペースのプロジェクトのみが繰り返されるようにする必要があります。しかし、検索パスが正しく設定されていないようです。
関連するコードは以下です
current_user.workspaces.each do |workspace|
html << '<li>' + workspace.name + "</li>"
PgTools.set_search_path(workspace.id) unless Rails.env.test?
html << '<li>Current search_path is ' + PgTools.current_search_path + '</li>' <!-- DEBUG LINE
Project.all.each do |project|
html << "<li>"
html << (link_to '- ' + project.name, edit_project_path(project.id))
html << "</li>"
end
end
出力を表示すると、次のようになります。
Workspace 1
Setting search_path to 10
Current search_path is 10, public
- Project 1a
Workspace 2
Setting search_path to 15
Current search_path is 10, public
- Project 1a
Workspace 3
Setting search_path to 14
Current search_path is 10, public
- Project 1a
ご覧のとおり、検索パスが変更されることはありません。その理由はわかりません。「current_search_path」メソッドが正常に機能するため、モジュール メソッドは明らかにアクセス可能です。
log/development.log を末尾にすると、次の出力が得られます。
Workspace Load (0.6ms) SELECT "workspaces".* FROM "workspaces" INNER JOIN "workspace_memberships" ON "workspaces"."id" = wworkspace_memberships"."workspace_id" WHERE "workspace_memberships"."user_id" = 2 ORDER BY workspaces.name ASC
(0.1ms) SHOW search_path
CACHE (0.0ms) SELECT "projects".* FROM "projects"
CACHE (0.0ms) SHOW search_path
CACHE (0.0ms) SELECT "projects".* FROM "projects"
CACHE (0.0ms) SHOW search_path
CACHE (0.0ms) SELECT "projects".* FROM "projects"
CACHE (0.0ms) SHOW search_path
CACHE (0.0ms) SELECT "projects".* FROM "projects"
CACHE (0.0ms) SHOW search_path
CACHE (0.0ms) SELECT "projects".* FROM "projects"
CACHE (0.0ms) SHOW search_path
CACHE (0.0ms) SELECT "projects".* FROM "projects"
CACHE (0.0ms) SHOW search_path
CACHE (0.0ms) SELECT "projects".* FROM "projects"
CACHE (0.0ms) SHOW search_path
CACHE (0.0ms) SELECT "projects".* FROM "projects"
CACHE (0.0ms) SHOW search_path
これはキャッシュの問題を示唆している可能性がありますが、私はここで本当に盲目的に飛んでおり、キャッシュを無効にするという考えが好きではありませんでした.
どんなアイデアでも大歓迎です。また、最終結果を達成するために完全に間違った方法で行っているという提案にもオープンです。
乾杯、
カイル。