0

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

これはキャッシュの問題を示唆している可能性がありますが、私はここで本当に盲目的に飛んでおり、キャッシュを無効にするという考えが好きではありませんでした.

どんなアイデアでも大歓迎です。また、最終結果を達成するために完全に間違った方法で行っているという提案にもオープンです。

乾杯、

カイル。

4

2 に答える 2

0

それは面白い。ソースは次のとおりです。

  def schema_search_path=(schema_csv)
    if schema_csv
      execute("SET search_path TO #{schema_csv}", 'SCHEMA')
      @schema_search_path = schema_csv
    end
  end

これら2つのステートメントがまったく同じものに評価される必要があることを考えると、それは問題ではありません。id.to_s を括弧で囲んでみましたか?

于 2013-03-17T22:21:50.277 に答える
0

あなたの問題は、スキーマ名が数字で始まることだと思います。ハッシュをスキーマ名として使用していた同様の問題がありました。解決策は次のとおりです。

ActiveRecord::Base.connection.schema_search_path = %{"#{workspace.id}", public}

これ%{}は、文字列自体で実際の引用符を使用できるように文字列を定義する別の方法です。

それが役立つことを願っています:D

于 2013-07-19T08:53:16.230 に答える