估计很多人看到标题都不知道是什么意思
。我也实在想不到比较清晰的标题……
当Rails和PostgreSQL碰到一起时,schema的意思就变得非常模糊了。对Rails而言,schema就是数据库的结构,实际上对大多数的数据库而言也是这样。而PostgreSQL中的schema指的是数据库和数据库对象(表,序列等)中间的一层,我也不知道翻译过来该叫什么,但pgAdmin中把这东西叫“模式”。用过PostgreSQL的同学应该不会陌生。下面的内容中,我会统一地把PostgreSQL中的schema叫做“模式”。
这篇文章,说的就是如何写这么一个迁移文件 -- 在指定的模式中进行操作,如创建表。比如以下代码的作用,就是在project模式下创建users表。
# config/initializers/migration_ext.rb
class CreateProjectTables < ActiveRecord::Migration
def self.up
run_in_schema :project do
create_table :users do |t|
t.string :login
end
end
end
end
这段代码和普通的migration文件没有什么区别,只是在create_table的外层加了一个run_in_schema而已。这样,users表就不是创建在默认的public模式,而是project模式。
run_in_schema在这里做了两件事:
- 如果数据库中没有project模式,则创建project模式。
- 让block中执行的所有操作(建表,执行指定sql语句等)都只影响project模式(这不是绝对的,下面会说明)。
run_in_schema的代码如下:
class ActiveRecord::Migration
def self.run_in_schema(schema, &block)
schema = schema.to_s
# 如果没有该schema,就创建一个
schemas = select_values "SELECT * FROM pg_catalog.pg_namespace WHERE nspname <> 'information_schema' AND nspname NOT LIKE 'pg%'"
execute "CREATE SCHEMA #{schema}" unless schemas.include?(schema)
# 设置一下search_path,让建表操作优先在指定的schema内执行
re = execute "SHOW search_path"
execute "SET search_path TO #{schema}, #{re.result}"
yield
execute "SET search_path TO #{re.result}"
end
end
代码很简单,关键就在于search_path的设置。它把指定的模式(本文例子中的project)放在前面,后面才是原来的search_path。
但这样做有个问题。比如这段代码:
run_in_schema :project do
drop_table :categories
end
这是一个删除categories表的操作。如果此时project模式中没有该表,但public模式中有的话,则会删除public模式下的categories表。原因就在于search_path中还是有public模式,只是搜索顺序靠后了一点。
那修改search_path的时候,只加入project模式不就完了?之所以不这样做,完全是因为schema_migrations这个表。Rails在执行完每一个migration文件后,都会去更新schema_migrations表。如果找不到,就会抛出异常。所以我不得不把原来的search_path加在进去。这个小bug只要稍加注意,还是没什么问题的。如果有同学知道这个问题的解决方法,请赐教。
参考资料
Creating a multi-tenant application using PostgreSQL's schemas and Rails
本来我是想找找Rails中怎么判断数据库中一个模式是否存在的方法的,然后在这篇文章中找到了解决办法,然后发现他设置search_path的思路和我一样,直接取消了我发到原创博客的想法……
分享到:
相关推荐
guardrails-engine-output-schema-validator --help Usage: guardrails-engine-output-schema-validator [options] Options: -V, --version output the version number -s, --stdin Read from stdin -f, --file...
rails-dev-box, 面向 Ruby on Rails 核心开发的虚拟机 用于 Ruby on Rails 核心开发的虚拟机简介注意:这个虚拟机不是为 Rails 应用程序开发而设计的,只是为。 这个项目自动设置开发环境,以便在 Ruby on Rails ...
rails-angular-postgres-and-bootstrap-second-edition 英文原版
rails-exporter-源码.rar
scp rails-passenger-postgres-nginx root@SERVER:/root/rails-passenger-postgres-nginx ssh root@SERVER "./rails-passenger-postgres-nginx app_name db_pass" 如果出现错误“ No PostgreSQL clusters exist ...
rails-documentation-2-0-2
rails-beginner-s-guide是Rails 指导手册,帮组学习了解rails开发
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
awesome-rails-gem-zh_CN, Rails 常用 Gem 列表 - Awesome Rails Gem 中文版
rails-react-components-源码.rar
rails-builds-test-源码.rar
rails-yelp-mvp-源码.rar
rails-development-environment-master.rar
Ruby on Rails 初体验--北大青鸟教师专题讲座PPT 想学Ruby的赶快下载看看。 Ruby--目前最快速开发工具
Ruby on Rails Guides v2 - Ruby on Rails 4.2.5
用于Ruby on Rails核心开发的虚拟机 介绍 请注意,该虚拟机并非为...host $ cd rails-dev-box host $ vagrant up 而已。 安装完成后,您可以使用以下命令访问虚拟机: host $ vagrant ssh Welcome to Ubuntu 20.10
rails-documentation-1-2-1.zip
rails-documentation-1-2-0-rc1.chm
rails-ftw-v0.18-2.1.5-4.1.8.exe用于在windows环境下搭建readmine环境
rails-playlists-源码.rar