Activerecord Rails 3.2-PgTools set_search_path无法从助手方法工作 更新日期:8/8/2012

Activerecord Rails 3.2-PgTools set_search_path无法从助手方法工作 更新日期:8/8/2012,activerecord,ruby-on-rails-3.2,multi-tenant,Activerecord,Ruby On Rails 3.2,Multi Tenant,我已经缩小了问题的范围 这条线有效 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 = ["11", "public"].join(",")
但这条线不行

ActiveRecord::Base.connection.schema_search_path = [workspace.id.to_s, "public"].join(",")
即使workspace.id==11

需要明确的是,“workspace.id”不会在循环的每次迭代中都得到更新。请注意,这仅适用于ActiveRecord::Base.connection.schema\u search\u 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中编写了一个helper方法来创建下拉列表。我觉得这是一个很好的地方,因为它必须显示在每一页上。在这个helper方法中,我必须设置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
正如你所看到的,搜索路径从未改变,我也不知道为什么。模块方法显然是可访问的,因为“当前搜索路径”方法工作良好

当我跟踪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
这可能意味着缓存问题,但我在这里真的瞎了眼,不喜欢禁用缓存的想法,因为我不知道这可能会有什么其他影响

欢迎任何意见。我也愿意接受这样的建议,即我完全走错了实现最终结果的道路

干杯


凯尔。

这很有趣。以下是消息来源:

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

考虑到这两个语句的计算结果完全相同,这并不重要。您是否尝试过在id.to_s周围加括号?

我认为您的问题在于模式名称以数字开头。在使用哈希作为模式名时,我遇到了类似的问题。以下是解决方案:

ActiveRecord::Base.connection.schema_search_path = %{"#{workspace.id}", public}
%{}
只是定义字符串的另一种方式,这样您就可以在字符串本身中使用实际的引号


我希望这有帮助:D

与其禁用缓存,不如刷新缓存(我不知道这是什么咒语)?还有,连接池呢?与直接在单个连接上执行SQL不同,您似乎更需要在所有打开的连接上以某种方式执行该语句,并强制对可能被打开的新连接执行该语句。@steve感谢您的回答,但我希望在Rails应用程序的上下文中解决此问题。我不确定您的建议是否可能/可行???也许此Rails pull request 7083可能会有所帮助:
ActiveRecord::Base.connection.schema_search_path = %{"#{workspace.id}", public}